23
 
1
# portabled v0.6w
2
3
Self-editing filesystem embedded in a single HTML file.
4
5
The idea, all of the painstaking implementation and the vision by [Oleg Mihailik](mailto:mihailik@gmail.com).
6
See the credits section for the used libraries and respective licences.
7
8
### Outstanding tasks:
9
 * Unifying of all import/export into 'moreDialog'.
10
 * Download/upload for GitHub, GDrive, Dropbox etc.
11
 * Extra power in Chrome app, node-webkit, HTMLA-ie7: I/O to the actual filesystem.
12
 * Delete folder.
13
 * Rename file/folder.
14
 * Saving current position in documents.
15
 * TypeScript extra features: navigate to, search integration, tooltips.
16
 * Sub-domains for TypeScript/JavaScript completion/build contexts.
17
 * Doc handlers in plugins, plugin API and isolation (using iframes with their own 'global' and 'require').
18
 * node.js emulation for plugins and dependencies, allowing non-doc plugins.
19
 * Highlight of **changes** in files.
20
 * Styles and colours (planning for pale seaside 'Whitstable' blue, maybe black theme too).
21
 * Scrollbar to use syntax-highlighted document lines.
22
 * Toast popup/fadeout messages for key events: opening, building, import-export completion.
23
 * Add whole raw TypeScript repository sample.
  • app
    • appRoot
      • PageModel.ts
        module portabled.app.appRoot {
          
          export class PageModel {
        
            private _drive: persistence.Drive = null;
            private _fileTree: portabled.files.FileTree = null;
            private _docHost: docs.DocHost = null;
          
            docHostRegions: docs.types.DocHostRegions = <any>{};
            fileTreeHost: HTMLElement = null;
            flyoutScroller: HTMLElement = null;
            brandingArea: HTMLElement = null;
          
            constructor() {
            }
        
            loadFromDOM(completed: () => void) {
              var fileTree = new portabled.files.FileTree(this.fileTreeHost);
        
              app.loading('Initializing caches...');
        
              var uniqueKey = this._getUniqueKey();
              var domTimestamp = fileTree.timestamp;
        
              var mountedDriveCallback: persistence.mountDrive.Callback = mountedDrive => {
        
                  app.loading('Initialising document host...');
                  var docHost = new docs.DocHost(
                      this.docHostRegions,
                      mountedDrive);
        
                  // everything loaded, now assign to state
                  this._fileTree = fileTree;
                  this._docHost = docHost;
                  this._drive = mountedDrive;
        
                  this._fileTree.selectedFile.subscribe(newSelectedFile => this._docHost.show(newSelectedFile));
        
                  if (this._fileTree.selectedFile()) {
                    app.loading('Opening...');
                    this._docHost.show(this._fileTree.selectedFile());
                  }
        
                  var readmeMD = this._drive.read('/readme.md');
                	if (readmeMD) {
                    if (!this._fileTree.selectedFile()) {
                      app.loading('Opening readme...');
                      this._fileTree.selectedFile('/readme.md');
                    }
        
                    var readmeHTML = marked(readmeMD);
                    if (this.brandingArea && 'innerHTML' in this.brandingArea)
                      this.brandingArea.innerHTML = readmeHTML;
                  }
        
                  build.processTemplate.mainDrive = mountedDrive;
        
                  completed();
        
              };
        
              mountedDriveCallback.progress = (current, total) => {
                app.loading('Retrieving cached files: ' + current + ' of ' + total + '...');
              };
              
        
              persistence.mountDrive(
                fileTree,
                uniqueKey,
                domTimestamp,
                persistence.defaultPersistenceModules(),
                mountedDriveCallback);
            }
        
            keydown(unused, e: KeyboardEvent) {
              if (e.keyCode === 220 || e.which === 220 // Ctrl+O
                || e.keyCode === 79 || e.which === 79) { // Ctrl+N
                if (e.ctrlKey || e.altKey || e.metaKey) {
                  this.moreClick();
                  return;
                }
              }
        
              if ((e.keyCode || e.which) === 66) { // Ctrl+B, Alt+B
                if (e.ctrlKey || e.altKey || e.metaKey) {
                  this.buildClick();
                  return;
                }
              }
        
              if ((e.keyCode || e.which) === 82) { // Alt+R
                if (e.altKey) {
                  var allFiles = this._drive.files();
                  var deleteFiles = allFiles;
        
                  if (this._fileTree.selectedFile()) {
                    var currentFile = files.normalizePath(this._fileTree.selectedFile());
                    var lastSlash = currentFile.lastIndexOf('/');
                    var parentDir = currentFile.slice(0, lastSlash+1);
        
                    deleteFiles = [];
                    for (var i = 0; i < allFiles.length; i++) {
                      if (allFiles[i].indexOf(parentDir) === 0)
                        deleteFiles.push(allFiles[i]);
                    }
                  }
        
                  if (confirm('Delete '+deleteFiles.length+' files' + (parentDir ? ' at '+parentDir : '') +' out of ' + allFiles.length + '?')) {
                    for (var i = 0; i < deleteFiles.length; i++) {
                      this._drive.write(deleteFiles[i], null);
                    }
                    
                    alert(deleteFiles.length + ' files deleted.');
                  }
                  return;
                }
              }
              
              /*
              if (typeof console !== 'undefined'
                  && typeof console.log === 'function') {
                console.log('key '+e.keyCode);
              }
              */
        
              return true;
            }
          
            thickbarMouseDown(unused, e: MouseEvent) {
              dragScrollMouseDown(e, this.flyoutScroller);
            }
        
            moreClick() {
              
              if (!this._fileTree)
                return;
              
              var currentSelectedText = '';
              var moreDlg = new moreDialog.Model(
                this._fileTree.selectedFile(),
                currentSelectedText,
                this._drive,
                typedFilename => { 
                  document.body.removeChild(div);
                  if (!typedFilename)
                    return;
        
                  var newFile = files.normalizePath(typedFilename);
        
                  if (this._drive.read(newFile) === null) {
                    this._drive.write(newFile, '');
                    this._docHost.add(newFile);
                  }
        
                  this._fileTree.selectedFile(newFile);
                });
        
              var div = document.createElement('div');
              document.body.appendChild(div);
              ko.applyBindingsToNode(div, { template: { name: 'MoreDialogView' } }, moreDlg);
              moreDlg.connectToDOM();
            }
          
            deleteClick() {
              
              var removeFile = this._fileTree.selectedFile();
              if (!removeFile)
                return;
              
              if (!confirm('Remove file\n  ' + removeFile + '  ?'))
                return;
              
              this._drive.write(removeFile, null);
              this._docHost.remove(removeFile);
            }
          
            private _getUniqueKey() {
              var key = window.location.pathname;
        
              key = key.split('?')[0];
              key = key.split('#')[0];
        
              key = key.toLowerCase();
        
              var ignoreSuffix = '/index.html';
        
              if (key.length > ignoreSuffix.length && key.slice(key.length - ignoreSuffix.length) === ignoreSuffix)
                key = key.slice(0, key.length - ignoreSuffix.length);
              
              if (key.charAt(0) === '/')
                key = key.slice(1);
              if (key.charAt(key.length - 1) === '/')
                key = key.slice(0, key.length - 1);
        
              if (window.location.port === 'blob:') {
                var pts = key.split('/');
                key = pts[pts.length - 1];
              }
        
              var hashedKey =
                  murmurhash2_32_gc(key, 2523).toString() + '-' +
                  murmurhash2_32_gc(key.slice(1), 45632).toString(); // a naive (stupid) way to reduce collisions
        
              return key;
            }
        
            buildClick() { 
              var file = this._fileTree.selectedFile();
              
              buildUI.runBuild(file, this._drive);
            }
        
            exportAllHTML() {
              importExport.exportAllHTML();
            }
        
            commitToGitHub() {
              var gitHubURL = document.body.getAttribute('data-github-url');
        
              if (/.github\.io$/.test(window.location.hostname.toLowerCase()))
                gitHubURL = window.location + '';
        
              if (!gitHubURL) {
                gitHubURL = prompt('GitHub URL');
                if (!gitHubURL)
                  return;
                
                document.body.setAttribute('data-github-url', gitHubURL);
              }
        
              if (gitHubURL.toLowerCase().indexOf('https://') ===0)
                gitHubURL = gitHubURL.slice('https://'.length);
              else if (gitHubURL.toLowerCase().indexOf('http://') == 0)
                gitHubURL = gitHubURL.slice('http://'.length);
        
              var gitHubURLParts = gitHubURL.split('/');
        
              // TODO: support both GitHub pages as well as browse URLs
              if (!/.github\.io$/.test(gitHubURLParts[0].toLowerCase())) {
                alert('not a GitHub URL');
                return;
              }
              if (gitHubURLParts.length < 2) {
                alert('not full GitHub URL (with the file name)');
                return;
              }
              
              var message = prompt('Commit message');
              if (!message)
                return;
        
              var user = gitHubURLParts[0].slice(0, gitHubURLParts[0].length - '.github.io'.length);
        
              var repo = gitHubURLParts[1];
              
              var path = gitHubURLParts.length === 2 ? 'index.html' : gitHubURLParts.slice(3).join('/');
              
              
              function commitViaJSAPI() {
        //        var gh = new Github();
        //        gh.Repo;
              }
              
              var xhr = new XMLHttpRequest();
              xhr.withCredentials = true;
              xhr.open('PUT', 'https://api.github.com/repos/'+user+'/'+repo+'/contents/'+path);
              xhr.onreadystatechange = () => {
                if (xhr.readyState == 4 && xhr.status == 200) {
                  var resultJSON = typeof xhr.response === 'string' ? JSON.parse(xhr.response) : xhr.response;
                  if (!resultJSON) {
                    alert('GitHub did not respond well.');
                    return;
                  }
                  
                  console.log(resultJSON);
                }
              };
              xhr.onerror = (err) => {
                alert('GitHub reject: ' + err.message);
              };
              
              var req = JSON.stringify({
                "path": path,
                "message": message,
                "content": '<!doctype html>' + document.documentElement.outerHTML
              });
              
              xhr.send(req);
            }
        
            exportAllZIP() {
              importExport.exportAllZIP(this._drive);
            }
          
            exportCurrentFile() {
              var selectedFile = this._fileTree.selectedFile();
              if (selectedFile)
                return;
              
              var simpleFileParts = selectedFile.split('/');
              var simpleFile = simpleFileParts[simpleFileParts.length - 1];
              
              importExport.exportBlob(simpleFile, [this._drive.read(selectedFile)]);
            }
        
            importText() {
              this._importSingeFile(
                (fileReader, file) => fileReader.readAsText(file),
                null);
            }
        
            importBase64() {
              this._importSingeFile(
                (fileReader, file) => fileReader.readAsArrayBuffer(file),
                text => {
                  alert('Base64 encoding is not implemented.');
                  return text;
                });
            }
        
            private _importSingeFile(requestLoad: (fileReader: FileReader, file: File) => void, convertText: (raw: string) => string) {
              importExport.importSingleFileWithConfirmation(
                requestLoad,
                file => this._drive.read(file),
                (saveName, data) => {
                  if (this._drive.read(saveName)) {
                    this._docHost.remove(saveName);
                  }
        
                  this._drive.write(saveName, data);
                  
                  this._drive.read(saveName);
                  this._docHost.add(saveName);
                  
                  this._fileTree.selectedFile(saveName);
                },
                convertText);
            }
        
            importZIP() {
              importExport.importZIPWithConfirmation(this._drive);
            }
          
            importPortabledHTML() {
              importExport.importPortabledHTMLWithConfirmation(this._drive);
            }
        
        
          }
          
        }
      • dragScroll.ts
        module portabled.app.appRoot {
          
          export function dragScrollMouseDown(e: MouseEvent, scroller: HTMLElement) {
            var start = e.clientX;
            var startScroll = scroller.scrollLeft;
            var move = (e: MouseEvent) => {
              var offset = e.clientX - start;
              scroller.scrollLeft = startScroll - offset;
            };
            var up = (e: MouseEvent) => {
              removeEventListener(window, 'mousemove', move);
              removeEventListener(window, 'mouseup', up);
              if (scroller.releaseCapture) {
                scroller.releaseCapture();
                removeEventListener(scroller, 'mousemove', move);
                removeEventListener(scroller, 'mouseup', up);
              }
            };
            if (scroller.setCapture) {
              scroller.setCapture(true);
              addEventListener(scroller, 'mousemove', move);
              addEventListener(scroller, 'mouseup', up);
            }
            addEventListener(window, 'mousemove', move);
            addEventListener(window, 'mouseup', up);
          }
          
        }
    • buildUI
      • runBuild.ts
        module portabled.app.buildUI {
          
          export function runBuild(file: string, drive: persistence.Drive) {
            
            var resolvedFile = files.normalizePath(file) || '';
            var template: string;
        
            if (/\.htm(l?)$/g.test(resolvedFile)) {
              template = drive.read(resolvedFile);
            }
            else {
              while (true) {
                var slashPos = resolvedFile.lastIndexOf('/');
                if (slashPos < 0) break;
        
                resolvedFile = resolvedFile.slice(0, slashPos);
                var testFile;
                if ((template = drive.read(testFile = resolvedFile + '/index.html'))
                  || (template = drive.read(testFile = resolvedFile + '/index.htm'))) {
                  resolvedFile = testFile;
                  break;
                }
              }
            }
            
            if (!template) {
              // cannot find HTML template
              alert('Cannot build ' + file);
              return;
            }
        
            var blankWindow = window.open('', '_blank' + dateNow());
        
            var pollUntil = dateNow() + 1000;
        
            while (dateNow() < pollUntil) {
              try {
                var blankWindowDoc = blankWindow.document;
              }
              catch (error) { }
            }
        
            if (!blankWindowDoc) {
              alert('Cannot open a window to host the built document');
              return;
            }
        
            blankWindow.document.open();
            blankWindow.document.write([
              '<html><title>Building ' + resolvedFile + '...</title>',
              '<style>',
              'html, body { background: black; color: green; }',
              'h2 { font-weight: 100; width: 40%; position: fixed; font-size: 200%; }',
              'pre { width: 50%; padding-left: 50%; opacity: 1; transition: opacity 1s; }',
              '</style>',
              '<h2>Building ' + resolvedFile + '</h2>',
              '<' + 's' + 'cript>',
              'var textContentProp = "textContent" in document.createElement("pre") ? "textContent" : "innerText";',
              'var lastLogElem;',
              'function log(text) {',
              '  var logElem = document.createElement("pre");',
              '  logElem[textContentProp]=text;',
              '  document.body.appendChild(logElem);',
              '  logElem.scrollIntoView();',
              '  if (lastLogElem) {',
              '    lastLogElem.style.opacity = 0.5;',
              '  }',
              '  lastLogElem = logElem;',
              '}',
              '<' + '/' + 's' + 'cript>'].join('\n'));
            blankWindow.document.close();
        
            build.processTemplate(
              template, [build.functions],
              logText => (<any>blankWindow).log(logText),
              (error, processed) => {
        
                if (error) {
                  var errorElem = blankWindow.document.createElement('pre');
                  errorElem.style.fontWeight = 'bold';
                  setTextContent(errorElem, error + '\n' + error.message + ' ' + (<any>error).stack);
                  blankWindow.document.body.appendChild(errorElem);
                  errorElem.scrollIntoView();
        
                  if (processed) {
                    var showResultButton = blankWindow.document.createElement('button');
                    setTextContent(showResultButton, ' Show results ');
                    showResultButton.onclick = showProcessed;
                    blankWindow.document.body.appendChild(showResultButton);
                    showResultButton.scrollIntoView();
                  }
                  return;
                }
        
                showProcessed();
        
                function showProcessed() {
        
                  try {
        
                    var blob = new Blob([processed], { type: 'text/html' });
                    var url = URL.createObjectURL(blob);
                    blankWindow.location.replace(url);
        
                  }
                  catch (blobError) {
                    blankWindow.document.open();
                    blankWindow.document.write(processed);
                    blankWindow.document.close();
                  }
                }
              });
            
          }
          
        }
    • importExport
      • commitToGitHub.ts
        module portabled.app.importExport {
        
          export function commitToGitHub() {
        
            
            
            var filename = saveFileName();
            exportBlob(filename, ['<!doctype html>\n', document.documentElement.outerHTML]);
          }
        
        }
      • exportAllHTML.ts
        module portabled.app.importExport {
        
          export function exportAllHTML() {
            var filename = saveFileName();
            exportBlob(filename, ['<!doctype html>\n', document.documentElement.outerHTML]);
          }
        
         }
      • exportAllZIP.ts
        module portabled.app.importExport {
        
          export function exportAllZIP(drive: persistence.Drive) {
            zip.useWebWorkers = false;
            var filename = saveFileName();
            if (filename.length > '.html'.length && filename.slice(filename.length - '.html'.length).toLowerCase() === '.html')
              filename = filename.slice(0, filename.length - '.html'.length);
            else if (filename.length > '.htm'.length && filename.slice(filename.length - '.htm'.length).toLowerCase() === '.htm')
              filename = filename.slice(0, filename.length - '.htm'.length);
            filename += '.zip';
        
            var blobWriter = new zip.BlobWriter('application/octet-binary');
            zip.createWriter(blobWriter, (zipWriter) => {
        
              var files = drive.files();
              var completedCount = 0;
        
            var zipDIV = document.createElement('div');
            zipDIV.style.position = 'fixed';
            zipDIV.style.left = '25%'; zipDIV.style.top = '45%';
            zipDIV.style.height = 'auto';
            zipDIV.style.width = '50%';
            zipDIV.style.background = 'silver';
            zipDIV.style.border = 'solid 2px gray';
            zipDIV.style.zIndex = '1000000';
            zipDIV.style.padding = '1em';
            setTextContent(zipDIV, 'ZIP ' + files.length + ' files...');
            document.body.appendChild(zipDIV);
        
            var zipwritingCompleted = () => {
                zipWriter.close((blob: Blob) => {
                  var url = URL.createObjectURL(blob);
                  if (typeof console !== 'undefined' && typeof console.log === 'function') {
                    console.log('Preparing to save the ZIP [' + blob.size + '] ', blob, url);
                  }
        
                  setTextContent(zipDIV, 'ZIP of ' + files.length + ' files, ' + blob.size + ' bytes');
                  zipDIV.appendChild(document.createElement('br'));
                  var a = document.createElement('a');
                  setTextContent(a, 'Save');
                  a.href = url;
                  a.setAttribute('download', filename);
        
                  zipDIV.appendChild(a);
        
                  a.onclick = () => document.body.removeChild(zipDIV);
                });
              };
        
              var lastDelay = dateNow();
              var callbackNest = 0;
        
              var continueWriter = () => {
                if (completedCount === files.length) {
                  setTimeout(zipwritingCompleted, 300);
                  return;
                }
        
                var content = drive.read(files[completedCount]);
                if (!content) {
                  completedCount++;
                  continueWriter();
                  return;
                }
        
                var zipRelativePath = files[completedCount].slice(1);
        
                if (typeof console !== 'undefined' && typeof console.log === 'function') {
                  setTextContent(zipDIV, 'ZIP ' + files.length + ' files: ' + zipRelativePath + ' [' + content.length + '] ' + (completedCount + 1) + '/' + files.length + '...');
                  console.log(zipRelativePath + ' [' + content.length + '] (' + (completedCount + 1) + ' of ' + files.length + ')...');
                }
        
                zipWriter.add(zipRelativePath, new zip.TextReader(content), () => {
                  completedCount++;
                  if (dateNow() - lastDelay > 200 || callbackNest >20) {
                    lastDelay = dateNow();
                    setTimeout(continueWriter, 100);
                  }
                  else {
                    callbackNest++;
                    continueWriter();
                    callbackNest--;
                  }
                });
              };
        
              continueWriter();
            });
          }
        }
      • exportBlob.ts
        module portabled.app.importExport {
        
        
          export function exportBlob(filename: string, textChunks: string[]) {
            try {
              var blob: Blob = new (<any>Blob)(textChunks, { type: 'application/octet-stream' });
            }
            catch (blobError) {
              exportDocumentWrite(filename, textChunks.join(''));
              return;
            }
            
            exportBlobHTML5(filename, blob);
          }
            
          function exportBlobHTML5(filename, blob: Blob) {
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.setAttribute('download', filename);
            try {
              // safer save method, supposed to work with FireFox
              var evt = document.createEvent("MouseEvents");
              (<any>evt).initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
              a.dispatchEvent(evt);
            }
            catch (e) {
              a.click();
            }
          }
        
          function exportDocumentWrite(filename: string, content: string) {
            var win = document.createElement('iframe');
            win.style.width = '100px';
            win.style.height = '100px';
            win.style.display = 'none';
            document.body.appendChild(win);
        
            setTimeout(() => {
              var doc = win.document;
              doc.open();
              doc.write(content);
              doc.close();
        
              doc.execCommand('SaveAs', null, filename);
            }, 200);
        
          }
          
        }
      • importPortabledHTMLWithConfirmation.ts
        module portabled.app.importExport {
        
          export function importPortabledHTMLWithConfirmation(drive: persistence.Drive) {
        
            importExport.loadFile(
              (fileReader: FileReader, file: File) => fileReader.readAsText(file),
              (data, file: File) => {
                var parseHOST = document.createElement('div');
                parseHOST.innerHTML = data;
                var fileTreeHost = parseHOST.getElementsByClassName('portabled-file-tree')[0];
                if (!fileTreeHost) {
                  alert('Incorrect format detected.');
                  return;
                }
        
                var importedFiles = importChildren(<any>fileTreeHost, drive);
        
                var folder = prompt(
                  'Add ' + importedFiles.length + ' files from portabled HTML to a virtual folder:',
                  '/');
        
                if (!folder)
                  return;
        
                if (folder.charAt(0) !== '/')
                  folder = '/' + folder;
                if (folder.charAt(folder.length - 1) !== '/')
                  folder = folder + '/';
        
                drive.timestamp = dateNow();
                for (var i = 0; i < importedFiles.length; i++) {
                  var normFilename = files.normalizePath(folder + '/' + importedFiles[i].path);
                  drive.write(normFilename, importedFiles[i].content);
                }
        
              });
            
            function importChildren(parent: HTMLElement, drive: persistence.Drive) {
              var fileElements = parent.getElementsByClassName('portabled-file');
              var allFiles: { path: string; content: string; }[] = [];
              for (var i = 0; i < fileElements.length; i++) {
                var f = importFileElement(parent, <any>fileElements[i], drive);
                if (f)
                  allFiles.push(f);
              }
              return allFiles;
            }
            
            function importFileElement(rootHost: HTMLElement, fileElement: HTMLElement, dive: persistence.Drive) {
              var parentPath = computeParentPath(rootHost, fileElement);
        
              var contentElement: HTMLElement = <any>fileElement.getElementsByClassName('portabled-file-content')[0];
              if (!contentElement)
                return null;
              var content = files.readNodeFileContent(contentElement);
        
              var filenameElement: HTMLElement = <any>fileElement.getElementsByClassName('portabled-file-name')[0];
              if (!filenameElement)
                return null;
              var filename = filenameElement.textContent || filenameElement.innerText;
              var path = (parentPath.charAt(parentPath.length-1) === '/' ? parentPath :  parentPath + '/') + filename;
              
              return { path, content };
            }
        
            function computeParentPath(rootHost: HTMLElement, fileElement: HTMLElement): string {
              var dirs: string[] = [];
              var current = fileElement;
              while (current.parentElement !== null && current.parentElement !== rootHost) {
                var current = current.parentElement;
                if (current.className.indexOf('portabled-dir')>=0) {
                  var nameSpan: HTMLElement = <any>current.getElementsByClassName('portabled-dir-name')[0];
                  if (nameSpan)
                    dirs.push(nameSpan.textContent || nameSpan.innerText);
                }
              }
        
              return '/' + dirs.join('/');
            }
          }
        }
      • importSingleFileWithConfirmation.ts
        module portabled.app.importExport { 
        
          export function importSingleFileWithConfirmation(
            requestLoad: (fileReader: FileReader, file: File) => void,
            read: (file: string) => string,
            write: (file: string, text: string) => void,
            convertText: (raw: string) => string) {
        
              importExport.loadFile(
                requestLoad,
                (data, file) => {
                  var saveNamePromptMessage;
                  var existingRaw = read(files.normalizePath(file.name));
                  var existing = convertText ? convertText(existingRaw) : existingRaw;
                  if (existing) {
                    if (existing === data) {
                      saveNamePromptMessage =
                        file.name + ' already exists ' +
                        'with that same content ' +
                        '(' + data.length + ' character' + (data.length === 1 ? '' : 's') + ')' +
                        '\n' +
                        'Provide path or cancel:';
                    }
                    else {
                      saveNamePromptMessage =
                        file.name + ' already exists ' +
                        'with that different content ' +
                        '(' + data.length + ' character' + (data.length === 1 ? '' : 's') + 
                        ' comparing to ' + existing.length+' in the existing)' +
                        '\n' +
                        'Provide path or cancel:';
                    }
                  }
                  else {
                    saveNamePromptMessage =
                     file.name+' loaded '+data.length+' character' + (data.length === 1 ? '' : 's')+
                      '\n' +
                      'Provide path or cancel:';
                  }
                  
                  var saveName = prompt(saveNamePromptMessage, file.name);
                  if (!saveName)
                    return;
        
                  saveName = files.normalizePath(saveName);
        
                  write(saveName, convertText ? convertText(data) : data);
        
                });
        
          }
        }
      • importZIPWithConfirmation.ts
        module portabled.app.importExport {
        
          export function importZIPWithConfirmation(drive: persistence.Drive) {
        
            importExport.loadFile(
              (fileReader: FileReader, file: File) => fileReader.readAsArrayBuffer(file),
              (data, file: File) => {
        
                zip.useWebWorkers = false;
                zip.createReader(
                  new zip.BlobReader(file),
                  reader => {
                    reader.getEntries(entries => {
        
                      var folder = prompt(
                        'Add ' + entries.length + ' files from zip to a virtual folder:',
                        '/');
        
                      if (!folder)
                        return;
        
                      if (folder.charAt(0) !== '/')
                        folder = '/' + folder;
                      if (folder.charAt(folder.length - 1) !== '/')
                        folder = folder + '/';
        
                      var completeCount = 0;
                      var overwriteCount = 0;
        
                      var processEntry = () => {
        
                        if (completeCount === entries.length) {
                          alert(
                            completeCount + ' imported into ' + folder +
                            (overwriteCount ? ', ' + overwriteCount + ' existing files overwritten' : ''));
                          return;
                        }
        
                        var entry = entries[completeCount];
        
                        if (entry.directory) {
                          completeCount++;
                          processEntry();
                          return;
                        }
        
                        var writer = new zip.TextWriter();
        
                        entry.getData(writer,(text) => {
                          var virtFilename = folder + entry.filename;
                          var normFileName = files.normalizePath(virtFilename);
        
                          var isOverwrite = false;
        
                          var fileEntry = drive.read(normFileName);
                          if (fileEntry)
                            isOverwrite = true;
        
                          drive.write(normFileName, text);
        
                          if (isOverwrite)
                            overwriteCount++;
        
                          completeCount++;
                          setTimeout(() => processEntry(), 1);
        
                        });
                      };
        
                      processEntry();
        
                    });
                  },
                  error => {
                    alert('Zip file error: ' + error);
                  });
        
              });
        
          }
        }
      • loadFile.ts
        module portabled.app.importExport {
        
          export function loadFile(
            requestLoad: (fileReader: FileReader, file: File) => void,
            processData: (data: any, file: File) => void) {
            var input = document.createElement('input');
            input.type = 'file';
        
            input.onchange = () => {
              if (!input.files || !input.files.length) return;
        
              var fileReader = new FileReader();
              fileReader.onerror = (error) => {
                alert('read ' + error.message);
              };
              fileReader.onloadend = () => {
                if (fileReader.readyState !== 2) {
                  alert('read ' + fileReader.readyState + fileReader.error);
                  return;
                }
        
                processData(fileReader.result, input.files[0]);
              };
        
              requestLoad(fileReader, input.files[0]);
            };
        
            input.click();
          }
        }
      • saveFileName.ts
        module portabled.app.importExport {
        
          export function saveFileName() {
        
            if (window.location.protocol.toLowerCase() === 'blob:')
              return 'nportabled.html';
        
            var urlParts = window.location.pathname.split('/');
            var currentFileName = decodeURI(urlParts[urlParts.length - 1]);
            var lastDot = currentFileName.indexOf('.');
            if (lastDot > 0) {
              currentFileName = currentFileName.slice(0, lastDot) + '.html';
            }
            else {
              currentFileName += '.html';
            }
            return currentFileName;
          }
        
        }
    • koBindingHandlers
      • load.ts
        module portabled.app.koBindingHandlers.load {
        
          export function init(elem, valueAccessor, allBindings, viewModel, bindingContext) {
            valueAccessor();
          }
        
        }
      • loadRaw.ts
        module portabled.app.koBindingHandlers.loadRaw {
        
          export function init(elem, valueAccessor, allBindings, viewModel, bindingContext) {
            valueAccessor();
            return { controlsDescendantBindings: true };
          }
        
        }
      • register.ts
        module portabled.app.koBindingHandlers {
        
          export function register(ko) {
        
            for (var k in portabled.app.koBindingHandlers) if (portabled.app.koBindingHandlers.hasOwnProperty(k)) {
              var bindingHandler = portabled.app.koBindingHandlers[k];
              if (bindingHandler && typeof bindingHandler === 'object')
                ko.bindingHandlers[k] = bindingHandler;
            }
        
          }
          
        }
    • moreDialog
      • ImportAsMultiModel.ts
        module portabled.app.moreDialog {
        
          export class ImportAsMultiModel {
        
            constructor(
            	private _drive: persistence.Drive) {
            }
        
          }
        
        }
      • ImportAsSingleModel.ts
        module portabled.app.moreDialog {
          
          interface SiblingEntry {
            file: string;
            dir?: string;
            isMatching: boolean;
            isSubdir: boolean;
          }
          
          export class ImportAsSingleModel {
        
            filename = ko.observable('');
            siblings = ko.observableArray<SiblingEntry>([]);
          
            contentHost = ko.observable<HTMLElement>(null);
          
            private _updateTimer = new Timer();
        
            constructor(
              defaultBaseDir: string,
            	private _file: File,
              private _data: any,
              private _text: string,
              private _drive: persistence.Drive) {
        
              this.filename(defaultBaseDir + '/' + this._file.name);
              
              this._updateFromFilename();
              
              this.filename.subscribe(() => this._updateTimer.reset());
              
              this._updateTimer.ontick = () => this._updateFromFilename();
              
              this.contentHost.subscribe(() => this._updateTimer.reset());
            }
        
          	click(data: SiblingEntry) {
              if (data.dir) {
                var filePart = null;
                var filenameParts = this.filename().split('/');
                for (var i = filenameParts.length - 1; i >= 0; i--) {
                  if (filenameParts[i]) {
                    filePart = filenameParts[i];
                    break;
                  }
                }
                if (!filePart)
                  filePart = this._file.name;
                this.filename(data.dir + filePart);
              }
              else {
                this.filename(data.file);
              }
            }
          
            private _updateFromFilename() {
              var normFilename = files.normalizePath(this.filename());
              var lastslash = normFilename.lastIndexOf('/');
              var parentDir = normFilename.slice(0, lastslash +1);
              
              var allFiles = this._drive.files();
              var filtered: SiblingEntry[] = [];
              var exactMatch = false;
              var skipDeepDirs: any = {};
              for (var i = 0; i < allFiles.length; i++) {
                if (!allFiles[i].indexOf(parentDir)) {
                  var nextSlash = allFiles[i].indexOf('/', parentDir.length);
                  if (nextSlash>0) {
                    // collapse deep directories beneath the current one
                    var subdir = allFiles[i].slice(parentDir.length, nextSlash);
                    if (skipDeepDirs.hasOwnProperty(subdir))
                      continue;
                    skipDeepDirs[subdir] = true;
                    filtered.push({ file: ' ' + parentDir + subdir + '/...', isMatching: false, isSubdir: true, dir: parentDir + subdir + '/' });
                    continue;
                  }
                  var isMatching = allFiles[i]===normFilename;
                  filtered.push({ file: allFiles[i], isMatching: isMatching, isSubdir: false });
                  if (isMatching)
                    exactMatch = true;
                }
              }
              
              filtered.sort((entry1, entry2) => entry1.file>entry2.file ? 1 : entry1.file < entry2.file ? -1 : 0);
              if (normFilename.lastIndexOf('/')>0) {
                // insert the parent directories at the start
                var normFilenameParts = normFilename.split('/');
                normFilenameParts = normFilenameParts.slice(0, normFilenameParts.length - 2); // current name and current dir
                var insertDirs: SiblingEntry[] = [];
                for (var i = 0; i < normFilenameParts.length; i++) {
                  var dir = normFilenameParts.slice(0, i + 1).join('/') + '/';
                  insertDirs.push({ file: ' ' + dir + '...', isMatching: false, isSubdir: true, dir: dir });
                }
                filtered = insertDirs.concat(filtered);
              }
              
              this.siblings(filtered);
        
              if (this.contentHost()) {
                if (!exactMatch) {
                  this.contentHost().style.display = 'none';
                }
                else {
                  this.contentHost().style.display = 'block';
        
                  this.contentHost().innerHTML = '';
                  var mergeHost = document.createElement('div');
                  mergeHost.style.width = '100%';
                  mergeHost.style.height = '100%';
                  mergeHost.style.background = 'cornflowerblue';
        
                  this.contentHost().innerHTML = '';
                  this.contentHost().appendChild(mergeHost);
        
                  var detectedMode =
                    /.ts$/.test(normFilename) ? 'text/typescript' :
                  	/.html$/.test(normFilename) ? 'text/html' :
                  	/.css$/.test(normFilename) ? 'text/css' :
                    /.js$/.test(normFilename) ? 'javascript' :
                  	'text';
        
                  var options = {
                    orig: this._text, // swapped with value to make new text on the left
                    origLeft: null,
                    value: this._drive.read(normFilename), // here
                    lineNumbers: true,
                    mode: detectedMode,
                    highlightDifferences: true,
                    connect: true,
                    collapseIdentical: true,
                    allowEditingOriginals: false,
                    revertButtons: false
                  };
        
                  setTimeout(() => {
                    var dv = (<any>CodeMirror).MergeView(mergeHost, options);
                  }, 1);
                  
        /*
                  dv.leftOriginal().setSize(null, '80%');
                  dv.editor().setSize(null, '80%');
                  dv.rightOriginal().setSize(null, '80%');
        */
        
                }
              }
            }
            
          }
          
        }
      • ImportModel.ts
        module portabled.app.moreDialog {
         
          export class ImportModel {
        
            asSingle = ko.observable<ImportAsSingleModel>(null);
          
            asMulti = ko.observable<ImportAsMultiModel>(null);
          
            private _defaultBaseDir: string;
            
            constructor(
              private _currentFile: string,
            	private _file: File,
              private _data: any,
              private _text: string,
              private _drive: persistence.Drive) {
        
              var normCurrentFile = files.normalizePath(this._currentFile || '/');
              var lastSlash = normCurrentFile.lastIndexOf('/');
              this._defaultBaseDir = normCurrentFile.slice(0, lastSlash);
              
              this._switchToSingleFile();
            }
            
            keydown(e: KeyboardEvent) {
              return true;
            }
          
            private _switchToSingleFile() {
        
              var singleModel = new ImportAsSingleModel(
                this._defaultBaseDir,
                this._file,
                this._data, this._text,
                this._drive);
        
              this.asMulti(null);
              this.asSingle(singleModel);
        
            }
        
          }
          
        }
      • Model.ts
        module portabled.app.moreDialog {
          
          export class Model {
        
            moreModel = ko.observable<MoreModel>(null);
            importModel = ko.observable<ImportModel>(null);
        
            constructor(
            	private _currentFile: string,
              private _currentSelection: string,
              private _drive: persistence.Drive,
              private _completed: (selected: string) => void) {
              
              var filenames = this._drive.files();
              var moreModel = new MoreModel(this._currentFile, this._currentSelection, filenames, this._completed);
              this.moreModel(moreModel);
              
              moreModel.importLoaded = (file, data, text) => this._importLoaded(file, data, text);
            }
        
            
            dismiss() {
              this._completed(null);
            }
        
            keydown(e: KeyboardEvent) {
              var moreModel = this.moreModel();
              if (moreModel)
                return moreModel.keydown(e);
              
              var importModel = this.importModel();
              if (importModel)
                return importModel.keydown(e);
              
              return true;
            }
          
            connectToDOM() {
              var moreModel = this.moreModel();
              if (moreModel)
                moreModel.loadFromDOM();
            }
          
            private _importLoaded(file: File, data: any, text: string) {
              
              var importModel = new ImportModel(this._currentFile, file, data, text, this._drive);
              this.moreModel(null);
              this.importModel(importModel);
              
            }
        
            
          }
          
        }
      • MoreModel.ts
        module portabled.app.moreDialog {
        
          export class MoreModel {
        
            text = ko.observable<string>(null);
            matchItems = ko.observableArray<MoreModel.MatchItem>([]);
            textInput: HTMLInputElement = null;
        
            private _selectedItem = -1;
            private _allMatchItems: MoreModel.MatchItem[] = [];
        
            constructor(
              currentFile: string,
              currentSelection: string,
              private _files: string[],
              private _completed: (selected: string) => void) {
        
              for (var i = 0; i < this._files.length; i++) {
                var m = new MoreModel.MatchItem(
                  this._files[i],
                  'file',
                  this._completed);
                this._allMatchItems.push(m);
              }
        
              this._allMatchItems.sort((m1, m2) => {
                if (m1.text > m2.text) return 1;
                else if (m1.text < m2.text) return -1;
                else return 0;
              })
        
              this.text(currentSelection || (currentFile ? currentFile.slice(1) : ''));
        
              this._updateList();
        
              var updateTimeout = 0;
              this.text.subscribe(() => {
                if (updateTimeout)
                  clearTimeout(updateTimeout);
                updateTimeout = setTimeout(() => this._updateList(), 300);
              });
            }
        
            loadFromDOM() {
              if (this.textInput)
                this.textInput.select();
              else
                alert('textInput is not there!');
            }
        
            keydown(e: KeyboardEvent) {
              if (e.keyCode === 13 || e.which === 13 || e.key === 'Enter') {
                this._keyEnter();
              }
              else if (e.keyCode === 27 || e.which === 27 || e.key === 'Escape') {
                this._keyEscape();
              }
              else if (e.keyCode === 38 || e.which === 38) {
                this._keyUp();
              }
              else if (e.keyCode === 40 || e.which === 40) {
                this._keyDown();
              }
              else {
                return true;
              }
            }
        
            acceptClick() {
              var sel = this._selectedItem >= 0 ? this.matchItems()[this._selectedItem] : null;
              if (sel)
                this._completed(sel.text);
              else
                this._completed(this.text());
            }
          
            importLoaded: (file: File, data: any, text: string) => void = null;
        
            importClick() {
              if (this.importLoaded) {
        
                // first load as binary
                importExport.loadFile(
                  (fileReader, file) => fileReader.readAsArrayBuffer(file),
                  (data, file) => {
        
                    // then load as text (need both to present neat UI)
                    var fileReader = new FileReader();
                    fileReader.onloadend = (e) => {
                    		this.importLoaded(file, data, fileReader.result);
              			};
                    fileReader.readAsText(file);
                  });
              }
        
            }
        
            private _keyEnter() {
              this.acceptClick();
            }
        
            private _keyEscape() {
              this._completed(null);
            }
        
            private _keyUp() {
              this._moveSelection(-1);
            }
        
            private _keyDown() {
              this._moveSelection(+1);
            }
        
            private _moveSelection(delta: number) {
              if (this._selectedItem >= 0) {
                var old = this.matchItems()[this._selectedItem];
                if (old)
                  old.selected(false);
              }
        
              var newSelection = this._selectedItem + delta;
              if (newSelection < 0)
                newSelection = this.matchItems().length - 1;
              if (newSelection >= this.matchItems().length)
                newSelection = 0;
        
              this._selectedItem = newSelection;
        
              var sel = this.matchItems()[newSelection];
              if (sel) {
                sel.selected(true);
                this.textInput.value = sel.text;
                if (this.textInput.setSelectionRange) {
                  this.textInput.setSelectionRange(0, sel.text.length);
                }
                else if ('selectionStart' in this.textInput) {
                  this.textInput.selectionStart = 0;
                  this.textInput.selectionEnd = sel.text.length;
                }
              }
            }
        
            private _updateList() {
              var list: MoreModel.MatchItem[] = [];
              var fullMatch = -1;
              var text = this.text();
              var textLower = (text || '').toLowerCase();
              for (var i = 0; i < this._allMatchItems.length; i++) {
                var m = this._allMatchItems[i];
                if (text) {
                  if (m.text === text) {
                    if (fullMatch === -1) {
                      m.selected(true);
                      fullMatch = i;
                    }
                    else {
                      m.selected(false);
                      list.push(m);
                    }
                  }
                  else if (m.text.toLowerCase().indexOf(textLower) >= 0) {
                    m.selected(false);
                    list.push(m);
                  }
                  else {
                    m.selected(false);
                  }
                }
                else {
                  m.selected(false);
                  list.push(m);
                }
              }
              if (!list.length) {
                var m = new MoreModel.MatchItem(text, 'create', this._completed);
                m.display = 'Create new file: ' + text;
                m.selected(true);
                fullMatch = 0;
                list.push(m);
              }
              this.matchItems(list);
              this._selectedItem = fullMatch;
            }
        
          }
        
          export module MoreModel {
        
            export class MatchItem {
        
              selected = ko.observable(false);
              display: string;
        
              constructor(
                public text: string,
                public type: string,
                private _completed: (file: string) => void) {
                this.display = text;
              }
        
              clickSelect() {
                this._completed(this.text);
              }
        
            }
        
          }
        
        }
      • layout.html
        <div class=portabled-more-dialog-background
           data-bind="click: dismiss, event: { keydown: function(unused, e) { return keydown(e); } }">
        
          <!-- ko template: { "if": moreModel(), data: moreModel() } -->
          <div class=portabled-more-dialog
             data-bind="click: function() { }, clickBubble: false">
            
            <input class=portabled-more-filename data-bind="hasFocus: true, textInput: text, load: textInput=$element">
        
            <div class=portabled-more-dialog-list data-bind="foreach: matchItems">
              <div class=portabled-more-dialog-item
                   data-bind="text: display, css: { selected: selected }, click: clickSelect ">
              </div>
            </div>
        
            <button data-bind="click: importClick"> import </button>
              
          </div>
        
          <!-- /ko -->
        
          <!-- ko template: { "if": importModel(), data: importModel() } -->
          
          <div class=portabled-import-dialog
             data-bind="click: function() { }, clickBubble: false">
            
            <!-- ko template: { "if": asSingle(), data: asSingle() } -->
            	<input class=portabled-more-filename data-bind="hasFocus: true, textInput: filename">
              <div class=portabled-import-tree data-bind="foreach: siblings()">
        
                <div
                     class=portabled-import-tree-item
                     data-bind="
                                text: file,
                                css: { 'portabled-import-tree-item-matching': isMatching, 'portabled-import-tree-subdir': isSubdir },
                                click: function() { $parent.click($data); }"></div>
              </div>
            	<div class=portabled-import-diff-host data-bind="loadRaw: contentHost($element)"></div>
            <!-- /ko -->
        
        
            <!-- ko template: { "if": asMulti(), data: asMulti() } -->
            	multi
            <!-- /ko -->
        
          </div>
          
          
          <!-- /ko -->
        
        </div>
      • style.css
        .portabled-more-dialog-background {
          
          position: fixed !important;
          position: absolute;
          left: 0px; top: 0px;
          width: 100%; height: 100%;
          background: rgba(1,1,1,0.6);
          z-index: 200;
          
        }
        
        .portabled-more-dialog {
          
          position: fixed !important;
          position: absolute;
          left: 15%;
          width: 70%;
          top: 20%;
          height: 70%;
          padding: 1em;
        
          background: #B3D0E4;
        
        }
        
        .portabled-more-filename {
          width: 95%;
        }
        
        .portabled-import-dialog {
          
          position: fixed !important;
          position: absolute;
          left: 15%;
          width: 70%;
          top: 10%;
          padding: 1em;
        
          background: #C8B6D6;
        
        }
        
        .portabled-import-tree {
          float: left;
          width: 30%;
          height: 80%;
          overflow: auto;
          border: solid 1px silver;
          padding: 3px;
        }
        
        .portabled-import-tree-item-matching {
          background: gold;
        }
        
        .portabled-import-tree-subdir {
          opacity: 0.6;
          font-weight: bold;
        }
        
        .portabled-import-diff-host {
          float: left;
          width: 67%; 
          height: 80%;
        }
        
        .portabled-more-dialog-list {
          height: 80%;
          overflow: auto;
        }
        
        .portabled-more-dialog input {
          
          width: 100%;
          font-size: 200%;
          
        }
        
        .portabled-more-dialog .portabled-more-dialog-item {
          font-size: 140%;
          padding: 0.25em;
        }
        
        .portabled-more-dialog .portabled-more-dialog-item.selected {
          background: cornflowerblue;
          color: white;
        }
    • body.css
      html {
        box-sizing: border-box;
      }
      
      *, *:before, *:after {
        box-sizing: inherit;
      }
      
      html {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
      body {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
    • flyout-branding.css
      .portabled-extra-content {
        float: left;
        width: 71%;
        height: 100%;
        margin-right: -1em;
        background: white;
      }
      
      .portabled-extra-content .portabled-branding-area {
        height: 40%;
        padding: 1em;
        overflow: auto;
        font-size: 90%;
      }
      
      .portabled-extra-content .portabled-scrollable-bottom {
        height: 60%;
        overflow: auto;
        padding: 1em;
      }
      
      .portabled-extra-content .portabled-links {
        float: left;
        font-size: 90%;
        width: 50%;
      }
      
      .portabled-extra-content .portabled-credits {
        float: left;
        height: 36%;
        width: 50%;
        font-size: 90%;
      }
      
    • flyout.css
      .portabled-main-content {
        position: fixed !important;
        position: absolute;
        left: 0px; top: 0px;
        height: 100%;
        width: 85%;
        padding-bottom: 2em;
      }
      
      
      .portabled-flyout-scroller {
        position: fixed !important;
        position: absolute;
        left: 0px; top: 0px; width: 100%; height: 100%;
        overflow-y: hidden;
        overflow-x: scroll;
      }
      
      .portabled-flyout-scroller-bg {
        height: 100%;
        width: 130%;
        padding-left: 85%;
      }
      
      .portabled-flyout {
        border-top: solid 1px silver;
        position: relative;
        height: 100%;
        background: #E8E8E8;
        z-index: 100;
        overflow: hidden;
        padding-bottom: 2em;
      }
      
      
    • loading.css
      #portabled-loading-host {
      
        position: absolute;
        left: 12%;
        top: 25%;
        z-index: 5000;
        
      }
      
      #portabled-loading-title {
        
        font-size: 200%;
        font-weight: 100;
        opacity: 0.6;
        
      }
    • loading.ts
      module portabled.app {
        
        var loadingHostDIV: HTMLElement;
        var loadingTitleDIV: HTMLElement;
        var loadingProgressDIV: HTMLElement;
      
        var loadingTimeout: number = 0;
      
        // baseUI, domFilesystem, flyoutUI, libraries
        var currentDescription;
      
        export function loading(description) {
      
          if (!loadingHostDIV) {
            loadingHostDIV = document.getElementById('portabled-loading-host');
            loadingTitleDIV = document.getElementById('portabled-loading-title');
            loadingProgressDIV = document.getElementById('portabled-loading-progress');
          }
      
          if (description) {
            loadingHostDIV.style.display = 'block';
          }
          else {
            loadingHostDIV.style.display = 'none';
            return;
          }
      
          currentDescription = description;
          if ('textContent' in loadingTitleDIV)
            loadingTitleDIV.textContent = currentDescription;
          else
            loadingTitleDIV.innerText = currentDescription;
        }
        
        
      }
    • start.ts
      module portabled.app {
      
        export function start() {
      
          loading('Initialising the application...');
      
      
          koBindingHandlers.register(ko);
      
          // Cleanup of the HTML for fishy scripts and remnants of the dialog windows.
          //
          // Some fishy internet providers (looking at you, Vodafone)
          // inject their scripts indiscriminately into every served web page.
          // These needs to be removed from DOM
          // at least to avoid saving them with the document.
          //
          // Dialog windows implemented as HTML DIVs may survive if document is saved.
          // That stuff can be safely removed (it appears at the end of DOM body).
      
          removeSpyScripts();
          removeTrailElements();
          
          addEventListener(window, 'load',() => {
            // this may never be executed, if window is already loaded
            removeSpyScripts();
            removeTrailElements();
          });
      
      
          loading('Restoring the setup...');
      
          var layout = new portabled.app.appRoot.PageModel();
      
          loading('Rendering...');
      
          ko.applyBindings(layout, document.body);
      
          loading('Processing...');
          layout.loadFromDOM(() => {
      
            setTimeout(() => {
              runStartScripts(() => {
                loading(null);
              });
            }, 1);
      
          });
      
        }
          
        var startScripts: { (completed: () => void): void; }[] = [];
      
        export module start {
          
          export function addStartScript(script: (completed: () => void) => void ) {
            startScripts.push(script);
          }
          
        }
        
        function runStartScripts(completed: () => void) {
          var completionInvoked = false;
          invokeNextStartupScript();
      
          function invokeNextStartupScript() {
            if (!startScripts.length) {
              if (!completionInvoked) {
                completionInvoked = true;
                setTimeout(() => {
                  completed();
                }, 1);
              }
              return;
            }
      
            var nextScript = startScripts.shift();
            nextScript(() => { 
              invokeNextStartupScript();
            });
      
            setTimeout(invokeNextStartupScript, 1);
          }
        }
          
        function removeSpyScripts() {
          var spyScripts: Element[] = [];
          for (var i = 0; i < document.scripts.length; i++) {
            if (document.scripts[i].getAttribute('data-legit') !== 'portabled')
              spyScripts.push(document.scripts[i]);
          }
          
          for (var i = 0; i < spyScripts.length; i++) {
            spyScripts[i].parentNode.removeChild(spyScripts[i]);
          }
        }
      
        function removeTrailElements() {
          var lastDIV = document.getElementById('portabled-last-element');
          while (lastDIV && lastDIV.nextSibling) {
            lastDIV.nextSibling.parentNode.removeChild(lastDIV.nextSibling);
          }
        }
      
      }
    • status.css
      .portabled-status-bar {
        position: fixed !important;
        position: absolute;
        left: 0px;
        bottom: 0px;
        height: 2em;
        width: 100%;
        background: #B3D0E4;
        z-index: 100;
      }
    • tree-and-bar.css
      .portabled-file-tree {
        float: left;
        width: 23%;
        height: 100%;
        overflow: auto;
        border-right: solid 1px whitesmoke;
      }
      
      .portabled-thick-bar-host {
        float: left;
        width: 2em;
        height: 100%;
        overflow: hidden;
      }
      
      .portabled-thick-bar-host .portabled-more-button {
        width: 2em;
        height: 2em;
        font-size: inherit;
        font-family: inherit;
        position: absolute;
        opacity: 0.8;
      }
      
      .portabled-thick-bar-host .portabled-thick-bar-bg {
        height: 100%;
        margin-top: 2em;
        padding-bottom: 2em;
      }
      
      .portabled-thick-bar-host .portabled-thick-bar-bg .portabled-thick-bar {
        height: 100%;
        background: white;
        border-left: solid 1px #E4EEF5;
        cursor: move;
      }
      
  • build
    • functions
      • appPageModel.ts
        module portabled.build.functions {
          
          export var appPageModel: app.appRoot.PageModel;
          
        }
      • embedFile.ts
        module portabled.build.functions {
        
          export function embedFile(...inputs: string[]) {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number') 
                inputsCore = inputsCore.concat(inputs[i]); 
              else 
                inputsCore.push(inputs[i]);
            }
            return embedFileCore(inputsCore);
          }
        
        
          function embedFileCore(inputs: string[]) {
            var outputs: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              var text = processTemplate.mainDrive.read(files.normalizePath(inputs[i]));
              if (text || typeof text === 'string')
                outputs.push(text);
              else
                outputs.push(inputs[i]);
            }
            return outputs.join('\n');
          }
        
        }
      • embedTree.ts
        module portabled.build.functions {
          
          export function embedTree() {
        
              var docNames = processTemplate.mainDrive.files();
              docNames.sort();
        
              var rootDir = {};
              for (var i = 0; i < docNames.length; i++) {
                var fullPath = docNames[i];
                var file = fullPath;
                if (file.charAt(0) === '/') file = file.slice(1);
                var parts = file.split('/');
                var dir = rootDir;
                for (var j = 0; j < parts.length - 1; j++) {
                  dir = dir[parts[j]] || (dir[parts[j]] = {});
                }
                var docState = processTemplate.mainDrive.read(fullPath);
                dir[parts[parts.length - 1]] = docState;
              }
        
              var tmp = document.createElement('pre');
        
              var addDir = (dir) => {
                for (var k in dir) if (dir.hasOwnProperty(k)) {
                  var child = dir[k];
                  if (typeof child === 'string') {
                    output.push('<li class=portabled-file><span class=portabled-file-name>' + k + '</span>');
                    tmp.textContent = child;
                    output.push('<pre class=portabled-file-content>' + tmp.innerHTML + '</pre></li>');
                  }
                  else {
                    output.push('<li class="portabled-dir portabled-dir-collapsed"><span class=portabled-dir-name>' + k + '</span><ul>');
                    addDir(child);
                    output.push('</ul></li>');
                  }
                }
              }
        
              var output: string[] = [];
        
              addDir(rootDir);
        
              return output.join('');
        
          }
          
        }
      • typescriptBuild.ts
        module portabled.build.functions {
        
          export function typescriptBuild() {
            var asyncFn: any = () => typescriptBuildCore();
            asyncFn.toString = () => 'typescriptBuild()';
            return asyncFn;
          }
        
          function typescriptBuildCore() {
            
            typescriptBuild.mainTS.compilerOptions.out = 'index.js';
        
            // ensure preloading is stopped
            typescriptBuild.mainTS.service();
        
            var files = typescriptBuild.mainTS.host.getScriptFileNames();
            var nonDeclFile = null;
            for (var i = 0; i < files.length; i++) {
              var f = files[i];
              if (f.slice(f.length - '.d.ts'.length) === '.d.ts')
                continue;
              nonDeclFile = f;
              break;
            }
            
            var program = typescriptBuild.mainTS.service().getProgram();
            var emitOutputStr: string = null;
            
            var errorList =
                program.getSyntacticDiagnostics().
            			concat(program.getGlobalDiagnostics()).
            			concat(program.getSemanticDiagnostics());
        
            if (errorList.length) {
              var errorFiles = 0;
              var errorFileMap = {};
              var errors: string[] = [];
              for (var i = 0; i < errorList.length; i++) {
                var err = errorList[i];
        
                if (!errorFileMap.hasOwnProperty(err.file.fileName)) {
                  errorFileMap[err.file.fileName] = 1;
                  errorFiles++;
                }
        
                var pos = err.file ? err.file.getLineAndCharacterOfPosition(err.start) : null;
                errors.push(
                  (err.file ? err.file.fileName + ' ' : '') +
                  (ts.DiagnosticCategory[err.category]) + err.code +
                  (pos ? ' @' + pos.line + ':' + pos.character : ' @@' + err.start) + ' ' + err.messageText);
              }
        
              throw new Error(
                'TypeScript compilation errors/warnings ' + nonDeclFile + ', ' + errors.length + ' errors in ' + errorFiles+' files:\n'+
                errors.join('\n'));
            }
        
            program.emit(nonDeclFile, (filename, data, orderMark) => emitOutputStr = data);
        
            return emitOutputStr;
            
            
          }
            
          export module typescriptBuild {
         
            export var mainTS: typescript.TypeScriptService;
        
          }
          
        }
      • uglifyCSS.ts
        declare var UglifyCSS: any;
        
        module portabled.build.functions {
        
          var cache: { [key: string]: { input: string; output: string; }; } = {};
        
          export function uglifyCSS(...inputs: string[]): any {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number')
                inputsCore = inputsCore.concat(inputs[i]);
              else
                inputsCore.push(inputs[i]);
            }
        
            return uglifyJSCore(inputsCore);
          }
        
        
        
          function uglifyJSCore(inputs: string[]): any {
            var inputParts: string[] = [];
            var inputTexts: string[] = [];
        
            for (var i = 0; i < inputs.length; i++) {
              inputParts[i] = inputTexts[i] = inputs[i];
              if (inputs[i].length < 200 && inputs[i].indexOf('\n') < 0) {
                var norm = files.normalizePath(inputs[i]);
                var inputText = processTemplate.mainDrive.read(norm);
                if (typeof inputText === 'string') {
                  inputParts[i] = norm;
                  inputTexts[i] = inputText;
                }
              }
            }
        
        
            var key = '{uglifyCSS}' + murmurhash2_32_gc(inputParts.join(','), 23);
            var input = inputTexts.join('\n');
        
            if (cache.hasOwnProperty(key) && cache[key].input === input)
              return cache[key].output;
            try {
              if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                var sessionCached = sessionStorage.getItem ? sessionStorage.getItem(key) : sessionStorage[key];
                if (sessionCached && typeof sessionCached === 'string') {
                  var cacheItem = JSON.parse(sessionCached);
                  if (cacheItem.input === input)
                    return cacheItem.output;
                }
              }
            }
            catch (sessionError) {
            }
        
            var asyncFn: any = () => {
              var output = uglifyText(input);
              cache[key] = { input, output };
        
              try {
                if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                  if (sessionStorage.setItem)
                    sessionStorage.setItem(key, JSON.stringify({ input, output }));
                }
              }
              catch (sessionError) {
              }
        
              return output;
            };
            asyncFn.toString = () => 'uglifyCSS(' + (key.length > 50 || key.indexOf('\n') ? key.replace(/\n/g, ' ').slice(0, 48) + '...' : key) + ')';
            return asyncFn;
          }
        
          function uglifyText(text: string) {
            var result = UglifyCSS.processString(text, {});
        
            return result;
          }
        
        }
      • uglifyJS.ts
        declare var Uglify2: any;
        
        module portabled.build.functions {
        
          var cache: { [key: string]: { input: string; output: string; }; } = {};
        
          export function uglifyJS(...inputs: string[]): any {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number')
                inputsCore = inputsCore.concat(inputs[i]);
              else
                inputsCore.push(inputs[i]);
            }
        
            return uglifyJSCore(inputsCore);
          }
        
          function uglifyJSCore(inputs: string[]): any {
            var inputParts: string[] = [];
            var inputTexts: string[] = [];
        
            for (var i = 0; i < inputs.length; i++) {
              inputParts[i] = inputTexts[i] = inputs[i];
              if (inputs[i].length < 200 && inputs[i].indexOf('\n') < 0) {
                var norm = files.normalizePath(inputs[i]);
                var inputText = processTemplate.mainDrive.read(norm);
                if (typeof inputText === 'string') {
                  inputParts[i] = norm;
                  inputTexts[i] = inputText;
                }
              }
            }
        
            var key = '{uglifyJS}' + murmurhash2_32_gc(inputParts.join(','), '23');
            var input = inputTexts.join('\n');
        
            if (!uglifyJS.skip && cache.hasOwnProperty(key) && cache[key].input === input)
              return cache[key].output;
        
            try {
              if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                var sessionCached = sessionStorage.getItem ? sessionStorage.getItem(key) : sessionStorage[key];
                if (sessionCached && typeof sessionCached === 'string') {
                  var cacheItem = JSON.parse(sessionCached);
                  if (cacheItem.input === input)
                    return cacheItem.output;
                }
              }
            }
            catch (sessionError) {
            }
        
            var asyncFn: any = () => {
              var output = uglifyText(input);
        
              if (!uglifyJS.skip) {
                cache[key] = { input, output };
        
                try {
                  if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                    if (sessionStorage.setItem)
                      sessionStorage.setItem(key, JSON.stringify({ input, output }));
                  }
                }
                catch (sssionError) {
                }
              }
        
              return output;
            };
            asyncFn.toString = () => 'uglify('+(key.length > 50 || key.indexOf('\n') ? key.replace(/\n/g, ' ').slice(0,48)+'...' : key)+')';
        
            return asyncFn;
          }
        
          function uglifyText(text: string) {
        
            if (uglifyJS.skip) {
              if (typeof console !== 'undefined' && typeof console.log === 'function')
                console.log('uglifyText(' + JSON.stringify(text.slice(0, Math.min(text.length, 20))) + ') skipping to plain text');
              return text;
            }
        
            var ast = Uglify2.parse(text, {});
            ast.figure_out_scope();
        
            var compressor = new Uglify2.Compressor({
              sequences: true,
              properties: true,
              dead_code: true,
              drop_debugger: true,
              unsafe: false,
              unsafe_comps: false,
              conditionals: true,
              comparisons: true,
              evaluate: true,
              booleans: true,
              loops: true,
              unused: true,
              hoist_funs: true,
              hoist_vars: false,
              if_return: true,
              join_vars: true,
              cascade: true,
              side_effects: true,
              negate_iife: true,
              screw_ie8: false,
        
              warnings: true,
              global_defs: {}
            });
        
            var compressed = ast.transform(compressor);
        
            compressed.figure_out_scope();
            compressed.compute_char_frequency();
            compressed.mangle_names();
        
            var result = compressed.print_to_string({
              quote_keys: false,
              space_colon: true,
              ascii_only: false,
              inline_script: true,
              max_line_len: 1024,
              beautify: false,
              source_map: null,
              bracketize: false,
              semicolons: true,
              comments: /@license|@preserve|^!/,
              preserve_line: false,
              screw_ie8: false
            });
        
            if (typeof console !== 'undefined' && typeof console.log === 'function')
              console.log('uglifyText(' + JSON.stringify(text.slice(0, Math.min(text.length, 20))) + ') resulted in ' + result.lengh + ' chars (' + (result.length * 100 / text.length) + '% original)');
        
            return result;
          }
        
          export module uglifyJS {
        
            export var skip: boolean;
        
          }
        
        }
    • processTemplate.ts
      module portabled.build {
        
        export function processTemplate(
          template: string, scopes: any[],
          log: (logText: string) => void,
          callback: (error: Error, result?: string) => void): void {
          // <%= expr %>
          // <% statement %>
          // <%-- comment --%>
      
          log('Generating build script...');
          setTimeout(() => {
          	var fnText = generateBuildScript(template, scopes);
      
            log('Preprocessing build script...');
            setTimeout(() => {
              var fn = Function('scopes', fnText);
      
              log('Executing build script...');
      
              var output: any[] = fn(scopes);
              var outputIndex = 0;
      
              processNextOutputChunk();
      
              function processNextOutputChunk() {
                var startTime = dateNow();
      
                // all heavy chunks will bail out and queue the next one on setTimeout,
                // simple literal insertions keep going for a slice of time
                while (true) {
                  if (outputIndex>=output.length) {
                    var result = output.join('');
                    callback(null, result);
                    return;
                  }
      
                  var outputChunk = output[outputIndex];
                  if (typeof outputChunk==='function') {
                    log('Processing ' + outputChunk + '...');
                    setTimeout(() => {
                      try {
                        var chunkResult = outputChunk();
                        var chunkResultText = String(chunkResult);
                        output[outputIndex] = chunkResultText;
                      }
                      catch (error) {
                        callback(error);
                        return;
                      }
      
                      log('...OK [' + chunkResultText.length + ']');
                      outputIndex++;
                      processNextOutputChunk();
                      //setTimeout(processNextOutputChunk, 1);
                    }, 1);
                    break;
                  }
                  else {
                    var literal = String(outputChunk);
                    output[outputIndex] = literal;
                    var literalLines = (literal.length > 100 ? literal.slice(0, 50) + '\n...\n' + literal.slice(literal.length - 5) : literal).split('\n');
                    while (literalLines.length && !literalLines[0]) literalLines.shift();
                    while (literalLines.length && !literalLines[literalLines.length - 1]) literalLines.pop();
                    log(literalLines.length <= 2 ? literalLines.join('\n') : literalLines[0] + '\n...\n' + literalLines[literalLines.length - 1]);
                    outputIndex++;
      
                    if (dateNow() - startTime > 300) {
                    	setTimeout(processNextOutputChunk, 1);
                      break;
                    }
                    // keep going if haven't been processing for long yet
      
                  }
                }
              }
              
            }, 1);
      
          }, 1);
      
        }
      
        export module processTemplate {
      
          export var mainDrive: persistence.Drive;
      
        }
        
        function generateBuildScript(template: string, scopes: any[]): string {
          var generated: string[] = [];
          for (var i = 0; i < scopes.length; i++) {
            generated.push('with(scopes[' + i + ']) {');
          }
          
          generated.push('var output =[];');
      
          var index = 0;
          while (index < template.length) {
            
            var nextOpenASP = template.indexOf('<%', index);
            if (nextOpenASP < 0) {
              generateWrite(generated, template.slice(index));
              break;
            }
      
            var ch = template.charAt(nextOpenASP + 2);
            if (ch === '=') {
              var closeASP = template.indexOf('%>', nextOpenASP);
              if (closeASP < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              generateRedirect(generated, template.slice(nextOpenASP + 3, closeASP));
              index = closeASP + 2;
            }
            else if (ch === '-') {
              var closeCommentMatch = template.charAt(nextOpenASP + 3) === '-' ? '--%>' : '-%>';
              var closeComment = template.indexOf(closeCommentMatch, nextOpenASP);
              if (closeComment < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              index = closeComment + closeCommentMatch.length;
            }
            else {
              var closeASP = template.indexOf('%>', nextOpenASP);
              if (closeASP < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              generateStatement(generated, template.slice(nextOpenASP + 2, closeASP));
              index = closeASP + 2;
            }
            
          }
      
          for (var i = 0; i < scopes.length; i++) {
            generated.push('}');
          }
      
          generated.push('return output;');
      
          var fnText = generated.join('\n');
          return fnText;
          
        }
      
        
        function generateWrite(generated: string[], chunk: string) {
          if (chunk)
            generated.push('output.push(\'' + stringLiteral(chunk) + '\');');
        }
        
        function generateRedirect(generated: string[], redirect: string) {
          generated.push('output.push(' + redirect + ');');
        }
      
        function generateStatement(generated: string[], statement: string) {
          generated.push(statement);
        }
      
        function stringLiteral(text: string) {
          return text.
            replace(/\\/g, '\\\\').
            replace(/\n/g, '\\n').
            replace(/\r/g, '\\r').
            replace(/\t/g, '\\t').
            replace(/\'/g, '\\\'').
            replace(/\"/g, '\\"');
        }
        
      }
  • docs
    • types
      • text
        • base
          • SimpleCodeMirrorDocHandler.ts
            module portabled.docs.types.text.base {
            
              export class SimpleCodeMirrorDocHandler implements CodeMirrorTextDoc {
            
                path = null;
                editor: CodeMirror = null;
                doc: CodeMirror.Doc = null;
                text: () => string = null;
                scroller: HTMLElement = null;
                status: HTMLElement = null;
                keyMap: any = {
                  "Ctrl-Enter": () => this._triggerCompletion(true),
                  "Alt-Enter": () => this._triggerCompletion(true),
                  "Ctrl-J": () => this._triggerCompletion(true),
                  "Alt-J": () => this._triggerCompletion(true)
                };
                removed = false;
            
                state: any = null;
            
                private _completionTimer: Timer = null;
                private _completionLastChangeText = null;
                private _isCompleting = false;
            
                constructor() {
                }
            
                open() {
                }
            
                close() {
                  if (this._completionTimer)
            	      this._completionTimer.stop();
                }
            
                remove() { 
                }
            
            
                asyncCompletion = false;
                
                shouldTriggerCompletion(textBeforeCursor: string): boolean {
                  return false;
                }
            
                getCompletions(callback?: Function): any {
                  return null;
                }
            
                onChanges(docChanges: CodeMirror.EditorChange[], summary: { lead: number; mid: number; trail: number; }) {
            
                  // awkward workaround to an apparent TS emit bug (super.method() instead of _super.instance.method())
                  this.onChangesCore(docChanges, summary);
            
                  if (this.getCompletions) {
                    if (!this._isCompleting) {
                      var cur = this.doc.getCursor();
                      var line = this.doc.getLine(cur.line);
                      this._completionLastChangeText = line.slice(0, cur.ch);
            
                      if (!this._completionTimer)
                        this._createCompletionTimer();
                      this._completionTimer.reset();
                    }
                  }
                }
                
                onChangesCore(docChanges: CodeMirror.EditorChange[], summary: { lead: number; mid: number; trail: number; }) {
                }
            
                private _createCompletionTimer() {
                  this._completionTimer = new Timer();
                  this._completionTimer.interval = 200;
                  this._completionTimer.ontick = () => {
                    if (this._isCompleting) return;
                    if (!this.editor)
                      return;
            
                    if (!this.shouldTriggerCompletion || this.shouldTriggerCompletion(this._completionLastChangeText)) {
                      this._triggerCompletion(/*implicitly*/ true);
                    }
                  };
                }
            
                onSave() {
                  
                }
            
                private _triggerCompletion(implicitly: boolean) {
            
                  if (this._completionTimer)
                    this._completionTimer.stop();
            
                  var lastResult;
                  
                  var close = () => {
                    CodeMirror.off(lastResult, 'close', close);
                    this._isCompleting = false;
                  };
                  
                  var hintFn = (cm,callback,options) => {
                    
                    var processResults = (results: CodeMirror.showHint.CompletionResult) => { 
                      if (result && result.list && implicitly) {
                        var chunk = this.doc.getRange(result.from, result.to);
                        for (var i = 0; i < result.list.length; i++) {
                          if (result.list[i] == <any>chunk) {
                            result = null;
                            break;
                          }
                        }
                      }
            
                      if (result) { 
                        this._isCompleting = true;
            
                        lastResult = result;
                        CodeMirror.on(lastResult, 'close', close);
                      }
                      else {
                        this._isCompleting = false;
                        if (lastResult)
                          CodeMirror.off(lastResult, 'close', close);
                      }
            
                      return result;
                    };
                    
                    if (this.asyncCompletion) {
                      (<any>this.getCompletions)(result => {
                        var res = processResults(result);
                        callback(res);
                      });
                    }
                    else {
                    
                      var result: CodeMirror.showHint.CompletionResult = this.getCompletions();
                      
                      var res = processResults(result);
                      return res;
                    }
                  };
                  
                  if (this.asyncCompletion) {
                    (<any>hintFn).async = true;
                  }
                  
                  var hintData: CodeMirror.showHint.Options = {
                    hint: hintFn,
                    completeSingle: implicitly ? false : true
                  };
            
                  // console.log('hintData ', hintData);
                  this.editor.showHint(hintData);
            
                }
                
                onCompletion(callback: (result: CodeMirror.showHint.CompletionResult) => void) {
                  var completions = <CodeMirror.showHint.CompletionResult>(<any>CodeMirror).hint.css(this.editor);
                  callback(completions);
                }
                
              }
              
            }
        • css
          • CssDocHandler.ts
            module portabled.docs.types.text.css {
              
              export var expectsFile = /.*\.css/g;
              export var acceptsFile = /.*\.css/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new CssDocHandler();
              }
            
              export class CssDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
            
            
                shouldTriggerCompletion(textBeforeCursor: string) {
            
                  if (textBeforeCursor.slice(textBeforeCursor.length - 2) === ': ')
                    return true;
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '-')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                  
                }
                
                getCompletions() {
                  return (<any>CodeMirror).hint.css(this.editor);
                }
                
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'css');
              }
            
              
            }
        • html
          • HtmlDocHandler.ts
            module portabled.docs.types.text.html {
            
              export var expectsFile = /.*\.(html|htm)/g;
              export var acceptsFile = /.*\.(html|htm)/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new HtmlDocHandler();
              }
            
              export class HtmlDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
            
            
                shouldTriggerCompletion(textBeforeCursor: string) {
            
                  var cursorPos = this.doc.getCursor();
                  var token = this.editor.getTokenAt(cursorPos);
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '<')
                    return true;
            
                  if (lastChar === '=' && token.type) // ignore equals sign not inside element tag
                    return true;
            
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase()) {
            
                    if (token.type) // token.type == null -> means simple text, don't complete
                      return true;
                  }
                  
                }
                
                getCompletions() {
                  if ((<any>CodeMirror).hint && (<any>CodeMirror).hint.html)
                  	return (<any>CodeMirror).hint.html(this.editor);
                }
                
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/html');
              }
            
              
            }
        • js
          • JavaScriptDocHandler.ts
            module portabled.docs.types.text.js {
              
              export var expectsFile = /.*\.js/g;
              export var acceptsFile = /.*\.js/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new JavaScriptDocHandler();
              }
            
              export class JavaScriptDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
                load(text: string) {
                  return;
                  ternServer().server.addFile(this.path, text);
                }
            
                open() {
                  return;
                  ternServer().server.delFile(this.path);
                  ternServer().addDoc(this.path, this.doc);
            
                }
            
                disabled_shouldTriggerCompletion(textBeforeCursor: string) {
            
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '.')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                  
                }
                
                disabled_getCompletions(callback): any {
            
                  return;
                  if (_completionSuccess === false) {
                    return (<any>CodeMirror).hint.javascript(this.editor);
                  }
            
                  try {
                    ternServer().getHint(this.editor, callback);
                    _completionSuccess = true;
                  }
                  finally {
                    if (!_completionSuccess)
                      _completionSuccess = false;
                  }
                  
            
                }
                
              }
            
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'javascript');
              }
            
              var _completionSuccess;
              var _ternServer;
              function ternServer() {
                
                if (_ternServer) return _ternServer;
                
                if (!(<any>CodeMirror).TernServer) return null;
                _ternServer = new (<any>CodeMirror).TernServer();
                return _ternServer;
                
              }
            }
        • json
          • JsonDocHandler.ts
            module portabled.docs.types.text.json {
              
              export var expectsFile = /.*\.json/g;
              export var acceptsFile = /.*\.json/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new js.JavaScriptDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'json');
              }
            
              
            }
        • less
          • LessDocHandler.ts
            module portabled.docs.types.text.less {
              
              export var expectsFile = /.*\.less/g;
              export var acceptsFile = /.*\.less/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-less');
              }
            
              
            }
        • md
          • MarkdownDocHandler.ts
            module portabled.docs.types.text.md {
              
              export var expectsFile = /.*\.md/g;
              export var acceptsFile = /.*\.md/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new MarkdownDocHandler();
              }
            
              export class MarkdownDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
                
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-markdown');
              }
            
              
            }
        • sass
          • SassDocHandler.ts
            module portabled.docs.types.text.sass {
            
              export var expectsFile = /.*\.sass/g;
              export var acceptsFile = /.*\.sass/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-sass');
              }
            
              
            }
        • scrollerView
          • ScrollerModel.ts
            module portabled.docs.types.text.scrollerView {
              
              export class ScrollerModel {
            
                lines = ko.observableArray<ScrollerModel.LineModel>([]);
                lineHeight: string;
                private _lineHeightNum: number;
            
                viewportFrom = ko.observable('0');
                viewportHeight = ko.observable('0');
                _debug = null;
            
                private _recreateTimeout = 0;
              
                constructor(
                  private _doc: CodeMirror.Doc,
                  private _viewLineNumber: number) {
            
                  this._lineHeightNum = ((10000 / this._viewLineNumber) | 0) / 100; // exact number of percents
                  this.lineHeight = this._lineHeightNum + '%';
            
                  this._recreateLines();
                }
            
                docChanges(docChanges: CodeMirror.EditorChange[]) {
                  
                  if (this._recreateTimeout)
                    clearTimeout(this._recreateTimeout);
                  this._recreateTimeout = setTimeout(() => this._recreateLines(), 200);
                  
                }
            
                scroll(scrollInfo: CodeMirror.ScrollInfo) {
                  var height = scrollInfo.height;
                  var lineCount = this._doc.lineCount();
                  if (lineCount < this._viewLineNumber)
                    height = Math.max(height, this._doc.getEditor().defaultTextHeight() * this._viewLineNumber);
                  
                  this.viewportFrom((scrollInfo.top * 100 / height) + '%');
                  this.viewportHeight((scrollInfo.clientHeight * 100 / height) + '%');
                  (<any>scrollInfo).maxHeight = height;
                  this._debug = {
                    lineCount: lineCount,
                    heightAtLine: this._doc.getEditor().heightAtLine(lineCount - 2),
                    defaultLineHeight: this._doc.getEditor().defaultTextHeight(),
                    height: height,
                    scrollInfo: scrollInfo
                  };
                }
            
                bindHandlers(dragElement: HTMLElement) {
                  addEventListener(dragElement, 'touchstart', (e: any) => { 
                    if (!e.touches || !e.touches.length) return;
                    var editor = this._doc.getEditor();
                    if (!editor) return;
            
                    var dbg = null;
            
                    var scrollInfo = editor.getScrollInfo();
                    if (scrollInfo.clientHeight === scrollInfo.height) return;
                    var startTop = scrollInfo.top;
                    var startCoord = e.touches[0].clientY;
                    var factor = scrollInfo.clientHeight / scrollInfo.height;
                    var move = e => {
                      if (!e.touches || !e.touches.length) return;
                      var editor = this._doc.getEditor();
                      if (!editor) return;
            
                      var scrollInfo = editor.getScrollInfo();
            
                      var deltaY = e.touches[0].clientY - startCoord;
                      var offset = deltaY * factor;
                      editor.scrollTo(null, scrollInfo.top + deltaY);
                      dbg = 'scrollY->'+ (scrollInfo.top + deltaY)+' factor:'+factor+' deltaY:'+deltaY;
                    };
            
                    var close = e => {
                      alert(dbg);
                      removeEventListener(window, 'touchend', close);
                      removeEventListener(window, 'touchmove', move);
                    };
            
                    addEventListener(window, 'touchmove', move);
                    addEventListener(window, 'touchend', close);
                  });
            
                  addEventListener(dragElement, 'mousedown', (e: MouseEvent) => {
                    var editor = this._doc.getEditor();
                    if (!editor) return;
            
                    var dbg = null;
            
                    var scrollInfo = editor.getScrollInfo();
                    if (scrollInfo.clientHeight === scrollInfo.height) return;
                    var startTop = scrollInfo.top;
                    var startCoord = e.clientY;
                    var factor = scrollInfo.clientHeight / scrollInfo.height;
                    var move = (e: MouseEvent) => {
                      var editor = this._doc.getEditor();
                      if (!editor) return;
            
                      var scrollInfo = editor.getScrollInfo();
            
                      var deltaY = e.clientY - startCoord;
                      var offset = deltaY * factor;
                      editor.scrollTo(null, scrollInfo.top + deltaY);
                    };
            
                    var close = e => {
                      removeEventListener(window, 'mouseup', close);
                      removeEventListener(window, 'mousemove', move);
                    };
            
                    addEventListener(window, 'mousemove', move);
                    addEventListener(window, 'mouseup', close);
                  });
                }
            
                private _recreateLines() {
                  var newLines: ScrollerModel.LineModel[] = [];
                  
                  var docLineCount = this._doc.lineCount();
                  
                  var run: string[] = [];
                  
                  var maxLength = 50;
                  
                  for (var i = 0; i < docLineCount; i++) {
                    run.push(this._doc.getLine(i));
                    if (i > docLineCount * (this._lineHeightNum/100) * (newLines.length+1) 
                        || i === docLineCount - 1) { 
                      var newLine = this._createLine(run);
                      maxLength = Math.max(maxLength, newLine.leadLength + newLine.textLength);
                      newLines.push(newLine);
                      run = [];
                    }
                  }
            
                  for (var i = 0; i < newLines.length; i++) {
                    newLines[i].lineWidth = ((100 * newLines[i].textLength / maxLength) | 0) + '%';
                    newLines[i].lineLead = ((100 * newLines[i].leadLength / maxLength) | 0) + '%';
                  }
            
                  this.lines(newLines);
                  
                  var editor = this._doc.getEditor();
                  if (editor)
                    this.scroll(editor.getScrollInfo());
                }
              
                private _createLine(run: string[]): ScrollerModel.LineModel {
                  return new ScrollerModel.LineModel(run);
                }
            
              }
            
              export module ScrollerModel {
                
                export class LineModel {
            
                  leadLength = 0;
                  textLength = 0;
                  lineWidth: string = null;
               		lineLead: string = null;
            
                  constructor(run: string[]) {
                    this.textLength = 0;
                    for (var i = 0; i < run.length; i++) {
                      var ln = run[i];
            
                      var lead = 0;
                      for (var j = 0; j < ln.length; j++) {
                        if (ln.charAt(j)===' ')
                          lead++;
                        else if (ln.charAt(j)==='\t')
                          lead+=2;
                        else
                          break;
                      }
            
                      this.leadLength += lead;
                      this.textLength += ln.length - j;
                    }
                    this.textLength = (this.textLength / i) | 0;
                  }
                }
                
              }
            }
          • ScrollerView.html
            <div class=portabled-scroller-outer
                 data-bind="load: bindHandlers($element)">
              <div class=portabled-scroller-thumb
                 data-bind="style: { top: viewportFrom, height: viewportHeight }">
              </div>
            </div>
            
            <!-- ko foreach: lines -->
            <div class=portabled-scroller-line
               data-bind="style: { marginLeft: lineLead, width: lineWidth, height: $parent.lineHeight }">
            </div>
            
            <!-- /ko -->
            
          • style.css
            .portabled-scroller-outer {
              float: left;
              width: 0px;
              height: 100%;
            }
            
            .portabled-scroller-thumb {
              position: relative;
              border: solid 3px red;
              width: 2.2em;
              margin: -0.1em;
              opacity: 0.5;
            }
            
            .portabled-scroller-line-host {
              width: 2em;
            }
            
            .portabled-scroller-line {
              background: gray;
              font-size: 3pt;
            }
        • scss
          • ScssDocHandler.ts
            module portabled.docs.types.text.scss {
            
              export var expectsFile = /.*\.scss/g;
              export var acceptsFile = /.*\.scss/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-scss');
              }
            
              
            }
        • ts
          • CodeMirrorCompletion.ts
            module portabled.docs.types.text.ts_ {
              
              export class CodeMirrorCompletion implements CodeMirror.showHint.Completion {
            
                text: string;
                from: CodeMirror.Pos;
                to: CodeMirror.Pos;
            
                constructor(
                  private lead: string,
                  private prefix: string,
                  private suffix: string,
                  private trail: string,
                  private lineNum: number,
                  private _entry: ts.CompletionEntry,
                  private _details: ts.CompletionEntryDetails) {
                  this.text = this._entry.name;
                  this.from = CodeMirror.Pos(lineNum, lead.length);
                  this.to = CodeMirror.Pos(lineNum, lead.length + prefix.length + suffix.length);
                }
            
                render(element: HTMLElement, self, data) {
                  var skipVerbose = 0;
                  if (this._details.displayParts.length > 3
                    && this._details.displayParts[0].text === '('
                    && this._details.displayParts[2].text === ')')
                    skipVerbose = 3;
            
                  element.appendChild(createSpan(
                    this._entry.kind.charAt(0),
                    'portabled-completion-icon portabled-completion-icon-' + this._entry.kind));
            
                  renderSyntaxPart(this._details.displayParts, element, this.text);
            
                  if (this._details.documentation && this._details.documentation.length) {
                    var docSpan = document.createElement('span');
                    docSpan.className = 'portabled-syntax-docs';
                    setTextContent(docSpan, ' // ');
                    renderSyntaxPart(this._details.documentation, docSpan);
                    element.appendChild(docSpan);
                  }
                }
                
              }
            
              var _useTextContent = -1;
              function createSpan(text: string, className: string) {
                var span = document.createElement('span');
                setTextContent(span, text);
                span.className = className;
                return span;
              }
              
            }
          • TypeScriptDocHandler.ts
            module portabled.docs.types.text.ts_ {
            
              export var expectsFile = /.*\.ts/g;
              export var acceptsFile = /.*\.ts/g;
            
              var _typescriptService: typescript.TypeScriptService;
            
              function typescriptService() {
                if (!_typescriptService) {
                  _typescriptService = new typescript.TypeScriptService();
                  build.functions.typescriptBuild.mainTS = _typescriptService;
                }
            
                return _typescriptService;
              }
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new TypeScriptDocHandler();
              }
            
              export class TypeScriptDocHandler
                extends base.SimpleCodeMirrorDocHandler
                implements typescript.ExternalDocument {
            
                private _changes: ts.TextChangeRange[] = [];
            
                private _matchHighlightTimer = new Timer();
                private _matchMarkers: { marker: CodeMirror.TextMarker; offset: number; isCurrent: boolean; }[] = null;
                private _matchMarkersInvalidated = true;
            
                private _statusUpdateTimer = new Timer();
            
                private _autoformatInProgress = false;
                private _foldData: ts.OutliningSpan[];
            
                constructor() {
                  super();
            
                  this.keyMap['Ctrl-,'] = () => this._matchGo(-1);
                  this.keyMap['Ctrl-<'] = () => this._matchGo(-1);
                  this.keyMap['Alt-,'] = () => this._matchGo(-1);
                  this.keyMap['Alt-<'] = () => this._matchGo(-1);
                  this.keyMap['Ctrl-.'] = () => this._matchGo(+1);
                  this.keyMap['Ctrl->'] = () => this._matchGo(+1);
                  this.keyMap['Alt-.'] = () => this._matchGo(+1);
                  this.keyMap['Alt->'] = () => this._matchGo(+1);
            
            
                  this._matchHighlightTimer.interval = 400;
                  this._matchHighlightTimer.ontick = () => this._updateMatchHighlight();
            
                  this._statusUpdateTimer.interval = 200;
                  this._statusUpdateTimer.ontick = () => this._updateStatus();
                }
            
                load(text: string) {
                  typescriptService().addFile(this.path, this);
                }
            
                open() {
                  this._matchHighlightTimer.reset();
                  this._statusUpdateTimer.reset();
            
                  var gutters = <string[]>this.editor.getOption('gutters');
                  if (!gutters || gutters.indexOf('CodeMirror-lint-markers') < 0) {
                    if (!gutters)
                      gutters = [];
                    gutters.push('CodeMirror-lint-markers');
                    this.editor.setOption('gutters', gutters);
                  }
            
                  var foldOptions = this.editor.getOption('foldOptions') || {};
                  foldOptions.rangeFinder = (cm: CodeMirror, pos: CodeMirror.Pos) => {
                    if (!this._foldData)
                    	this._foldData = typescriptService().service().getOutliningSpans(this.path);
                    if (!this._foldData)
                      return;
            
                    var lineStartOffset = this.doc.indexFromPos({ line: pos.line, ch: 0 });
                    var lineLength = this.doc.getLine(pos.line).length;
                    for (var i = 0; i < this._foldData.length; i++) {
                      var sp = this._foldData[i];
                      if (sp.hintSpan.start>=lineStartOffset && sp.hintSpan.start < lineStartOffset + lineLength) {
                        var result = {
                          from: this.doc.posFromIndex(sp.textSpan.start),
                          to: this.doc.posFromIndex(sp.textSpan.start + sp.textSpan.length)
                        };
                        return result;
                      }
                    }
                    return null;
                  };
                  this.editor.setOption('foldOptions', foldOptions);
            
                  this.editor.setOption('lint', () => {
            
                    var resultErrors: { message: string; severity: string; from: any; to: any; }[] = [];
                    if (!this.doc || !this.text || !this.text())
                      return resultErrors;
            
                    var addDiag = (diag: ts.Diagnostic) => {
                      var messageTextOrChain = diag.messageText;
                      var messageText: string;
                      var severity: string;
                      if (typeof messageTextOrChain === 'string') {
                        messageText = messageTextOrChain;
                        severity = diag.category === ts.DiagnosticCategory.Error ? 'error' : 'warning';
                      }
                      else {
                        var chain = messageTextOrChain;
                        messageText = chain.messageText;
                        severity = chain.category === ts.DiagnosticCategory.Error ? 'error' : 'warning';
                        while (chain) {
                          messageText = '\n' + chain.messageText;
                          if (chain.category === ts.DiagnosticCategory.Error)
                            severity = 'error';
                          chain = chain.next;
                        }
                      }
                      resultErrors.push({
                        message: messageText,
                        severity,
                        from: this.doc.posFromIndex(diag.start),
                        to: this.doc.posFromIndex(diag.start + diag.length)
                      });
                    };
            
                    var syntacticDiags = typescriptService().service().getSyntacticDiagnostics(this.path);
                    var semanticDiags = typescriptService().service().getSemanticDiagnostics(this.path);
            
                    if (syntacticDiags) {
                      for (var i = 0; i < syntacticDiags.length; i++) {
                        addDiag(syntacticDiags[i]);
                      }
                    }
            
                    if (semanticDiags) {
                      for (var i = 0; i < semanticDiags.length; i++) {
                        addDiag(semanticDiags[i]);
                      }
                    }
            
                    return resultErrors;
                  });
                }
            
                close() {
                  this._matchHighlightTimer.stop();
                  this._statusUpdateTimer.stop();
                }
            
                shouldTriggerCompletion(textBeforeCursor: string) {
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '.')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                }
            
                getCompletions(): any {
                  var cur = this.doc.getCursor();
                  var curOffset = this.doc.indexFromPos(cur);
            
                  var completions = typescriptService().service().getCompletionsAtPosition(
                    this.path,
                    curOffset);
            
                  if (!completions || !completions.entries.length)
                    return;
            
                  var lineText = this.doc.getLine(cur.line);
                  var prefixLength = 0;
                  while (prefixLength < cur.ch) {
                    var ch = lineText.charAt(cur.ch - prefixLength - 1);
                    if (!isalphanumeric(ch))
                      break;
                    prefixLength++;
                  }
                  var suffixLength = 0;
                  while (cur.ch + suffixLength < lineText.length) {
                    var ch = lineText.charAt(cur.ch + suffixLength);
                    if (!isalphanumeric(ch))
                      break;
                    suffixLength++;
                  }
                  var lead = lineText.slice(0, cur.ch - prefixLength);
                  var prefix = lineText.slice(cur.ch - prefixLength, cur.ch);
                  var suffix = lineText.slice(cur.ch, cur.ch + suffixLength);
                  var trail = lineText.slice(cur.ch + suffixLength);
                  var matchTextLower = prefix.toLowerCase();
            
                  var completionEntries: CodeMirrorCompletion[] = [];
                  for (var i = 0; i < completions.entries.length; i++) {
                    if (completionEntries.length > 16) break;
                    var co = completions.entries[i];
            
                    if (prefixLength && co.name.toLowerCase().indexOf(matchTextLower) < 0)
                      continue;
            
                    var det = typescriptService().service().getCompletionEntryDetails(this.path, curOffset, co.name);
            
                    completionEntries.push(new CodeMirrorCompletion(
                      lead, prefix, suffix, trail, cur.line,
                      co, det));
                  }
            
                  if (!completionEntries.length
                    || (completionEntries.length === 1 && completionEntries[completionEntries.length - 1].text === prefix))
                    return;
            
                  var result: CodeMirror.showHint.CompletionResult = {
                    list: completionEntries,
                    from: CodeMirror.Pos(cur.line, cur.ch - prefixLength),
                    to: cur
                  };
            
                  return result;
                }
            
                onChangesCore(docChanges: CodeMirror.EditorChange[], summary: ChangeSummary) {
            
                  this._foldData = null;
            
                  var tsChanges = ts.createTextChangeRange(
                    ts.createTextSpan(summary.lead, summary.mid),
                    summary.newmid);
            
                  this._changes.push(tsChanges);
            
                  this._matchHighlightTimer.reset();
                  this._matchMarkersInvalidated = true;
            
                  this._statusUpdateTimer.reset();
            
                  this._autoformatAsNeeded(docChanges);
                }
            
                onCursorMoved(cursorPos: CodeMirror.Pos) {
                  this._matchHighlightTimer.reset();
                  this._statusUpdateTimer.reset();
                }
            
                changes(): ts.TextChangeRange[] {
                  return this._changes;
                }
            
                private _autoformatAsNeeded(docChanges: CodeMirror.EditorChange[]) {
            
                  if (this._autoformatInProgress)
                    return;
            
                  var ch = docChanges[docChanges.length - 1];
                  var chText = ch.text.length ? ch.text[ch.text.length - 1] : null;
                  if (!chText && ch.text.length > 1)
                    chText = '\n';
            
                  var lastch = chText.charAt(chText.length - 1);
                  switch (lastch) {
                    case '}':
                    case ';':
                    case '\n':
                      break;
            
                    default:
                      return;
                  }
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  var fmtOps: ts.FormatCodeOptions = {
                    IndentSize: 2,
                    TabSize: 2,
                    NewLineCharacter: '\n',
                    ConvertTabsToSpaces: true,
            
                    InsertSpaceAfterCommaDelimiter: true,
                    InsertSpaceAfterSemicolonInForStatements: true,
                    InsertSpaceBeforeAndAfterBinaryOperators: true,
                    InsertSpaceAfterKeywordsInControlFlowStatements: true,
                    InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
                    InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
                    PlaceOpenBraceOnNewLineForFunctions: false,
                    PlaceOpenBraceOnNewLineForControlBlocks: false
                  };
            
                  var fmtEdits = typescriptService().service().getFormattingEditsAfterKeystroke(
                    this.path,
                    cursorOffset,
                    lastch,
                    fmtOps);
            
                  if (fmtEdits && fmtEdits.length) {
                    this._autoformatInProgress = true;
                    this.editor.operation(() => {
                      for (var i = fmtEdits.length - 1; i >= 0; i--) {
                        var ed = fmtEdits[i];
                        var from = this.doc.posFromIndex(ed.span.start);
                        var to = this.doc.posFromIndex(ed.span.start + ed.span.length);
                        this.doc.replaceRange(ed.newText, from, to);
                      }
                    });
                    this._autoformatInProgress = false;
                  }
            
                }
            
                private _addDiag(d: ts.Diagnostic, kind: string) {
            
                  var tsFrom = d.file.getLineAndCharacterOfPosition(d.start); // zero-based
                  var tsTo = d.file.getLineAndCharacterOfPosition(d.start + d.length); // zero-based
            
                  var marker = this.doc.markText(
                    CodeMirror.Pos(tsFrom.line, tsFrom.character),
                    CodeMirror.Pos(tsTo.line, tsTo.character), {
                      className: 'portabled-diag portabled-diag-' + kind + ' portabled-diag-' + ts.DiagnosticCategory[d.category]
                    });
            
                  marker['__error'] = d;
                }
            
                private _updateMatchHighlight() {
                  if (!this.doc && !this.editor)
                    return;
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
                  if (!this._matchMarkersInvalidated && this._matchMarkers) {
                    for (var i = 0; i < this._matchMarkers.length; i++) {
                      var m = this._matchMarkers[i];
                      var pos = m.marker.find();
                      if (pos && compareSign(pos.from, cursor) <= 0 && compareSign(cursor, pos.to) <= 0) {
                        if (m.isCurrent) {
                          // all is well
                          return;
                        }
                      }
                    }
                  }
            
                  var newMatches = typescriptService().service().getOccurrencesAtPosition(this.path, cursorOffset);
            
                  this.editor.operation(() => {
            
                    if (this._matchMarkers) {
                      for (var i = 0; i < this._matchMarkers.length; i++) {
                        this._matchMarkers[i].marker.clear();
                      }
                    }
                    this._matchMarkers = [];
            
                    if (!newMatches)
                      return;
            
                    for (var i = 0; i < newMatches.length; i++) {
                      var m = newMatches[i];
                      if (m.fileName !== this.path)
                        continue;
            
                      var from = this.doc.posFromIndex(m.textSpan.start);
                      var to = this.doc.posFromIndex(m.textSpan.start + m.textSpan.length);
            
                      var isCurrent = cursorOffset >= m.textSpan.start && cursorOffset <= m.textSpan.start + m.textSpan.length;
            
                      var marker = this.doc.markText(
                        from,
                        to,
                        {
                          className: isCurrent ? 'portabled-match portabled-match-current' : 'portabled-match'
                        });
                      this._matchMarkers.push({ marker: marker, offset: m.textSpan.start, isCurrent: isCurrent });
            
                    }
            
                    this._matchMarkers.sort((m1, m2) => m1.offset - m2.offset);
            
                  });
            
                  this._matchMarkersInvalidated = false;
            
                }
            
                private _matchGo(dir: number) {
                  if (!this.doc && !this.editor)
                    return;
            
                  if (this._matchHighlightTimer.isWaiting())
                    this._matchHighlightTimer.endWaiting();
                  if (!this._matchMarkers)
                    this._updateMatchHighlight();
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  for (var matchIndex = 0; matchIndex < this._matchMarkers.length; matchIndex++) {
                    var m = this._matchMarkers[matchIndex];
                    if (m.isCurrent)
                      break;
                  }
            
                  if (matchIndex >= this._matchMarkers.length)
                    return;
            
                  var newMatchIndex = matchIndex + dir;
                  if (newMatchIndex < 0)
                    newMatchIndex = this._matchMarkers.length - 1;
                  else if (newMatchIndex >= this._matchMarkers.length)
                    newMatchIndex = 0;
            
                  var innerOffset = cursorOffset - this._matchMarkers[matchIndex].offset;
                  var newCursorOffset = this._matchMarkers[newMatchIndex].offset + innerOffset;
                  var newCursor = this.doc.posFromIndex(newCursorOffset);
            
                  this.doc.setCursor(newCursor);
                  this._updateMatchHighlight();
            
                }
            
                private _updateStatus() {
                  if (!this.editor)
                    return;
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  var signature = typescriptService().service().getSignatureHelpItems(this.path, cursorOffset);
                  if (signature && signature.items.length) {
                    setTextContent(this.status, '');
            
                    var si = signature.items[signature.selectedItemIndex || 0];
                    if (si.prefixDisplayParts)
                      renderSyntaxPart(si.prefixDisplayParts, this.status);
            
                    if (si.parameters) {
                      for (var i = 0; i < si.parameters.length; i++) {
                        if (i > 0)
                          renderSyntaxPart(si.separatorDisplayParts, this.status);
                        if (i === signature.argumentIndex) {
                          var paramHighlight = document.createElement('span');
                          paramHighlight.className = 'portabled-syntax-current';
                          renderSyntaxPart(si.parameters[i].displayParts, paramHighlight);
                          this.status.appendChild(paramHighlight);
                        }
                        else {
                          renderSyntaxPart(si.parameters[i].displayParts, this.status);
                        }
                      }
                    }
            
                    if (si.suffixDisplayParts)
                      renderSyntaxPart(si.suffixDisplayParts, this.status);
            
                    if (si.documentation && si.documentation.length) {
                      var docSpan = document.createElement('span');
                      docSpan.className = 'portabled-syntax-docs';
                      setTextContent(docSpan, ' // ');
                      renderSyntaxPart(si.documentation, docSpan);
                      this.status.appendChild(docSpan);
                    }
            
                  }
                  else {
            
                    var qi = typescriptService().service().getQuickInfoAtPosition(this.path, cursorOffset);
                    if (qi && qi.displayParts) {
                      setTextContent(this.status, '');
            
                      var skipUntilCloseBracket = true;
                      for (var i = 0; i < qi.displayParts.length; i++) {
                        var dip = qi.displayParts[i];
                        if (skipUntilCloseBracket) {
                          if (dip.text === ')')
                            skipUntilCloseBracket = false;
                          continue;
                        }
                        if (!dip.text)
                          continue; // TS really does inject empty tokens
            
                        var sp = document.createElement('span');
                        if ('textContent' in sp)
                          sp.textContent = dip.text;
                        else
                          sp.innerText = dip.text;
                        sp.className = 'portabled-syntax-' + dip.kind;
            
                        this.status.appendChild(sp);
                      }
            
                      if (qi.documentation && qi.documentation.length) {
                        var sp = document.createElement('span');
                        var sp = document.createElement('span');
                        if ('textContent' in sp)
                          sp.textContent = ' // ';
                        else
                          sp.innerText = ' // ';
                        sp.className = 'portabled-syntax-comment';
                        this.status.appendChild(sp);
            
                        for (var i = 0; i < qi.documentation.length; i++) {
                          var dip = qi.documentation[i];
            
                          if (!dip.text)
                            continue; // TS really does inject empty tokens
            
                          var sp = document.createElement('span');
                          if ('textContent' in sp)
                            sp.textContent = dip.text;
                          else
                            sp.innerText = dip.text;
                          sp.className = 'portabled-syntax-' + dip.kind;
            
                          this.status.appendChild(sp);
                        }
                      }
                    }
                    else {
                      if ('textContent' in this.status)
                        this.status.textContent = this.path;
                      else
                        this.status.innerText = this.path;
                    }
                  }
            
                  var def = typescriptService().service().getDefinitionAtPosition(this.path, cursorOffset);
                  if (def && def.length) {
                    var defSpan = document.createElement('span');
                    var shortFileName = def[0].fileName.slice(def[0].fileName.lastIndexOf('/')+1);
                    setTextContent(defSpan, ' @' + shortFileName + ' ' + def[0].containerKind + ' ' + def[0].containerName);
                    defSpan.style.color = 'cornflowerblue';
                    this.status.appendChild(defSpan);
                  }
            
                }
            
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/typescript');
              }
            
              function compareSign(p1: CodeMirror.Pos, p2: CodeMirror.Pos) {
                if (p1.line > p2.line)
                  return 1;
                else if (p1.line < p2.line)
                  return -1;
                else if (p1.ch > p2.ch)
                  return 1;
                else if (p1.ch < p2.ch)
                  return -1;
                else
                  return 0;
              }
            
              function isalphanumeric(ch: string) {
                if (ch >= '0' && ch <= '9') return true;
                if (ch >= 'A' && ch <= 'Z') return true;
                if (ch >= 'a' && ch <= 'z') return true;
                if (ch === '_' || ch === '$') return true;
                if (ch.charCodeAt(0) < 128) return false;
                // slow Unicode path
                return ch.toLowerCase() !== ch.toUpperCase();
              }
            
            }
          • renderSyntaxPart.ts
            module portabled.docs.types.text.ts_ {
            
              export function renderSyntaxPart(syntax: ts.SymbolDisplayPart[], element: HTMLElement, skipUntil?: string): void {
                var skipping = skipUntil ? true : false;
            
                for (var i = 0; i < syntax.length; i++) {
                  var p = syntax[i];
                  if (!p.text) continue;
            
                  if (skipping) {
                    if (p.text === skipUntil)
                      skipping = false;
                    else
                    	continue;
                  }
            
                  var sp = document.createElement('span');
                  setTextContent(sp, p.text);
                  sp.className = 'portabled-syntax-'+p.kind;
            
                  element.appendChild(sp);
                }
              }
            
              
            }
          • style.css
            .portabled-completion-icon {
              border: solid 1px black;
              font-size: 0.8;
              display: inline-block;
              width: 1.5em;
              margin: 2px;
              margin-right: 0.3em;
              text-align: center;
              border-radius: 3px;
            }
            
            .portabled-completion-icon-local {
              border-color: fuchsia;
              color: fuchsia;
              background: lavenderblush;
            }
            
            .portabled-completion-icon-function {
              border-color: green;
              color: green;
              background: honeydew;
            }
            
            .portabled-syntax-moduleName {
              opacity: 0.3;
            }
            
            .portabled-syntax-className {
              opacity: 0.5;
            }
            
            .portabled-syntax-propertyName {
              font-weight: bold;
            }
            
            .portabled-syntax-methodName {
              font-weight: bold;
            }
            
            .portabled-syntax-keyword {
              opacity: 0.7;
            }
            
            .portabled-syntax-current {
              font-weight: bold;
            }
            
            .portabled-syntax-docs {
              opacity: 0.8;
            }
            
            
            .portabled-match {
              background: silver;
              background: rgba(20, 120, 0, 0.08);
              background: linear-gradient(rgba(20,120,0,0), rgba(20,120,0,0.02), rgba(20,120,0,0.2));
              border-bottom: solid 2px rgba(20,120,0,0.3);
            }
            
            .portabled-match-current {
              background: silver;
              background: rgba(20, 120, 0, 0.08);
              background: linear-gradient(rgba(20,120,0,0), rgba(20,120,0,0.01), rgba(20,120,0,0.2));
              border-bottom: solid 3px rgba(20,120,0,0.3);
            }
            
            
            .portabled-diag-syntactic {
              background: solid coral 3px;
              background: rgba(255, 127, 80, 0.4);
              border-bottom: solid 4px tomato;
            }
            
            .portabled-diag-semantic {
              background: gold;
              background: rgba(255, 215, 0, 0.4);
              border-bottom: solid 4px orange;
            }
            
        • CodeMirror-ext.css
          .CodeMirror {
            height: 100%;
            font-family: inherit;
            font-size: inherit;
          }
          
          .CodeMirror-hints {
            font-family: inherit;
          }
          .CodeMirror-hint {
            max-width: 52em;
            max-height: 4.5em;
            overflow-x: inherit;
            overflow-y: hidden;
            white-space: normal;
          }
          
          .CodeMirror .cm-trailingspace {
            background: linear-gradient(to right, cornflowerblue -5%, transparent 50%, gold 100%)
          }
        • CodeMirrorDocHandler.ts
          module portabled.docs.types.text {
          
            export class CodeMirrorDocHandler implements DocHandler {
          
              static codeMirrorEditorPools: { [moduleName: string]: CodeMirror[]; } = {};
          
              private _closures = {
                cm_change: (cm, docChange) => this._docSingleChange(docChange),
                cm_changes: (cm, docChanges) => this._docChanges(docChanges),
                cm_cursorActivity: (cm) => this._cursorActivity(),
                cm_scroll: (cm) => this._scroll()
              };
          
              private _saveTimer = new Timer();
          
              private _appliedKeyMap = null;
          
              private _scrollerModel: scrollerView.ScrollerModel = null;
          
              private _retrievedText: string = null;
              private _validLead: number = -1;
              private _validTrail: number = 0;
              private _totalLength: number = 0;
          
              private _newValidLead: number = -1;
              private _newValidTrail: number = -1;
          
              constructor(
                public path: string,
                public storage: DocState,
                public textDoc: CodeMirrorTextDoc,
                public moduleName: string,
                public moduleObj: TextHandlerModule) {
          
                this._saveTimer.ontick = () => this._save();
          
                this.textDoc.path = path;
          
                this.textDoc.text = () => this.text();
          
                if (this.textDoc.load) {
                  var text = this.storage.read();
                  this.textDoc.load(text);
                }
          
              }
          
              showEditor(regions: DocHostRegions): void {
          
                if (!this.textDoc.doc) {
                  if (!this._retrievedText && typeof this._retrievedText !== 'string') {
                    this._retrievedText = this.storage.read();
                    this._validLead = -1;
                    this._validTrail = 0;
                    this._totalLength = this._retrievedText.length;
                  }
          
                  this.textDoc.doc = (this.moduleObj && this.moduleObj.createCodeMirrorDoc) ?
                    this.moduleObj.createCodeMirrorDoc(this.storage.read()) :
                    createCodeMirrorDoc(this._retrievedText);
                }
          
          
                var cmPool =
                  CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''] ||
                  (CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''] = []);
          
                if (cmPool.length) {
                  this.textDoc.editor = cmPool.pop();
                  // avoid zoom on focus
                  this.textDoc.editor.getInputField().style.fontSize = '16px';
          
                  regions.content.appendChild(this.textDoc.editor.getWrapperElement());
                }
                else {
                  this.textDoc.editor = (this.moduleObj && this.moduleObj.createCodeMirrorEditor) ?
                    this.moduleObj.createCodeMirrorEditor(regions.content) :
                    createCodeMirrorEditor(regions.content);
          
                  this._appliedKeyMap = this.textDoc.keyMap;
                  if (this._appliedKeyMap) {
                    this._appliedKeyMap = CodeMirror.normalizeKeyMap(this._appliedKeyMap);
                    this.textDoc.editor.addKeyMap(this._appliedKeyMap);
                  }
                }
          
                if (this.textDoc.editor.getDoc() !== this.textDoc.doc)
                  this.textDoc.editor.swapDoc(this.textDoc.doc);
          
                try {
                  this.textDoc.editor.focus();
                }
                catch (e) { }
          
                setTimeout(() => {
                  if (this.textDoc.editor && this.textDoc.editor.getDoc() === this.textDoc.doc) {
                    this.textDoc.editor.refresh();
                    this.textDoc.editor.focus();
                    this._scroll();
                  }
                }, 2);
          
          
                this.textDoc.editor.on('change', this._closures.cm_change);
                this.textDoc.editor.on('changes', this._closures.cm_changes);
                this.textDoc.editor.on('cursorActivity', this._closures.cm_cursorActivity);
                this.textDoc.editor.on('scroll', this._closures.cm_scroll);
          
          
                if (!this._scrollerModel) {
                  this._scrollerModel = new scrollerView.ScrollerModel(this.textDoc.doc, 300);
                }
          
                if (!this.textDoc.scroller) {
                  this.textDoc.scroller = document.createElement('div');
                  this.textDoc.scroller.style.width = '100%';
                  this.textDoc.scroller.style.height = '100%';
                  ko.renderTemplate('ScrollerView', this._scrollerModel, null, this.textDoc.scroller);
                }
          
                regions.scroller.appendChild(this.textDoc.scroller);
          
                if (!this.textDoc.status) {
                  this.textDoc.status = document.createElement('div');
                  this.textDoc.status.style.width = '100%';
                  this.textDoc.status.style.height = '100%';
                  this.textDoc.status.textContent = this.path;
                }
          
                regions.status.appendChild(this.textDoc.status);
          
                if (this.textDoc.open)
                  this.textDoc.open();
          
          
              }
          
              hideEditor(): void {
          
                this._saveTimer.endWaiting();
          
                if (!this.textDoc || !this.textDoc.doc)
                  return;
          
                this.textDoc.editor.off('changes', this._closures.cm_changes);
                this.textDoc.editor.off('cursorActivity', this._closures.cm_cursorActivity);
                this.textDoc.editor.off('scroll', this._closures.cm_scroll);
          
                if (this._appliedKeyMap) {
                  this.textDoc.editor.removeKeyMap(this._appliedKeyMap);
                  this._appliedKeyMap = null;
                }
          
                if (this.textDoc.close)
                  this.textDoc.close();
          
                var editor = this.textDoc.editor;
                this.textDoc.editor = null;
          
                editor.swapDoc(new CodeMirror.Doc(''));
          
                var cmPool =
                  CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''];
          
                cmPool.push(editor);
              }
          
              remove(): void {
                this._saveTimer.stop();
          
                if (!this.textDoc || !this.textDoc.doc)
                  return;
          
                if (this.textDoc.remove)
                  this.textDoc.remove();
          
                this.textDoc.doc = null;
              }
          
              text(): string {
          
                var doc = this.textDoc.doc;
                if (!this._retrievedText && typeof this._retrievedText !== 'string') {
                  this._retrievedText = doc ? doc.getValue() : this.storage.read();
                  this._totalLength = this._retrievedText ? this._retrievedText.length : 0;
                  this._validLead = -1;
                  return this._retrievedText;
                }
          
                if (this._validLead < 0)
                  return this._retrievedText;
          
                var lineCount = doc.lineCount();
                var totalLength = doc.indexFromPos({
                  line: lineCount - 1,
                  ch: doc.getLine(lineCount - 1).length
                });
          
                if (this._validLead + this._validTrail === this._retrievedText.length
                  && this._retrievedText.length === totalLength)
                  return this._retrievedText;
          
                if (this._validLead + this._validTrail < totalLength / 4) { // if more than 0.75 of the document is modified
                  this._retrievedText = doc.getValue();
                  this._validLead = -1;
                  return this._retrievedText;
                }
          
                var mid = doc.getRange(
                  doc.posFromIndex(this._validLead),
                  doc.posFromIndex(totalLength - this._validTrail));
          
                this._retrievedText =
                this._retrievedText.slice(0, this._validLead) +
                mid +
                this._retrievedText.slice(this._retrievedText.length - this._validTrail);
                this._validLead = -1;
          
          
                return this._retrievedText;
              }
          
              private _docSingleChange(docChange: CodeMirror.EditorChange) {
                var doc = this.textDoc.doc;
          
                var newValidLead = doc.indexFromPos(docChange.from);
                var newValidTrail = this._totalLength - newValidLead - totalLength(docChange.removed);
          
                if (this._newValidLead < 0 || this._newValidLead > newValidLead)
                  this._newValidLead = newValidLead;
                if (this._newValidTrail < 0 || this._newValidTrail > newValidTrail)
                  this._newValidTrail = newValidTrail;
              }
          
              private _docChanges(docChanges: CodeMirror.EditorChange[]) {
          
                var doc = this.textDoc.doc;
          
                var lineCount = doc.lineCount();
                var newTotalLength = doc.indexFromPos({
                  line: lineCount - 1,
                  ch: doc.getLine(lineCount - 1).length
                });
          
                var changeLead = this._newValidLead;
                var changeTrail = this._newValidTrail;
          
                this._newValidLead = -1;
                this._newValidTrail = -1;
          
          
                if (this._validLead < 0) {
                  this._validLead = changeLead;
                  this._validTrail = changeTrail;
                }
                else {
                  this._validLead = Math.min(this._validLead, changeLead);
                  this._validTrail = Math.min(this._validTrail, changeTrail);
                }
          
                var changeSummary = {
                  lead: changeLead,
                  mid: this._totalLength - changeLead - changeTrail,
                  newmid: 0,
                  trail: changeTrail
                };
                changeSummary.newmid = newTotalLength - changeLead - changeTrail;
          
                this._totalLength = newTotalLength;
          
                if (this.textDoc.onChanges) {
                  this.textDoc.onChanges(docChanges, changeSummary);
                }
          
                if (this._scrollerModel)
                  this._scrollerModel.docChanges(docChanges);
          
                this._saveTimer.interval = (this.moduleObj && this.moduleObj.saveDelay) || saveDelay;
                this._saveTimer.reset();
          
              }
          
              private _cursorActivity() {
                if (this.textDoc.onCursorMoved) {
                  var cursorPos = this.textDoc.doc.getCursor();
                  //this.textDoc.status.textContent = 'token '+this.textDoc.editor.getTokenAt(cursorPos).type;
                  this.textDoc.onCursorMoved(cursorPos);
                }
          
                // TODO: scroller/thickBar cursor activity
          
              }
          
              private _scroll() {
                var scr = this.textDoc.editor.getScrollInfo();
                if (this.textDoc.onScroll)
                  this.textDoc.onScroll(scr);
          
                if (this._scrollerModel)
                  this._scrollerModel.scroll(scr);
          
              }
          
              private _save() {
                this.storage.write(this.text());
              }
          
            }
          
            function totalLength(lines: string[]): number {
              var length = 0;
              for (var i = 0; i < lines.length; i++) {
                length += lines[i].length;
              }
              if (lines.length > 1)
                length += lines.length - 1;
              return length;
            }
          }
        • api.ts
          module portabled.docs.types.text {
            
            export interface TextHandlerModule {
          
              loadText(path: string, storage: DocState): CodeMirrorTextDoc;
              
              expectsFile: RegExp;
              acceptsFile?: RegExp;
          
              createCodeMirrorEditor?: (host: HTMLElement) => CodeMirror;
              createCodeMirrorDoc?: (text: string) => CodeMirror.Doc;
              
              saveDelay?: number;
          
            }
            
            export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
              return {
                path: null,
                editor: null,
                doc: null,
                text: null,
                scroller: null,
                status: null,
                state: null,
                open: null,
                close: null,
                remove: null
              };
            }
          
            export interface CodeMirrorTextDoc {
          
              path: string;
              editor: CodeMirror;
              doc: CodeMirror.Doc;
              text: () => string;
              scroller: HTMLElement;
              status: HTMLElement;
              removed?: boolean;
          
              state: any;
          
              load?: (text: string) => void;
          
              open();
              close();
              remove();
          
              onCursorMoved?: (cursorPos: CodeMirror.Pos) => void;
              onScroll?: (scrollInfo: CodeMirror.ScrollInfo) => void;
          
              onChanges?: (
                docChanges: CodeMirror.EditorChange[],
                summary: ChangeSummary) => void;
          
              onSave?: () => void;
          
              keyMap?: any;
            }
          
            export interface ChangeSummary {
              lead: number;
              mid: number;
              newmid: number;
              trail: number;
            }
          
            export function createCodeMirrorEditor(host: HTMLElement): CodeMirror {
              return new CodeMirror(host, {
                  lineNumbers: true,
                  matchBrackets: true,
                  autoCloseBrackets: true,
                  matchTags: true,
                  showTrailingSpace: true,
                  autoCloseTags: true,
                	foldGutter: true,
              		gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                  //highlightSelectionMatches: {showToken: /\w/},
                  styleActiveLine: true,
                  tabSize: 2
                });
            }
            
            export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
              return new CodeMirror.Doc(text || '');
            }
          
          }
        • load.ts
          module portabled.docs.types.text {
          
            export var expectsFile = /.*\.txt/g;
            export var acceptsFile = /.*/g;
            
            export var saveDelay = 700;
          
            export function load(path: string, storage: DocState): DocHandler {
          
              var submodules = listSubmodules<TextHandlerModule>(portabled.docs.types.text, 'loadText');
              for (var i = 0; i < submodules.length; i++) {
          
                var match = path.match(submodules[i].moduleObj.expectsFile);
                if (match && match.length && match[0] === path) {
                  var textDoc = submodules[i].moduleObj.loadText(path, storage);
                  if (textDoc)
                    return new CodeMirrorDocHandler(path, storage, textDoc, submodules[i].moduleName, submodules[i].moduleObj);
                }
          
              }
              
              for (var i = 0; i < submodules.length; i++) {
          
                if (submodules[i].moduleObj.acceptsFile) { 
                  var match = path.match(submodules[i].moduleObj.acceptsFile);
                  if (!match || !match.length || match[0] !== path) continue;
                }
          
                var textDoc = submodules[i].moduleObj.loadText(path, storage);
                if (textDoc)
                  return new CodeMirrorDocHandler(path, storage, textDoc, submodules[i].moduleName, submodules[i].moduleObj);
              }
          
              var textDoc = portabled.docs.types.text.loadText(path, storage);
              return new CodeMirrorDocHandler(
                path, storage, textDoc,
                null, null);
              
            }
            
            
            
          
            
          }
      • api.ts
        /**
         * Add your generic document type handlers to nested modules
         * inside 'types' module.
         * Define load function in the same way load function is defined here below.
         */
        module portabled.docs.types {
        
          /**
           * Document handlers modules are expected to export these members.
           */
          export interface DocHandlerModule {
            
            load(path: string, storage: DocState): DocHandler;
            
            expectsFile: RegExp;
            acceptsFile?: RegExp;
        
          }
          
          /**
           * Default type loading.
           * Other handlers should conform to the same signature, and be on the child modules, like so:
           * module portabled.docs.types.text { function load(...); }
           */
          declare function load(path: string, storage: DocState): DocHandler;
        
          export interface DocHandler {
        
            showEditor(regions: DocHostRegions): void;
            hideEditor(): void;
        
            // TODO: implement icons like this:
            //
            // load(context: { iconText(text: string): void; iconColor(color: string): void; }): void;
        
            remove();
        
          }
        
          export interface DocHostRegions {
            content: HTMLElement;
            scroller: HTMLElement;
            status: HTMLElement;
          }
        
          
          export interface DocState {
            read(): string;
            write(content: string);
            
            readState(): any;
            writeState(state: any);
          }
        
        
        }
      • listSubmodules.ts
        module portabled.docs.types {
          
          export function listSubmodules<T>(
            parentModule: any,
            loadFunctionName: string) {
            
            var result: { moduleName: string; moduleObj: T; }[] = parentModule.__cachedSubmoduleList;
        
            if (!result) {
              result = parentModule.__cachedSubmoduleList = [];
        
              for (var moduleName in parentModule) if (parentModule.hasOwnProperty(moduleName)) {
                var moduleObj = parentModule[moduleName];
                if (moduleObj && typeof moduleObj === 'object'
                  && moduleName.charAt(0).toUpperCase() !== moduleName.charAt(0)
                  && moduleObj[loadFunctionName] && typeof moduleObj[loadFunctionName] === 'function'
                  && moduleObj.expectsFile) {
                  result.push({ moduleName: moduleName, moduleObj: moduleObj });
                }
              }
              
              parentModule.__cachedSubmoduleList = result;
            }
        
            return result;
          }
          
        }
      • load.ts
        module portabled.docs.types {
          
          export function load(path: string, storage: DocState): DocHandler {
           
            var submodules = listSubmodules<DocHandlerModule>(portabled.docs.types, 'load');
            for (var i = 0; i < submodules.length; i++) {
        
              var match = path.match(submodules[i].moduleObj.expectsFile);
              if (match && match.length && match[0] === path) {
                var docHandler = submodules[i].moduleObj.load(path, storage);
                if (docHandler)
                  return docHandler;
              }
        
            }
            
            for (var i = 0; i < submodules.length; i++) {
        
              if (submodules[i].moduleObj.acceptsFile) { 
                var match = path.match(submodules[i].moduleObj.acceptsFile);
                if (!match || !match.length || match[0] !== path) continue;
              }
        
              var docHandler = submodules[i].moduleObj.load(path, storage);
              if (docHandler)
                return docHandler;
            }
        
            return null;
          }
          
        }
    • DocHost.ts
      module portabled.docs {
        
        export class DocHost {
      
          private _docs: { [file: string]: docs.types.DocHandler; } = {};
      
          private _activeHandler: docs.types.DocHandler = null;
      
          constructor(
            private _regions: docs.types.DocHostRegions,
            private _drive: persistence.Drive) {
      
            var files = this._drive.files();
            for (var i = 0; i < files.length; i++) {
              this.add(files[i]);
            }
      
          }
        
          show(file: string) {
      
            var oldHandler = this._activeHandler;
            var oldElements: Element[] = [];
      
            if (this._regions.content) {
              for (var i = 0; i < this._regions.content.children.length; i++) {
                oldElements.push(this._regions.content.children[i]);
              }
            }
      
            if (this._regions.scroller) {
              for (var i = 0; i < this._regions.scroller.children.length; i++) {
                oldElements.push(this._regions.scroller.children[i]);
              }
            }
      
             if (this._regions.status) {
              for (var i = 0; i < this._regions.status.children.length; i++) {
                oldElements.push(this._regions.status.children[i]);
              }
            }
      
            try {
              this._activeHandler = this._docs[file];
              if (!this._activeHandler) {
      
                if (file === null)
                  return; // one of expected values here
      
                // TODO: handle unopenable file
                return;
              }
      
              this._activeHandler.showEditor(this._regions);
            }
            finally {
      
              if (oldHandler && oldHandler.hideEditor) {
                oldHandler.hideEditor();
              }
      
              for (var i = 0; i < oldElements.length; i++) {
                oldElements[i].parentNode.removeChild(oldElements[i]);
              }
      
            }
          }
      
          add(file: string) {
            var docState = new DocState(file, this._drive);
            var docHandler = docs.types.load(file, docState);
            this._docs[file] = docHandler;
          }
      
          remove(file: string) {
      
            var openAnotherFile = false;
            
            var docHandler = this._docs[file];
            if (docHandler) {
      
              openAnotherFile = true;
      
              if (this._activeHandler === docHandler) {
                this.show(null);
              }
      
              docHandler.remove();
      
              delete this._docs[file];
            }
            
            if (openAnotherFile) {
              // TODO: show another file
            }
          }
          
        }
      
        class DocState implements docs.types.DocState {
          
          constructor(private _file: string, private _drive: persistence.Drive) {
          }
      
          read(): string {
            return this._drive.read(this._file);
          }
      
          write(content: string) {
            this._drive.timestamp = Date.now ? Date.now() : +new Date();
            this._drive.write(this._file, content);
          }
          
          readState(): any {
            // TODO...
          }
      
          writeState(state: any) {
            // TODO...
          }
          
        }
        
      }
  • files
    • FileTree.css
      .portabled-file-tree {
        padding-left: 0.1em;
      }
      
      .portabled-file-tree ul {
        margin: 1px;
        margin-left: 0px;
        padding-left: 0.4em;
      }
      
      .portabled-file-tree ul li {
        margin: 0px;
        padding: 0px;
      }
      
      .portabled-file-tree li .portabled-file-name {
        padding: 1px;
        margin-left: -1em;
        padding-left: 1em;
        cursor: pointer;
        border: solid 1px transparent;
      }
      
      .portabled-file-tree ul li .portabled-file-name:hover {
        border: solid 1px gold;
      }
      
      .portabled-file-tree li .portabled-dir-name {
        padding: 1px;
        margin-left: -1em;
        padding-left: 1em;
        font-weight: bold;
        cursor: pointer;
        border: solid 1px transparent;
      }
      
      .portabled-file-tree ul li .portabled-dir-name:hover {
        border: solid 1px gold;
      }
      
      
      .portabled-file-tree li.portabled-dir {
        list-style: none;
        cursor: default;
      }
      
      .portabled-file-tree li.portabled-dir::before {
        content: "\25bc";
      }
      
      .portabled-file-tree li.portabled-dir-collapsed::before {
        content: "\25ba";
      }
      
      .portabled-file-tree .portabled-dir-collapsed ul {
        display: none;
      }
      
      
      
      .portabled-file-tree li.portabled-file {
        list-style: none;
      }
      
      .portabled-file-tree li.portabled-file::before {
        content: "\25a1";
        padding-right: 0.2em;
      }
      
      .portabled-file-tree .portabled-file-selected .portabled-file-name {
        background: cornflowerblue;
        background: rgba(100,149,237,0.5);
      }
      
      
      .portabled-file-content {
        display: none;
      }
      
    • FileTree.ts
      module portabled.files {
        
        export class FileTree implements persistence.Drive {
      
          private _virtualRoot: Node;
          private _allFiles: { [file: string]: Node; } = {};
          private _selectedFileNode = ko.observable<Node>(null);
      
          selectedFile = ko.computed<string>({
            read: () => {
              var n = this._selectedFileNode();
              return n ? n.fullPath : null;
            },
            write: (value) => {
              var node = this._allFiles[value] || null;
              if (node || value === null || value === undefined)
                this._selectFileNode(node);
            }
          });
          
          timestamp: number = 0;
      
          constructor(private _host: HTMLElement) {
      
            var domSelection = { selectedFile: null };
            this._virtualRoot = new Node(null, <any>this._host, this._allFiles, domSelection);
            
            if (domSelection.selectedFile)
              this.selectedFile(domSelection.selectedFile);
            
            try {
              var timestamStr = this._virtualRoot.readAttr('timestamp');
              this.timestamp = timestamStr ? parseInt(timestamStr) : 0;
            }
            catch (parseError) {
              this.timestamp = 0;
            }
      
            addEventListener(this._host, 'click', e => this._onClick(<any>e));
          }
      
          files(): string[] {
            return objectKeys(this._allFiles);
          }
      
          read(file: string): string {
            var n = this._allFiles[file];
            if (n)
              return n.read();
            else
              return null;
          }
      
          write(file: string, content: string) {
            var n = this._allFiles[file];
            if (!n) {
              file = normalizePath(file);
              n = this._allFiles[file];
            }
      
            if (n) {
              if (content || typeof content === 'string') {
                n.write(content);
              }
              else {
                n.parent.remove(n);
                delete this._allFiles[file];
              }
            }
            else {
              if (!content && typeof content !== 'string')
                return;
      
              var newFile = this._createFile(file);
              newFile.write(content);
            }
            
            this._virtualRoot.writeAttr('timestamp', this.timestamp + '');
          }
          
          private _createFile(file: string): Node {
            var lastSlashPos = file.lastIndexOf('/');
            if (lastSlashPos) { // slash in position other than lead
              var parentDir = file.slice(1, lastSlashPos);
              var fileName = file = file.slice(lastSlashPos + 1);
              var parent = this._virtualRoot.findOrCreateDir(parentDir);
              var node = parent.createFile(fileName);
              this._allFiles[node.fullPath] = node;
              return node;
            }
            else { 
              var node = this._virtualRoot.createFile(file.slice(1));
              this._allFiles[node.fullPath] = node;
              return node;
            }
          }
          
          private _onClick(e: MouseEvent) {
            var node = this._getNode(<any>e.target || <any>e.srcElement);
            if (!node) return;
            if (node === this._virtualRoot) return;
            
            if (node.isDir) {
              node.toggleCollapse();
            }
            else {
              this._selectFileNode(node);
            }
            
          }
          
          private _selectFileNode(node: Node) {
            var oldSelected = this._selectedFileNode();
            if (oldSelected) {
              oldSelected.setSelectClass(false);
            }
            
            if (node)
              node.setSelectClass(true);
            
            this._selectedFileNode(node);
          }
          
          private _getNode(elem: HTMLElement): Node {
            while (elem) {
              var node = (<any>elem)._portabled_node;
              if (node) return node;
              elem = elem.parentElement;
              if (!elem)
                return null;
            }
          }
      
        }
      
        class Node {
      
          isDir: boolean = false;
          name: string = null;
          fullPath: string = null;
      
          private _contentPRE: HTMLPreElement = null;
          private _subDirs: Node[] = [];
          private _files: Node[] = [];
          private _ul: HTMLUListElement = null;
          
          constructor(
            public parent: Node,
            public li: HTMLElement,
            allFiles: { [file: string]: Node; },
            selection: { selectedFile: string; }) {
              
            (<any>li)._portabled_node = this;
            
            var childLIs: HTMLLIElement[] = [];
            for (var i = 0; i < this.li.children.length; i++) {
      
              var child = this.li.children[i];
              if ((<HTMLLIElement>child).tagName === 'LI') childLIs.push(<HTMLLIElement>child);
              if ((<HTMLUListElement>child).tagName === 'UL') {
                this._ul = <HTMLUListElement>child;
                for (var j = 0; j < this._ul.children.length; j++) {
                  var ulLI = <HTMLLIElement>this._ul.children[j];
                  if (ulLI.tagName === 'LI') childLIs.push(ulLI);
                }
              }
              
      
              if (((<HTMLDivElement>child).tagName === 'DIV' || (<HTMLDivElement>child).tagName === 'SPAN') && (<HTMLDivElement>child).className) {
                if ((<HTMLDivElement>child).className.indexOf('portabled-file-name') >= 0) {
                  this.isDir = false;
                  this.name = child.textContent || (<HTMLDivElement>child).innerText;
                }
                else if ((<HTMLDivElement>child).className.indexOf('portabled-dir-name') >= 0) {
                  this.isDir = true;
                  this.name = child.textContent || (<HTMLDivElement>child).innerText;
                }
              }
      
              if ((<HTMLPreElement>child).tagName === 'PRE' && (<HTMLPreElement>child).className 
                && (<HTMLPreElement>child).className.indexOf('portabled-file-content') >= 0) {
                
                if (this._contentPRE) {
                  // double content?
                }
                else {
                  this._contentPRE = <HTMLPreElement>child;
                }
                
              }
      
            }
            
            if (this.parent) {
              this.fullPath = this.parent.fullPath + '/' + this.name;
            }
            else { 
              this.name = '';
              this.fullPath = '';
            }
            
            if (selection) {
              if (li.className.indexOf('portabled-file-selected') >= 0) {
                if (selection.selectedFile)
                  li.className = li.className.replace(/portabled\-file\-selected/g, '');
                else
                  selection.selectedFile = this.fullPath;
              }
            }
            else { 
              if (li.className.indexOf('portabled-file-selected') >= 0)
                li.className = li.className.replace(/portabled\-file\-selected/g, '');
            }
      
            if (allFiles)
              this._createChildNodesAndSort(childLIs, allFiles, selection);
      
          }
      
          read(): string {
            if (this.isDir)
              return null; // DEBUG
      
            return readNodeFileContent(this._contentPRE);
          }
      
          write(content: string) {
            if (this.isDir)
              return; // DEBUG
      
            if (!this._contentPRE) {
              this._contentPRE = document.createElement('pre');
              this._contentPRE.className = 'portabled-file-content';
              this.li.appendChild(this._contentPRE);
            }
            
            this._contentPRE.textContent = content || '';
          }
        
          readAttr(prop: string) {
            if (this.li)
              return this.li.getAttribute(getSafeAttributeName(prop));
            else
              return this._ul.getAttribute(getSafeAttributeName(prop));      
          }
        
          writeAttr(prop: string, value: string) {
            if (value === null || value === undefined) {
              if (this.li)
                this.li.removeAttribute(getSafeAttributeName(prop));
              else
                this._ul.removeAttribute(getSafeAttributeName(prop));      
            }
            else {
              if (this.li)
                this.li.setAttribute(getSafeAttributeName(prop), value);
              else
                this._ul.setAttribute(getSafeAttributeName(prop), value);
            }
          }
        
          remove(childNode: Node) {
            var nodeList = childNode.isDir ? this._subDirs : this._files;
            var index = nodeList.indexOf(childNode);
            nodeList.splice(index, 1);
            this._ul.removeChild(childNode.li);
            
            if (!this.parent || this._files.length + this._subDirs.length)
              return;
      
            this.parent.remove(this);
          }
      
          findOrCreateDir(relativePath: string): Node {
            
            var slashPos = relativePath.indexOf('/');
            var subdirName = slashPos > 0 ? relativePath.slice(0, slashPos) : relativePath;
            var restPath = slashPos > 0 ? relativePath.slice(slashPos + 1) : null;
            
            var matchIndex = this._binarySearchNode(subdirName, this._subDirs);
            var subdir: Node;
            if (matchIndex >= 0) {
              subdir = this._subDirs[matchIndex];
            }
            else {
              //return this._subDirs[matchIndex];
              var insertIndex = -matchIndex - 100;
      
              var newLI = document.createElement('li');
              newLI.className = 'portabled-dir';
              var fnameDIV = document.createElement('span');
              fnameDIV.className = 'portabled-dir-name';
              if ('textContent' in fnameDIV)
                fnameDIV.textContent = subdirName;
              else
                fnameDIV.innerText = subdirName;
              newLI.appendChild(fnameDIV);
              var ul = document.createElement('ul');
              newLI.appendChild(ul);
              subdir = new Node(this, newLI, /*allFiles*/ null, /*selection*/ null);
              
              var insertSibling =
                insertIndex < this._subDirs.length ? this._subDirs[insertIndex].li    :
                this._files.length ? this._files[0].li :
                null;
              
              this._subDirs.splice(insertIndex, 0, subdir);
              if (!this._ul) {
                this._ul = document.createElement('ul');
                this.li.appendChild(this._ul);
              }
      
              this._ul.insertBefore(subdir.li, insertSibling);
            }
            
            if (restPath)
              return subdir.findOrCreateDir(restPath);
            else
              return subdir;
          }
        
          createFile(fileName: string): Node {
            var newLI = document.createElement('li');
            newLI.className = 'portabled-file';
            var fnameDIV = document.createElement('span');
            fnameDIV.className = 'portabled-file-name';
            if ('textContent' in fnameDIV)
              fnameDIV.textContent = fileName;
            else
              fnameDIV.innerText = fileName;
              
            newLI.appendChild(fnameDIV);
            var newNode = new Node(this, newLI, /*allFiles*/ null, /*selection*/ null);
            this._insertChildNode(
              this._files,
              newNode,
                /*forceRerootingEvenIfOrdered*/ true,
                /*insertBeforeElement*/null);
            return newNode;
          }
        
          toggleCollapse() {
            if (this.li.className && this.li.className.indexOf('portabled-dir-collapsed') >= 0) {
              this.li.className = this.li.className.replace(/portabled\-dir\-collapsed/g, '');
            }
            else { 
              this.li.className = (this.li.className || '') + ' portabled-dir-collapsed';
            }
          }
        
          setSelectClass(selected: boolean) {
            if (selected) {
              this.li.className = (this.li.className || '') + ' portabled-file-selected';
            }
            else { 
              this.li.className = this.li.className ? this.li.className.replace(/portabled\-file\-selected/g, '') : null;
            }
          }
      
          private _createChildNodesAndSort(
            childLIs: HTMLLIElement[],
            allFiles: { [file: string]: Node; },
            selection: { selectedFile: string; }) {
            
            for (var i = 0; i < childLIs.length; i++) {
              var node = new Node(this, childLIs[i], allFiles, selection);
              
              if (node.isDir) {
                this._insertChildNode(
                  this._subDirs, node,
                  /*forceRerootingEvenIfOrdered*/ <any>this._files.length,
                  this._files.length ? this._files[0].li : node.li);
              }
              else {
                allFiles[node.fullPath] = node;
                this._insertChildNode(
                  this._files, node,
                  /*forceRerootingEvenIfOrdered*/ false,
                  node.li);
              }
            }
            
          }
      
          private _insertChildNode(
            nodeList: Node[],
            node: Node,
            forceRerootingEvenIfOrdered: boolean,
            insertBeforeElement: HTMLElement) {
            
            var insertIndex = this._binarySearchNode(node.name, nodeList);
            if (insertIndex >= 0)
              alert('Node should not exist: we are inserting it.');
      
            insertIndex = -insertIndex - 100;
            
            if (insertIndex >= nodeList.length) {      
              nodeList.push(node);
              if (forceRerootingEvenIfOrdered)
                this._ul.insertBefore(node.li, insertBeforeElement);
              return;
            }
      
            this._ul.insertBefore(node.li, nodeList[insertIndex].li);
            nodeList.splice(insertIndex, 0, node);
            
          }
        
          /** returns match index, or (-100 - insertionIndex) */
          private _binarySearchNode(name: string, list: Node[]): number {
            if (!list.length)
              return -100;
            
            if (name > list[list.length - 1].name)
              return -100 - list.length;
            if (name == list[list.length - 1].name)
              return list.length - 1;
            
            if (name < list[0].name)
              return -100;
            if (name === list[0].name)
              return 0;
            
            var rangeStart = 1;
            var rangeLength = list.length - 2;
            while (true) {
              if (!rangeLength)
                return -100 - rangeStart;
              
              var mid = rangeStart + (rangeLength >> 1);
              if (name === list[mid].name)
                return mid;
      
              if (name < list[mid].name) {
                rangeLength = mid - rangeStart;
              }
              else {
                rangeLength -= mid - rangeStart + 1;
                rangeStart = mid + 1;
              }
            }
          }
          
        }
      
        export function normalizePath(path: string) : string {
          
          if (!path) return '/'; // empty paths converted to root
          
          while (' \n\t\r'.indexOf(path.charAt(0))>=0) // removing leading whitespace
            path = path.slice(1);
      
          while ('\n\t\r\\'.indexOf(path.charAt(path.length - 1))>=0) // removing trailing whitespace and trailing slashes
            path = path.slice(0, path.length - 1);
      
          if (path.charAt(0) !== '/') // ensuring leading slash
            path = '/' + path;
      
          path = path.replace(/\/\/*/g, '/'); // replacing duplicate slashes with single
      
          return path;
        }
      
        export function getSafeAttributeName(caseSensitiveName: string): string {
          if (caseSensitiveName.toLowerCase() === caseSensitiveName
             && caseSensitiveName.indexOf('^')<0)
            return caseSensitiveName;
          var result: string[] = [];
          for (var i = 0; i < caseSensitiveName.length; i++) {
            var c = caseSensitiveName.charAt(i);
            if (c === '^' || c.toLowerCase() !== c)
              result.push('^');
      
            result.push(c);
          }
          return result.join('');
        }
      
      	export function readNodeFileContent(node: HTMLElement) {
          return node ? node.textContent || (node.innerText ? node.innerText.replace(/\r\n/g, '\n') : '') : '';
        }
      
      }
  • imports
    • codemirror
      • addon
        • comment
          • comment.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var noOptions = {};
              var nonWS = /[^\s\u00a0]/;
              var Pos = CodeMirror.Pos;
            
              function firstNonWS(str) {
                var found = str.search(nonWS);
                return found == -1 ? 0 : found;
              }
            
              CodeMirror.commands.toggleComment = function(cm) {
                var minLine = Infinity, ranges = cm.listSelections(), mode = null;
                for (var i = ranges.length - 1; i >= 0; i--) {
                  var from = ranges[i].from(), to = ranges[i].to();
                  if (from.line >= minLine) continue;
                  if (to.line >= minLine) to = Pos(minLine, 0);
                  minLine = from.line;
                  if (mode == null) {
                    if (cm.uncomment(from, to)) mode = "un";
                    else { cm.lineComment(from, to); mode = "line"; }
                  } else if (mode == "un") {
                    cm.uncomment(from, to);
                  } else {
                    cm.lineComment(from, to);
                  }
                }
              };
            
              CodeMirror.defineExtension("lineComment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var commentString = options.lineComment || mode.lineComment;
                if (!commentString) {
                  if (options.blockCommentStart || mode.blockCommentStart) {
                    options.fullLines = true;
                    self.blockComment(from, to, options);
                  }
                  return;
                }
                var firstLine = self.getLine(from.line);
                if (firstLine == null) return;
                var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
                var pad = options.padding == null ? " " : options.padding;
                var blankLines = options.commentBlankLines || from.line == to.line;
            
                self.operation(function() {
                  if (options.indent) {
                    var baseString = firstLine.slice(0, firstNonWS(firstLine));
                    for (var i = from.line; i < end; ++i) {
                      var line = self.getLine(i), cut = baseString.length;
                      if (!blankLines && !nonWS.test(line)) continue;
                      if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
                      self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
                    }
                  } else {
                    for (var i = from.line; i < end; ++i) {
                      if (blankLines || nonWS.test(self.getLine(i)))
                        self.replaceRange(commentString + pad, Pos(i, 0));
                    }
                  }
                });
              });
            
              CodeMirror.defineExtension("blockComment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var startString = options.blockCommentStart || mode.blockCommentStart;
                var endString = options.blockCommentEnd || mode.blockCommentEnd;
                if (!startString || !endString) {
                  if ((options.lineComment || mode.lineComment) && options.fullLines != false)
                    self.lineComment(from, to, options);
                  return;
                }
            
                var end = Math.min(to.line, self.lastLine());
                if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
            
                var pad = options.padding == null ? " " : options.padding;
                if (from.line > end) return;
            
                self.operation(function() {
                  if (options.fullLines != false) {
                    var lastLineHasText = nonWS.test(self.getLine(end));
                    self.replaceRange(pad + endString, Pos(end));
                    self.replaceRange(startString + pad, Pos(from.line, 0));
                    var lead = options.blockCommentLead || mode.blockCommentLead;
                    if (lead != null) for (var i = from.line + 1; i <= end; ++i)
                      if (i != end || lastLineHasText)
                        self.replaceRange(lead + pad, Pos(i, 0));
                  } else {
                    self.replaceRange(endString, to);
                    self.replaceRange(startString, from);
                  }
                });
              });
            
              CodeMirror.defineExtension("uncomment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
            
                // Try finding line comments
                var lineString = options.lineComment || mode.lineComment, lines = [];
                var pad = options.padding == null ? " " : options.padding, didSomething;
                lineComment: {
                  if (!lineString) break lineComment;
                  for (var i = start; i <= end; ++i) {
                    var line = self.getLine(i);
                    var found = line.indexOf(lineString);
                    if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
                    if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment;
                    if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
                    lines.push(line);
                  }
                  self.operation(function() {
                    for (var i = start; i <= end; ++i) {
                      var line = lines[i - start];
                      var pos = line.indexOf(lineString), endPos = pos + lineString.length;
                      if (pos < 0) continue;
                      if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
                      didSomething = true;
                      self.replaceRange("", Pos(i, pos), Pos(i, endPos));
                    }
                  });
                  if (didSomething) return true;
                }
            
                // Try block comments
                var startString = options.blockCommentStart || mode.blockCommentStart;
                var endString = options.blockCommentEnd || mode.blockCommentEnd;
                if (!startString || !endString) return false;
                var lead = options.blockCommentLead || mode.blockCommentLead;
                var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end);
                var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString);
                if (close == -1 && start != end) {
                  endLine = self.getLine(--end);
                  close = endLine.lastIndexOf(endString);
                }
                if (open == -1 || close == -1 ||
                    !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
                    !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
                  return false;
            
                // Avoid killing block comments completely outside the selection.
                // Positions of the last startString before the start of the selection, and the first endString after it.
                var lastStart = startLine.lastIndexOf(startString, from.ch);
                var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
                if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
                // Positions of the first endString after the end of the selection, and the last startString before it.
                firstEnd = endLine.indexOf(endString, to.ch);
                var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
                lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
                if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
            
                self.operation(function() {
                  self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
                                    Pos(end, close + endString.length));
                  var openEnd = open + startString.length;
                  if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
                  self.replaceRange("", Pos(start, open), Pos(start, openEnd));
                  if (lead) for (var i = start + 1; i <= end; ++i) {
                    var line = self.getLine(i), found = line.indexOf(lead);
                    if (found == -1 || nonWS.test(line.slice(0, found))) continue;
                    var foundEnd = found + lead.length;
                    if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
                    self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
                  }
                });
                return true;
              });
            });
            
          • continuecomment.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var modes = ["clike", "css", "javascript"];
            
              for (var i = 0; i < modes.length; ++i)
                CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
            
              function continueComment(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), mode, inserts = [];
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].head, token = cm.getTokenAt(pos);
                  if (token.type != "comment") return CodeMirror.Pass;
                  var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;
                  if (!mode) mode = modeHere;
                  else if (mode != modeHere) return CodeMirror.Pass;
            
                  var insert = null;
                  if (mode.blockCommentStart && mode.blockCommentContinue) {
                    var end = token.string.indexOf(mode.blockCommentEnd);
                    var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
                    if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {
                      // Comment ended, don't continue it
                    } else if (token.string.indexOf(mode.blockCommentStart) == 0) {
                      insert = full.slice(0, token.start);
                      if (!/^\s*$/.test(insert)) {
                        insert = "";
                        for (var j = 0; j < token.start; ++j) insert += " ";
                      }
                    } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
                               found + mode.blockCommentContinue.length > token.start &&
                               /^\s*$/.test(full.slice(0, found))) {
                      insert = full.slice(0, found);
                    }
                    if (insert != null) insert += mode.blockCommentContinue;
                  }
                  if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
                    var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
                    if (found > -1) {
                      insert = line.slice(0, found);
                      if (/\S/.test(insert)) insert = null;
                      else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
                    }
                  }
                  if (insert == null) return CodeMirror.Pass;
                  inserts[i] = "\n" + insert;
                }
            
                cm.operation(function() {
                  for (var i = ranges.length - 1; i >= 0; i--)
                    cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
                });
              }
            
              function continueLineCommentEnabled(cm) {
                var opt = cm.getOption("continueComments");
                if (opt && typeof opt == "object")
                  return opt.continueLineComment !== false;
                return true;
              }
            
              CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
                if (prev && prev != CodeMirror.Init)
                  cm.removeKeyMap("continueComment");
                if (val) {
                  var key = "Enter";
                  if (typeof val == "string")
                    key = val;
                  else if (typeof val == "object" && val.key)
                    key = val.key;
                  var map = {name: "continueComment"};
                  map[key] = continueComment;
                  cm.addKeyMap(map);
                }
              });
            });
            
        • dialog
          • dialog.css
            .CodeMirror-dialog {
              position: absolute;
              left: 0; right: 0;
              background: white;
              z-index: 15;
              padding: .1em .8em;
              overflow: hidden;
              color: #333;
            }
            
            .CodeMirror-dialog-top {
              border-bottom: 1px solid #eee;
              top: 0;
            }
            
            .CodeMirror-dialog-bottom {
              border-top: 1px solid #eee;
              bottom: 0;
            }
            
            .CodeMirror-dialog input {
              border: none;
              outline: none;
              background: transparent;
              width: 20em;
              color: inherit;
              font-family: monospace;
            }
            
            .CodeMirror-dialog button {
              font-size: 70%;
            }
            
          • dialog.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Open simple dialogs on top of an editor. Relies on dialog.css.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              function dialogDiv(cm, template, bottom) {
                var wrap = cm.getWrapperElement();
                var dialog;
                dialog = wrap.appendChild(document.createElement("div"));
                if (bottom)
                  dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
                else
                  dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
            
                if (typeof template == "string") {
                  dialog.innerHTML = template;
                } else { // Assuming it's a detached DOM element.
                  dialog.appendChild(template);
                }
                return dialog;
              }
            
              function closeNotification(cm, newVal) {
                if (cm.state.currentNotificationClose)
                  cm.state.currentNotificationClose();
                cm.state.currentNotificationClose = newVal;
              }
            
              CodeMirror.defineExtension("openDialog", function(template, callback, options) {
                if (!options) options = {};
            
                closeNotification(this, null);
            
                var dialog = dialogDiv(this, template, options.bottom);
                var closed = false, me = this;
                function close(newVal) {
                  if (typeof newVal == 'string') {
                    inp.value = newVal;
                  } else {
                    if (closed) return;
                    closed = true;
                    dialog.parentNode.removeChild(dialog);
                    me.focus();
            
                    if (options.onClose) options.onClose(dialog);
                  }
                }
            
                var inp = dialog.getElementsByTagName("input")[0], button;
                if (inp) {
                  if (options.value) {
                    inp.value = options.value;
                    inp.select();
                  }
            
                  if (options.onInput)
                    CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
                  if (options.onKeyUp)
                    CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
            
                  CodeMirror.on(inp, "keydown", function(e) {
                    if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
                    if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
                      inp.blur();
                      CodeMirror.e_stop(e);
                      close();
                    }
                    if (e.keyCode == 13) callback(inp.value, e);
                  });
            
                  if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
            
                  inp.focus();
                } else if (button = dialog.getElementsByTagName("button")[0]) {
                  CodeMirror.on(button, "click", function() {
                    close();
                    me.focus();
                  });
            
                  if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
            
                  button.focus();
                }
                return close;
              });
            
              CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
                closeNotification(this, null);
                var dialog = dialogDiv(this, template, options && options.bottom);
                var buttons = dialog.getElementsByTagName("button");
                var closed = false, me = this, blurring = 1;
                function close() {
                  if (closed) return;
                  closed = true;
                  dialog.parentNode.removeChild(dialog);
                  me.focus();
                }
                buttons[0].focus();
                for (var i = 0; i < buttons.length; ++i) {
                  var b = buttons[i];
                  (function(callback) {
                    CodeMirror.on(b, "click", function(e) {
                      CodeMirror.e_preventDefault(e);
                      close();
                      if (callback) callback(me);
                    });
                  })(callbacks[i]);
                  CodeMirror.on(b, "blur", function() {
                    --blurring;
                    setTimeout(function() { if (blurring <= 0) close(); }, 200);
                  });
                  CodeMirror.on(b, "focus", function() { ++blurring; });
                }
              });
            
              /*
               * openNotification
               * Opens a notification, that can be closed with an optional timer
               * (default 5000ms timer) and always closes on click.
               *
               * If a notification is opened while another is opened, it will close the
               * currently opened one and open the new one immediately.
               */
              CodeMirror.defineExtension("openNotification", function(template, options) {
                closeNotification(this, close);
                var dialog = dialogDiv(this, template, options && options.bottom);
                var closed = false, doneTimer;
                var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
            
                function close() {
                  if (closed) return;
                  closed = true;
                  clearTimeout(doneTimer);
                  dialog.parentNode.removeChild(dialog);
                }
            
                CodeMirror.on(dialog, 'click', function(e) {
                  CodeMirror.e_preventDefault(e);
                  close();
                });
            
                if (duration)
                  doneTimer = setTimeout(close, duration);
            
                return close;
              });
            });
            
        • display
          • fullscreen.css
            .CodeMirror-fullscreen {
              position: fixed;
              top: 0; left: 0; right: 0; bottom: 0;
              height: auto;
              z-index: 9;
            }
            
          • fullscreen.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
                if (old == CodeMirror.Init) old = false;
                if (!old == !val) return;
                if (val) setFullscreen(cm);
                else setNormal(cm);
              });
            
              function setFullscreen(cm) {
                var wrap = cm.getWrapperElement();
                cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
                                              width: wrap.style.width, height: wrap.style.height};
                wrap.style.width = "";
                wrap.style.height = "auto";
                wrap.className += " CodeMirror-fullscreen";
                document.documentElement.style.overflow = "hidden";
                cm.refresh();
              }
            
              function setNormal(cm) {
                var wrap = cm.getWrapperElement();
                wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
                document.documentElement.style.overflow = "";
                var info = cm.state.fullScreenRestore;
                wrap.style.width = info.width; wrap.style.height = info.height;
                window.scrollTo(info.scrollLeft, info.scrollTop);
                cm.refresh();
              }
            });
            
          • panel.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineExtension("addPanel", function(node, options) {
                if (!this.state.panels) initPanels(this);
            
                var info = this.state.panels;
                if (options && options.position == "bottom")
                  info.wrapper.appendChild(node);
                else
                  info.wrapper.insertBefore(node, info.wrapper.firstChild);
                var height = (options && options.height) || node.offsetHeight;
                this._setSize(null, info.heightLeft -= height);
                info.panels++;
                return new Panel(this, node, options, height);
              });
            
              function Panel(cm, node, options, height) {
                this.cm = cm;
                this.node = node;
                this.options = options;
                this.height = height;
                this.cleared = false;
              }
            
              Panel.prototype.clear = function() {
                if (this.cleared) return;
                this.cleared = true;
                var info = this.cm.state.panels;
                this.cm._setSize(null, info.heightLeft += this.height);
                info.wrapper.removeChild(this.node);
                if (--info.panels == 0) removePanels(this.cm);
              };
            
              Panel.prototype.changed = function(height) {
                var newHeight = height == null ? this.node.offsetHeight : height;
                var info = this.cm.state.panels;
                this.cm._setSize(null, info.height += (newHeight - this.height));
                this.height = newHeight;
              };
            
              function initPanels(cm) {
                var wrap = cm.getWrapperElement();
                var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
                var height = parseInt(style.height);
                var info = cm.state.panels = {
                  setHeight: wrap.style.height,
                  heightLeft: height,
                  panels: 0,
                  wrapper: document.createElement("div")
                };
                wrap.parentNode.insertBefore(info.wrapper, wrap);
                var hasFocus = cm.hasFocus();
                info.wrapper.appendChild(wrap);
                if (hasFocus) cm.focus();
            
                cm._setSize = cm.setSize;
                if (height != null) cm.setSize = function(width, newHeight) {
                  if (newHeight == null) return this._setSize(width, newHeight);
                  info.setHeight = newHeight;
                  if (typeof newHeight != "number") {
                    var px = /^(\d+\.?\d*)px$/.exec(newHeight);
                    if (px) {
                      newHeight = Number(px[1]);
                    } else {
                      info.wrapper.style.height = newHeight;
                      newHeight = info.wrapper.offsetHeight;
                      info.wrapper.style.height = "";
                    }
                  }
                  cm._setSize(width, info.heightLeft += (newHeight - height));
                  height = newHeight;
                };
              }
            
              function removePanels(cm) {
                var info = cm.state.panels;
                cm.state.panels = null;
            
                var wrap = cm.getWrapperElement();
                info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
                wrap.style.height = info.setHeight;
                cm.setSize = cm._setSize;
                cm.setSize();
              }
            });
            
          • placeholder.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.on("blur", onBlur);
                  cm.on("change", onChange);
                  onChange(cm);
                } else if (!val && prev) {
                  cm.off("blur", onBlur);
                  cm.off("change", onChange);
                  clearPlaceholder(cm);
                  var wrapper = cm.getWrapperElement();
                  wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
                }
            
                if (val && !cm.hasFocus()) onBlur(cm);
              });
            
              function clearPlaceholder(cm) {
                if (cm.state.placeholder) {
                  cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
                  cm.state.placeholder = null;
                }
              }
              function setPlaceholder(cm) {
                clearPlaceholder(cm);
                var elt = cm.state.placeholder = document.createElement("pre");
                elt.style.cssText = "height: 0; overflow: visible";
                elt.className = "CodeMirror-placeholder";
                elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
                cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
              }
            
              function onBlur(cm) {
                if (isEmpty(cm)) setPlaceholder(cm);
              }
              function onChange(cm) {
                var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
                wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
            
                if (empty) setPlaceholder(cm);
                else clearPlaceholder(cm);
              }
            
              function isEmpty(cm) {
                return (cm.lineCount() === 1) && (cm.getLine(0) === "");
              }
            });
            
          • rulers.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("rulers", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  clearRulers(cm);
                  cm.off("refresh", refreshRulers);
                }
                if (val && val.length) {
                  setRulers(cm);
                  cm.on("refresh", refreshRulers);
                }
              });
            
              function clearRulers(cm) {
                for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) {
                  var node = cm.display.lineSpace.childNodes[i];
                  if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className))
                    node.parentNode.removeChild(node);
                }
              }
            
              function setRulers(cm) {
                var val = cm.getOption("rulers");
                var cw = cm.defaultCharWidth();
                var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
                var minH = cm.display.scroller.offsetHeight + 30;
                for (var i = 0; i < val.length; i++) {
                  var elt = document.createElement("div");
                  elt.className = "CodeMirror-ruler";
                  var col, cls = null, conf = val[i];
                  if (typeof conf == "number") {
                    col = conf;
                  } else {
                    col = conf.column;
                    if (conf.className) elt.className += " " + conf.className;
                    if (conf.color) elt.style.borderColor = conf.color;
                    if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
                    if (conf.width) elt.style.borderLeftWidth = conf.width;
                    cls = val[i].className;
                  }
                  elt.style.left = (left + col * cw) + "px";
                  elt.style.top = "-50px";
                  elt.style.bottom = "-20px";
                  elt.style.minHeight = minH + "px";
                  cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);
                }
              }
            
              function refreshRulers(cm) {
                clearRulers(cm);
                setRulers(cm);
              }
            });
            
        • edit
          • closebrackets.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var DEFAULT_BRACKETS = "()[]{}''\"\"";
              var DEFAULT_TRIPLES = "'\"";
              var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
              var SPACE_CHAR_REGEX = /\s/;
            
              var Pos = CodeMirror.Pos;
            
              CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
                if (old != CodeMirror.Init && old)
                  cm.removeKeyMap("autoCloseBrackets");
                if (!val) return;
                var pairs = DEFAULT_BRACKETS, triples = DEFAULT_TRIPLES, explode = DEFAULT_EXPLODE_ON_ENTER;
                if (typeof val == "string") pairs = val;
                else if (typeof val == "object") {
                  if (val.pairs != null) pairs = val.pairs;
                  if (val.triples != null) triples = val.triples;
                  if (val.explode != null) explode = val.explode;
                }
                var map = buildKeymap(pairs, triples);
                if (explode) map.Enter = buildExplodeHandler(explode);
                cm.addKeyMap(map);
              });
            
              function charsAround(cm, pos) {
                var str = cm.getRange(Pos(pos.line, pos.ch - 1),
                                      Pos(pos.line, pos.ch + 1));
                return str.length == 2 ? str : null;
              }
            
              // Project the token type that will exists after the given char is
              // typed, and use it to determine whether it would cause the start
              // of a string token.
              function enteringString(cm, pos, ch) {
                var line = cm.getLine(pos.line);
                var token = cm.getTokenAt(pos);
                if (/\bstring2?\b/.test(token.type)) return false;
                var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
                stream.pos = stream.start = token.start;
                for (;;) {
                  var type1 = cm.getMode().token(stream, token.state);
                  if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
                  stream.start = stream.pos;
                }
              }
            
              function buildKeymap(pairs, triples) {
                var map = {
                  name : "autoCloseBrackets",
                  Backspace: function(cm) {
                    if (cm.getOption("disableInput")) return CodeMirror.Pass;
                    var ranges = cm.listSelections();
                    for (var i = 0; i < ranges.length; i++) {
                      if (!ranges[i].empty()) return CodeMirror.Pass;
                      var around = charsAround(cm, ranges[i].head);
                      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
                    }
                    for (var i = ranges.length - 1; i >= 0; i--) {
                      var cur = ranges[i].head;
                      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
                    }
                  }
                };
                var closingBrackets = "";
                for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
                  closingBrackets += right;
                  map["'" + left + "'"] = function(cm) {
                    if (cm.getOption("disableInput")) return CodeMirror.Pass;
                    var ranges = cm.listSelections(), type, next;
                    for (var i = 0; i < ranges.length; i++) {
                      var range = ranges[i], cur = range.head, curType;
                      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
                      if (!range.empty()) {
                        curType = "surround";
                      } else if (left == right && next == right) {
                        if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
                          curType = "skipThree";
                        else
                          curType = "skip";
                      } else if (left == right && cur.ch > 1 && triples.indexOf(left) >= 0 &&
                                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
                                 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) {
                        curType = "addFour";
                      } else if (left == '"' || left == "'") {
                        if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both";
                        else return CodeMirror.Pass;
                      } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) {
                        curType = "both";
                      } else {
                        return CodeMirror.Pass;
                      }
                      if (!type) type = curType;
                      else if (type != curType) return CodeMirror.Pass;
                    }
            
                    cm.operation(function() {
                      if (type == "skip") {
                        cm.execCommand("goCharRight");
                      } else if (type == "skipThree") {
                        for (var i = 0; i < 3; i++)
                          cm.execCommand("goCharRight");
                      } else if (type == "surround") {
                        var sels = cm.getSelections();
                        for (var i = 0; i < sels.length; i++)
                          sels[i] = left + sels[i] + right;
                        cm.replaceSelections(sels, "around");
                      } else if (type == "both") {
                        cm.replaceSelection(left + right, null);
                        cm.execCommand("goCharLeft");
                      } else if (type == "addFour") {
                        cm.replaceSelection(left + left + left + left, "before");
                        cm.execCommand("goCharRight");
                      }
                    });
                  };
                  if (left != right) map["'" + right + "'"] = function(cm) {
                    var ranges = cm.listSelections();
                    for (var i = 0; i < ranges.length; i++) {
                      var range = ranges[i];
                      if (!range.empty() ||
                          cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
                        return CodeMirror.Pass;
                    }
                    cm.execCommand("goCharRight");
                  };
                })(pairs.charAt(i), pairs.charAt(i + 1));
                return map;
              }
            
              function buildExplodeHandler(pairs) {
                return function(cm) {
                  if (cm.getOption("disableInput")) return CodeMirror.Pass;
                  var ranges = cm.listSelections();
                  for (var i = 0; i < ranges.length; i++) {
                    if (!ranges[i].empty()) return CodeMirror.Pass;
                    var around = charsAround(cm, ranges[i].head);
                    if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
                  }
                  cm.operation(function() {
                    cm.replaceSelection("\n\n", null);
                    cm.execCommand("goCharLeft");
                    ranges = cm.listSelections();
                    for (var i = 0; i < ranges.length; i++) {
                      var line = ranges[i].head.line;
                      cm.indentLine(line, null, true);
                      cm.indentLine(line + 1, null, true);
                    }
                  });
                };
              }
            });
            
          • closetag.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Tag-closer extension for CodeMirror.
             *
             * This extension adds an "autoCloseTags" option that can be set to
             * either true to get the default behavior, or an object to further
             * configure its behavior.
             *
             * These are supported options:
             *
             * `whenClosing` (default true)
             *   Whether to autoclose when the '/' of a closing tag is typed.
             * `whenOpening` (default true)
             *   Whether to autoclose the tag when the final '>' of an opening
             *   tag is typed.
             * `dontCloseTags` (default is empty tags for HTML, none for XML)
             *   An array of tag names that should not be autoclosed.
             * `indentTags` (default is block tags for HTML, none for XML)
             *   An array of tag names that should, when opened, cause a
             *   blank line to be added inside the tag, and the blank line and
             *   closing line to be indented.
             *
             * See demos/closetag.html for a usage example.
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../fold/xml-fold"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
                if (old != CodeMirror.Init && old)
                  cm.removeKeyMap("autoCloseTags");
                if (!val) return;
                var map = {name: "autoCloseTags"};
                if (typeof val != "object" || val.whenClosing)
                  map["'/'"] = function(cm) { return autoCloseSlash(cm); };
                if (typeof val != "object" || val.whenOpening)
                  map["'>'"] = function(cm) { return autoCloseGT(cm); };
                cm.addKeyMap(map);
              });
            
              var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
                                   "source", "track", "wbr"];
              var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
                                "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
            
              function autoCloseGT(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), replacements = [];
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var pos = ranges[i].head, tok = cm.getTokenAt(pos);
                  var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
                  if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
            
                  var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
                  var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
                  var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
            
                  var tagName = state.tagName;
                  if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
                  var lowerTagName = tagName.toLowerCase();
                  // Don't process the '>' at the end of an end-tag or self-closing tag
                  if (!tagName ||
                      tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
                      tok.type == "tag" && state.type == "closeTag" ||
                      tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
                      dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
                      closingTagExists(cm, tagName, pos, state, true))
                    return CodeMirror.Pass;
            
                  var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
                  replacements[i] = {indent: indent,
                                     text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
                                     newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
                }
            
                for (var i = ranges.length - 1; i >= 0; i--) {
                  var info = replacements[i];
                  cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
                  var sel = cm.listSelections().slice(0);
                  sel[i] = {head: info.newPos, anchor: info.newPos};
                  cm.setSelections(sel);
                  if (info.indent) {
                    cm.indentLine(info.newPos.line, null, true);
                    cm.indentLine(info.newPos.line + 1, null, true);
                  }
                }
              }
            
              function autoCloseCurrent(cm, typingSlash) {
                var ranges = cm.listSelections(), replacements = [];
                var head = typingSlash ? "/" : "</";
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var pos = ranges[i].head, tok = cm.getTokenAt(pos);
                  var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
                  if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
                                      tok.start != pos.ch - 1))
                    return CodeMirror.Pass;
                  // Kludge to get around the fact that we are not in XML mode
                  // when completing in JS/CSS snippet in htmlmixed mode. Does not
                  // work for other XML embedded languages (there is no general
                  // way to go from a mixed mode to its current XML state).
                  if (inner.mode.name != "xml") {
                    if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
                      replacements[i] = head + "script>";
                    else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
                      replacements[i] = head + "style>";
                    else
                      return CodeMirror.Pass;
                  } else {
                    if (!state.context || !state.context.tagName ||
                        closingTagExists(cm, state.context.tagName, pos, state))
                      return CodeMirror.Pass;
                    replacements[i] = head + state.context.tagName + ">";
                  }
                }
                cm.replaceSelections(replacements);
                ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++)
                  if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
                    cm.indentLine(ranges[i].head.line);
              }
            
              function autoCloseSlash(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                return autoCloseCurrent(cm, true);
              }
            
              CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
            
              function indexOf(collection, elt) {
                if (collection.indexOf) return collection.indexOf(elt);
                for (var i = 0, e = collection.length; i < e; ++i)
                  if (collection[i] == elt) return i;
                return -1;
              }
            
              // If xml-fold is loaded, we use its functionality to try and verify
              // whether a given tag is actually unclosed.
              function closingTagExists(cm, tagName, pos, state, newTag) {
                if (!CodeMirror.scanForClosingTag) return false;
                var end = Math.min(cm.lastLine() + 1, pos.line + 500);
                var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
                if (!nextClose || nextClose.tag != tagName) return false;
                var cx = state.context;
                // If the immediate wrapping context contains onCx instances of
                // the same tag, a closing tag only exists if there are at least
                // that many closing tags of that type following.
                for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
                pos = nextClose.to;
                for (var i = 1; i < onCx; i++) {
                  var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
                  if (!next || next.tag != tagName) return false;
                  pos = next.to;
                }
                return true;
              }
            });
            
          • continuelist.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
                  emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
                  unorderedListRE = /[*+-]\s/;
            
              CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), replacements = [];
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].head, match;
                  var eolState = cm.getStateAfter(pos.line);
                  var inList = eolState.list !== false;
                  var inQuote = eolState.quote !== false;
            
                  if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {
                    cm.execCommand("newlineAndIndent");
                    return;
                  }
                  if (cm.getLine(pos.line).match(emptyListRE)) {
                    cm.replaceRange("", {
                      line: pos.line, ch: 0
                    }, {
                      line: pos.line, ch: pos.ch + 1
                    });
                    replacements[i] = "\n";
            
                  } else {
                    var indent = match[1], after = match[4];
                    var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
                      ? match[2]
                      : (parseInt(match[3], 10) + 1) + ".";
            
                    replacements[i] = "\n" + indent + bullet + after;
                  }
                }
            
                cm.replaceSelections(replacements);
              };
            });
            
          • matchbrackets.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
                (document.documentMode == null || document.documentMode < 8);
            
              var Pos = CodeMirror.Pos;
            
              var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
            
              function findMatchingBracket(cm, where, strict, config) {
                var line = cm.getLineHandle(where.line), pos = where.ch - 1;
                var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
                if (!match) return null;
                var dir = match.charAt(1) == ">" ? 1 : -1;
                if (strict && (dir > 0) != (pos == where.ch)) return null;
                var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
            
                var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
                if (found == null) return null;
                return {from: Pos(where.line, pos), to: found && found.pos,
                        match: found && found.ch == match.charAt(0), forward: dir > 0};
              }
            
              // bracketRegex is used to specify which type of bracket to scan
              // should be a regexp, e.g. /[[\]]/
              //
              // Note: If "where" is on an open bracket, then this bracket is ignored.
              //
              // Returns false when no bracket was found, null when it reached
              // maxScanLines and gave up
              function scanForBracket(cm, where, dir, style, config) {
                var maxScanLen = (config && config.maxScanLineLength) || 10000;
                var maxScanLines = (config && config.maxScanLines) || 1000;
            
                var stack = [];
                var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
                var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
                                      : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
                for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
                  var line = cm.getLine(lineNo);
                  if (!line) continue;
                  var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
                  if (line.length > maxScanLen) continue;
                  if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
                  for (; pos != end; pos += dir) {
                    var ch = line.charAt(pos);
                    if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
                      var match = matching[ch];
                      if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
                      else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
                      else stack.pop();
                    }
                  }
                }
                return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
              }
            
              function matchBrackets(cm, autoclear, config) {
                // Disable brace matching in long lines, since it'll cause hugely slow updates
                var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
                var marks = [], ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
                  if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
                    var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
                    marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
                    if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
                      marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
                  }
                }
            
                if (marks.length) {
                  // Kludge to work around the IE bug from issue #1193, where text
                  // input stops going to the textare whever this fires.
                  if (ie_lt8 && cm.state.focused) cm.focus();
            
                  var clear = function() {
                    cm.operation(function() {
                      for (var i = 0; i < marks.length; i++) marks[i].clear();
                    });
                  };
                  if (autoclear) setTimeout(clear, 800);
                  else return clear;
                }
              }
            
              var currentlyHighlighted = null;
              function doMatchBrackets(cm) {
                cm.operation(function() {
                  if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
                  currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
                });
              }
            
              CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init)
                  cm.off("cursorActivity", doMatchBrackets);
                if (val) {
                  cm.state.matchBrackets = typeof val == "object" ? val : {};
                  cm.on("cursorActivity", doMatchBrackets);
                }
              });
            
              CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
              CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
                return findMatchingBracket(this, pos, strict, config);
              });
              CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
                return scanForBracket(this, pos, dir, style, config);
              });
            });
            
          • matchtags.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../fold/xml-fold"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.off("cursorActivity", doMatchTags);
                  cm.off("viewportChange", maybeUpdateMatch);
                  clear(cm);
                }
                if (val) {
                  cm.state.matchBothTags = typeof val == "object" && val.bothTags;
                  cm.on("cursorActivity", doMatchTags);
                  cm.on("viewportChange", maybeUpdateMatch);
                  doMatchTags(cm);
                }
              });
            
              function clear(cm) {
                if (cm.state.tagHit) cm.state.tagHit.clear();
                if (cm.state.tagOther) cm.state.tagOther.clear();
                cm.state.tagHit = cm.state.tagOther = null;
              }
            
              function doMatchTags(cm) {
                cm.state.failedTagMatch = false;
                cm.operation(function() {
                  clear(cm);
                  if (cm.somethingSelected()) return;
                  var cur = cm.getCursor(), range = cm.getViewport();
                  range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
                  var match = CodeMirror.findMatchingTag(cm, cur, range);
                  if (!match) return;
                  if (cm.state.matchBothTags) {
                    var hit = match.at == "open" ? match.open : match.close;
                    if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
                  }
                  var other = match.at == "close" ? match.open : match.close;
                  if (other)
                    cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
                  else
                    cm.state.failedTagMatch = true;
                });
              }
            
              function maybeUpdateMatch(cm) {
                if (cm.state.failedTagMatch) doMatchTags(cm);
              }
            
              CodeMirror.commands.toMatchingTag = function(cm) {
                var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
                if (found) {
                  var other = found.at == "close" ? found.open : found.close;
                  if (other) cm.extendSelection(other.to, other.from);
                }
              };
            });
            
          • trailingspace.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {
                if (prev == CodeMirror.Init) prev = false;
                if (prev && !val)
                  cm.removeOverlay("trailingspace");
                else if (!prev && val)
                  cm.addOverlay({
                    token: function(stream) {
                      for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {}
                      if (i > stream.pos) { stream.pos = i; return null; }
                      stream.pos = l;
                      return "trailingspace";
                    },
                    name: "trailingspace"
                  });
              });
            });
            
        • fold
          • brace-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "brace", function(cm, start) {
              var line = start.line, lineText = cm.getLine(line);
              var startCh, tokenType;
            
              function findOpening(openCh) {
                for (var at = start.ch, pass = 0;;) {
                  var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
                  if (found == -1) {
                    if (pass == 1) break;
                    pass = 1;
                    at = lineText.length;
                    continue;
                  }
                  if (pass == 1 && found < start.ch) break;
                  tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
                  if (!/^(comment|string)/.test(tokenType)) return found + 1;
                  at = found - 1;
                }
              }
            
              var startToken = "{", endToken = "}", startCh = findOpening("{");
              if (startCh == null) {
                startToken = "[", endToken = "]";
                startCh = findOpening("[");
              }
            
              if (startCh == null) return;
              var count = 1, lastLine = cm.lastLine(), end, endCh;
              outer: for (var i = line; i <= lastLine; ++i) {
                var text = cm.getLine(i), pos = i == line ? startCh : 0;
                for (;;) {
                  var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
                  if (nextOpen < 0) nextOpen = text.length;
                  if (nextClose < 0) nextClose = text.length;
                  pos = Math.min(nextOpen, nextClose);
                  if (pos == text.length) break;
                  if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
                    if (pos == nextOpen) ++count;
                    else if (!--count) { end = i; endCh = pos; break outer; }
                  }
                  ++pos;
                }
              }
              if (end == null || line == end && endCh == startCh) return;
              return {from: CodeMirror.Pos(line, startCh),
                      to: CodeMirror.Pos(end, endCh)};
            });
            
            CodeMirror.registerHelper("fold", "import", function(cm, start) {
              function hasImport(line) {
                if (line < cm.firstLine() || line > cm.lastLine()) return null;
                var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
                if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
                if (start.type != "keyword" || start.string != "import") return null;
                // Now find closing semicolon, return its position
                for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {
                  var text = cm.getLine(i), semi = text.indexOf(";");
                  if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)};
                }
              }
            
              var start = start.line, has = hasImport(start), prev;
              if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1))
                return null;
              for (var end = has.end;;) {
                var next = hasImport(end.line + 1);
                if (next == null) break;
                end = next.end;
              }
              return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
            });
            
            CodeMirror.registerHelper("fold", "include", function(cm, start) {
              function hasInclude(line) {
                if (line < cm.firstLine() || line > cm.lastLine()) return null;
                var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
                if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
                if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
              }
            
              var start = start.line, has = hasInclude(start);
              if (has == null || hasInclude(start - 1) != null) return null;
              for (var end = start;;) {
                var next = hasInclude(end + 1);
                if (next == null) break;
                ++end;
              }
              return {from: CodeMirror.Pos(start, has + 1),
                      to: cm.clipPos(CodeMirror.Pos(end))};
            });
            
            });
            
          • comment-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
              return mode.blockCommentStart && mode.blockCommentEnd;
            }, function(cm, start) {
              var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
              if (!startToken || !endToken) return;
              var line = start.line, lineText = cm.getLine(line);
            
              var startCh;
              for (var at = start.ch, pass = 0;;) {
                var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
                if (found == -1) {
                  if (pass == 1) return;
                  pass = 1;
                  at = lineText.length;
                  continue;
                }
                if (pass == 1 && found < start.ch) return;
                if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) {
                  startCh = found + startToken.length;
                  break;
                }
                at = found - 1;
              }
            
              var depth = 1, lastLine = cm.lastLine(), end, endCh;
              outer: for (var i = line; i <= lastLine; ++i) {
                var text = cm.getLine(i), pos = i == line ? startCh : 0;
                for (;;) {
                  var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
                  if (nextOpen < 0) nextOpen = text.length;
                  if (nextClose < 0) nextClose = text.length;
                  pos = Math.min(nextOpen, nextClose);
                  if (pos == text.length) break;
                  if (pos == nextOpen) ++depth;
                  else if (!--depth) { end = i; endCh = pos; break outer; }
                  ++pos;
                }
              }
              if (end == null || line == end && endCh == startCh) return;
              return {from: CodeMirror.Pos(line, startCh),
                      to: CodeMirror.Pos(end, endCh)};
            });
            
            });
            
          • foldcode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function doFold(cm, pos, options, force) {
                if (options && options.call) {
                  var finder = options;
                  options = null;
                } else {
                  var finder = getOption(cm, options, "rangeFinder");
                }
                if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
                var minSize = getOption(cm, options, "minFoldSize");
            
                function getRange(allowFolded) {
                  var range = finder(cm, pos);
                  if (!range || range.to.line - range.from.line < minSize) return null;
                  var marks = cm.findMarksAt(range.from);
                  for (var i = 0; i < marks.length; ++i) {
                    if (marks[i].__isFold && force !== "fold") {
                      if (!allowFolded) return null;
                      range.cleared = true;
                      marks[i].clear();
                    }
                  }
                  return range;
                }
            
                var range = getRange(true);
                if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
                  pos = CodeMirror.Pos(pos.line - 1, 0);
                  range = getRange(false);
                }
                if (!range || range.cleared || force === "unfold") return;
            
                var myWidget = makeWidget(cm, options);
                CodeMirror.on(myWidget, "mousedown", function(e) {
                  myRange.clear();
                  CodeMirror.e_preventDefault(e);
                });
                var myRange = cm.markText(range.from, range.to, {
                  replacedWith: myWidget,
                  clearOnEnter: true,
                  __isFold: true
                });
                myRange.on("clear", function(from, to) {
                  CodeMirror.signal(cm, "unfold", cm, from, to);
                });
                CodeMirror.signal(cm, "fold", cm, range.from, range.to);
              }
            
              function makeWidget(cm, options) {
                var widget = getOption(cm, options, "widget");
                if (typeof widget == "string") {
                  var text = document.createTextNode(widget);
                  widget = document.createElement("span");
                  widget.appendChild(text);
                  widget.className = "CodeMirror-foldmarker";
                }
                return widget;
              }
            
              // Clumsy backwards-compatible interface
              CodeMirror.newFoldFunction = function(rangeFinder, widget) {
                return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
              };
            
              // New-style interface
              CodeMirror.defineExtension("foldCode", function(pos, options, force) {
                doFold(this, pos, options, force);
              });
            
              CodeMirror.defineExtension("isFolded", function(pos) {
                var marks = this.findMarksAt(pos);
                for (var i = 0; i < marks.length; ++i)
                  if (marks[i].__isFold) return true;
              });
            
              CodeMirror.commands.toggleFold = function(cm) {
                cm.foldCode(cm.getCursor());
              };
              CodeMirror.commands.fold = function(cm) {
                cm.foldCode(cm.getCursor(), null, "fold");
              };
              CodeMirror.commands.unfold = function(cm) {
                cm.foldCode(cm.getCursor(), null, "unfold");
              };
              CodeMirror.commands.foldAll = function(cm) {
                cm.operation(function() {
                  for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
                    cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
                });
              };
              CodeMirror.commands.unfoldAll = function(cm) {
                cm.operation(function() {
                  for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
                    cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
                });
              };
            
              CodeMirror.registerHelper("fold", "combine", function() {
                var funcs = Array.prototype.slice.call(arguments, 0);
                return function(cm, start) {
                  for (var i = 0; i < funcs.length; ++i) {
                    var found = funcs[i](cm, start);
                    if (found) return found;
                  }
                };
              });
            
              CodeMirror.registerHelper("fold", "auto", function(cm, start) {
                var helpers = cm.getHelpers(start, "fold");
                for (var i = 0; i < helpers.length; i++) {
                  var cur = helpers[i](cm, start);
                  if (cur) return cur;
                }
              });
            
              var defaultOptions = {
                rangeFinder: CodeMirror.fold.auto,
                widget: "\u2194",
                minFoldSize: 0,
                scanUp: false
              };
            
              CodeMirror.defineOption("foldOptions", null);
            
              function getOption(cm, options, name) {
                if (options && options[name] !== undefined)
                  return options[name];
                var editorOptions = cm.options.foldOptions;
                if (editorOptions && editorOptions[name] !== undefined)
                  return editorOptions[name];
                return defaultOptions[name];
              }
            
              CodeMirror.defineExtension("foldOption", function(options, name) {
                return getOption(this, options, name);
              });
            });
            
          • foldgutter.css
            .CodeMirror-foldmarker {
              color: blue;
              text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
              font-family: arial;
              line-height: .3;
              cursor: pointer;
            }
            .CodeMirror-foldgutter {
              width: .7em;
            }
            .CodeMirror-foldgutter-open,
            .CodeMirror-foldgutter-folded {
              cursor: pointer;
            }
            .CodeMirror-foldgutter-open:after {
              content: "\25BE";
            }
            .CodeMirror-foldgutter-folded:after {
              content: "\25B8";
            }
            
          • foldgutter.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./foldcode"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./foldcode"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.clearGutter(cm.state.foldGutter.options.gutter);
                  cm.state.foldGutter = null;
                  cm.off("gutterClick", onGutterClick);
                  cm.off("change", onChange);
                  cm.off("viewportChange", onViewportChange);
                  cm.off("fold", onFold);
                  cm.off("unfold", onFold);
                  cm.off("swapDoc", updateInViewport);
                }
                if (val) {
                  cm.state.foldGutter = new State(parseOptions(val));
                  updateInViewport(cm);
                  cm.on("gutterClick", onGutterClick);
                  cm.on("change", onChange);
                  cm.on("viewportChange", onViewportChange);
                  cm.on("fold", onFold);
                  cm.on("unfold", onFold);
                  cm.on("swapDoc", updateInViewport);
                }
              });
            
              var Pos = CodeMirror.Pos;
            
              function State(options) {
                this.options = options;
                this.from = this.to = 0;
              }
            
              function parseOptions(opts) {
                if (opts === true) opts = {};
                if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
                if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
                if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
                return opts;
              }
            
              function isFolded(cm, line) {
                var marks = cm.findMarksAt(Pos(line));
                for (var i = 0; i < marks.length; ++i)
                  if (marks[i].__isFold && marks[i].find().from.line == line) return true;
              }
            
              function marker(spec) {
                if (typeof spec == "string") {
                  var elt = document.createElement("div");
                  elt.className = spec + " CodeMirror-guttermarker-subtle";
                  return elt;
                } else {
                  return spec.cloneNode(true);
                }
              }
            
              function updateFoldInfo(cm, from, to) {
                var opts = cm.state.foldGutter.options, cur = from;
                var minSize = cm.foldOption(opts, "minFoldSize");
                var func = cm.foldOption(opts, "rangeFinder");
                cm.eachLine(from, to, function(line) {
                  var mark = null;
                  if (isFolded(cm, cur)) {
                    mark = marker(opts.indicatorFolded);
                  } else {
                    var pos = Pos(cur, 0);
                    var range = func && func(cm, pos);
                    if (range && range.to.line - range.from.line >= minSize)
                      mark = marker(opts.indicatorOpen);
                  }
                  cm.setGutterMarker(line, opts.gutter, mark);
                  ++cur;
                });
              }
            
              function updateInViewport(cm) {
                var vp = cm.getViewport(), state = cm.state.foldGutter;
                if (!state) return;
                cm.operation(function() {
                  updateFoldInfo(cm, vp.from, vp.to);
                });
                state.from = vp.from; state.to = vp.to;
              }
            
              function onGutterClick(cm, line, gutter) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                if (gutter != opts.gutter) return;
                cm.foldCode(Pos(line, 0), opts.rangeFinder);
              }
            
              function onChange(cm) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                state.from = state.to = 0;
                clearTimeout(state.changeUpdate);
                state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
              }
            
              function onViewportChange(cm) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                clearTimeout(state.changeUpdate);
                state.changeUpdate = setTimeout(function() {
                  var vp = cm.getViewport();
                  if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
                    updateInViewport(cm);
                  } else {
                    cm.operation(function() {
                      if (vp.from < state.from) {
                        updateFoldInfo(cm, vp.from, state.from);
                        state.from = vp.from;
                      }
                      if (vp.to > state.to) {
                        updateFoldInfo(cm, state.to, vp.to);
                        state.to = vp.to;
                      }
                    });
                  }
                }, opts.updateViewportTimeSpan || 400);
              }
            
              function onFold(cm, from) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var line = from.line;
                if (line >= state.from && line < state.to)
                  updateFoldInfo(cm, line, line + 1);
              }
            });
            
          • indent-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "indent", function(cm, start) {
              var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
              if (!/\S/.test(firstLine)) return;
              var getIndent = function(line) {
                return CodeMirror.countColumn(line, null, tabSize);
              };
              var myIndent = getIndent(firstLine);
              var lastLineInFold = null;
              // Go through lines until we find a line that definitely doesn't belong in
              // the block we're folding, or to the end.
              for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
                var curLine = cm.getLine(i);
                var curIndent = getIndent(curLine);
                if (curIndent > myIndent) {
                  // Lines with a greater indent are considered part of the block.
                  lastLineInFold = i;
                } else if (!/\S/.test(curLine)) {
                  // Empty lines might be breaks within the block we're trying to fold.
                } else {
                  // A non-empty line at an indent equal to or less than ours marks the
                  // start of another block.
                  break;
                }
              }
              if (lastLineInFold) return {
                from: CodeMirror.Pos(start.line, firstLine.length),
                to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
              };
            });
            
            });
            
          • markdown-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
              var maxDepth = 100;
            
              function isHeader(lineNo) {
                var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
                return tokentype && /\bheader\b/.test(tokentype);
              }
            
              function headerLevel(lineNo, line, nextLine) {
                var match = line && line.match(/^#+/);
                if (match && isHeader(lineNo)) return match[0].length;
                match = nextLine && nextLine.match(/^[=\-]+\s*$/);
                if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
                return maxDepth;
              }
            
              var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
              var level = headerLevel(start.line, firstLine, nextLine);
              if (level === maxDepth) return undefined;
            
              var lastLineNo = cm.lastLine();
              var end = start.line, nextNextLine = cm.getLine(end + 2);
              while (end < lastLineNo) {
                if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
                ++end;
                nextLine = nextNextLine;
                nextNextLine = cm.getLine(end + 2);
              }
            
              return {
                from: CodeMirror.Pos(start.line, firstLine.length),
                to: CodeMirror.Pos(end, cm.getLine(end).length)
              };
            });
            
            });
            
          • xml-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
              function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
            
              var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
              var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
              var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
            
              function Iter(cm, line, ch, range) {
                this.line = line; this.ch = ch;
                this.cm = cm; this.text = cm.getLine(line);
                this.min = range ? range.from : cm.firstLine();
                this.max = range ? range.to - 1 : cm.lastLine();
              }
            
              function tagAt(iter, ch) {
                var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
                return type && /\btag\b/.test(type);
              }
            
              function nextLine(iter) {
                if (iter.line >= iter.max) return;
                iter.ch = 0;
                iter.text = iter.cm.getLine(++iter.line);
                return true;
              }
              function prevLine(iter) {
                if (iter.line <= iter.min) return;
                iter.text = iter.cm.getLine(--iter.line);
                iter.ch = iter.text.length;
                return true;
              }
            
              function toTagEnd(iter) {
                for (;;) {
                  var gt = iter.text.indexOf(">", iter.ch);
                  if (gt == -1) { if (nextLine(iter)) continue; else return; }
                  if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
                  var lastSlash = iter.text.lastIndexOf("/", gt);
                  var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
                  iter.ch = gt + 1;
                  return selfClose ? "selfClose" : "regular";
                }
              }
              function toTagStart(iter) {
                for (;;) {
                  var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
                  if (lt == -1) { if (prevLine(iter)) continue; else return; }
                  if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
                  xmlTagStart.lastIndex = lt;
                  iter.ch = lt;
                  var match = xmlTagStart.exec(iter.text);
                  if (match && match.index == lt) return match;
                }
              }
            
              function toNextTag(iter) {
                for (;;) {
                  xmlTagStart.lastIndex = iter.ch;
                  var found = xmlTagStart.exec(iter.text);
                  if (!found) { if (nextLine(iter)) continue; else return; }
                  if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
                  iter.ch = found.index + found[0].length;
                  return found;
                }
              }
              function toPrevTag(iter) {
                for (;;) {
                  var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
                  if (gt == -1) { if (prevLine(iter)) continue; else return; }
                  if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
                  var lastSlash = iter.text.lastIndexOf("/", gt);
                  var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
                  iter.ch = gt + 1;
                  return selfClose ? "selfClose" : "regular";
                }
              }
            
              function findMatchingClose(iter, tag) {
                var stack = [];
                for (;;) {
                  var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
                  if (!next || !(end = toTagEnd(iter))) return;
                  if (end == "selfClose") continue;
                  if (next[1]) { // closing tag
                    for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
                      stack.length = i;
                      break;
                    }
                    if (i < 0 && (!tag || tag == next[2])) return {
                      tag: next[2],
                      from: Pos(startLine, startCh),
                      to: Pos(iter.line, iter.ch)
                    };
                  } else { // opening tag
                    stack.push(next[2]);
                  }
                }
              }
              function findMatchingOpen(iter, tag) {
                var stack = [];
                for (;;) {
                  var prev = toPrevTag(iter);
                  if (!prev) return;
                  if (prev == "selfClose") { toTagStart(iter); continue; }
                  var endLine = iter.line, endCh = iter.ch;
                  var start = toTagStart(iter);
                  if (!start) return;
                  if (start[1]) { // closing tag
                    stack.push(start[2]);
                  } else { // opening tag
                    for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
                      stack.length = i;
                      break;
                    }
                    if (i < 0 && (!tag || tag == start[2])) return {
                      tag: start[2],
                      from: Pos(iter.line, iter.ch),
                      to: Pos(endLine, endCh)
                    };
                  }
                }
              }
            
              CodeMirror.registerHelper("fold", "xml", function(cm, start) {
                var iter = new Iter(cm, start.line, 0);
                for (;;) {
                  var openTag = toNextTag(iter), end;
                  if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
                  if (!openTag[1] && end != "selfClose") {
                    var start = Pos(iter.line, iter.ch);
                    var close = findMatchingClose(iter, openTag[2]);
                    return close && {from: start, to: close.from};
                  }
                }
              });
              CodeMirror.findMatchingTag = function(cm, pos, range) {
                var iter = new Iter(cm, pos.line, pos.ch, range);
                if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
                var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
                var start = end && toTagStart(iter);
                if (!end || !start || cmp(iter, pos) > 0) return;
                var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
                if (end == "selfClose") return {open: here, close: null, at: "open"};
            
                if (start[1]) { // closing tag
                  return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
                } else { // opening tag
                  iter = new Iter(cm, to.line, to.ch, range);
                  return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
                }
              };
            
              CodeMirror.findEnclosingTag = function(cm, pos, range) {
                var iter = new Iter(cm, pos.line, pos.ch, range);
                for (;;) {
                  var open = findMatchingOpen(iter);
                  if (!open) break;
                  var forward = new Iter(cm, pos.line, pos.ch, range);
                  var close = findMatchingClose(forward, open.tag);
                  if (close) return {open: open, close: close};
                }
              };
            
              // Used by addon/edit/closetag.js
              CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
                var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
                return findMatchingClose(iter, name);
              };
            });
            
        • hint
          • anyword-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var WORD = /[\w$]+/, RANGE = 500;
            
              CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
                var word = options && options.word || WORD;
                var range = options && options.range || RANGE;
                var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
                var end = cur.ch, start = end;
                while (start && word.test(curLine.charAt(start - 1))) --start;
                var curWord = start != end && curLine.slice(start, end);
            
                var list = [], seen = {};
                var re = new RegExp(word.source, "g");
                for (var dir = -1; dir <= 1; dir += 2) {
                  var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
                  for (; line != endLine; line += dir) {
                    var text = editor.getLine(line), m;
                    while (m = re.exec(text)) {
                      if (line == cur.line && m[0] === curWord) continue;
                      if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
                        seen[m[0]] = true;
                        list.push(m[0]);
                      }
                    }
                  }
                }
                return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
              });
            });
            
          • css-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../mode/css/css"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../mode/css/css"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
                                   "first-letter": 1, "first-line": 1, "first-child": 1,
                                   before: 1, after: 1, lang: 1};
            
              CodeMirror.registerHelper("hint", "css", function(cm) {
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                var inner = CodeMirror.innerMode(cm.getMode(), token.state);
                if (inner.mode.name != "css") return;
            
                var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
                if (/[^\w$_-]/.test(word)) {
                  word = ""; start = end = cur.ch;
                }
            
                var spec = CodeMirror.resolveMode("text/css");
            
                var result = [];
                function add(keywords) {
                  for (var name in keywords)
                    if (!word || name.lastIndexOf(word, 0) == 0)
                      result.push(name);
                }
            
                var st = inner.state.state;
                if (st == "pseudo" || token.type == "variable-3") {
                  add(pseudoClasses);
                } else if (st == "block" || st == "maybeprop") {
                  add(spec.propertyKeywords);
                } else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
                  add(spec.valueKeywords);
                  add(spec.colorKeywords);
                } else if (st == "media" || st == "media_parens") {
                  add(spec.mediaTypes);
                  add(spec.mediaFeatures);
                }
            
                if (result.length) return {
                  list: result,
                  from: CodeMirror.Pos(cur.line, start),
                  to: CodeMirror.Pos(cur.line, end)
                };
              });
            });
            
          • html-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./xml-hint"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./xml-hint"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
              var targets = ["_blank", "_self", "_top", "_parent"];
              var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
              var methods = ["get", "post", "put", "delete"];
              var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
              var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
                           "3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
                           "orientation:landscape", "device-height: [X]", "device-width: [X]"];
              var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
            
              var data = {
                a: {
                  attrs: {
                    href: null, ping: null, type: null,
                    media: media,
                    target: targets,
                    hreflang: langs
                  }
                },
                abbr: s,
                acronym: s,
                address: s,
                applet: s,
                area: {
                  attrs: {
                    alt: null, coords: null, href: null, target: null, ping: null,
                    media: media, hreflang: langs, type: null,
                    shape: ["default", "rect", "circle", "poly"]
                  }
                },
                article: s,
                aside: s,
                audio: {
                  attrs: {
                    src: null, mediagroup: null,
                    crossorigin: ["anonymous", "use-credentials"],
                    preload: ["none", "metadata", "auto"],
                    autoplay: ["", "autoplay"],
                    loop: ["", "loop"],
                    controls: ["", "controls"]
                  }
                },
                b: s,
                base: { attrs: { href: null, target: targets } },
                basefont: s,
                bdi: s,
                bdo: s,
                big: s,
                blockquote: { attrs: { cite: null } },
                body: s,
                br: s,
                button: {
                  attrs: {
                    form: null, formaction: null, name: null, value: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "autofocus"],
                    formenctype: encs,
                    formmethod: methods,
                    formnovalidate: ["", "novalidate"],
                    formtarget: targets,
                    type: ["submit", "reset", "button"]
                  }
                },
                canvas: { attrs: { width: null, height: null } },
                caption: s,
                center: s,
                cite: s,
                code: s,
                col: { attrs: { span: null } },
                colgroup: { attrs: { span: null } },
                command: {
                  attrs: {
                    type: ["command", "checkbox", "radio"],
                    label: null, icon: null, radiogroup: null, command: null, title: null,
                    disabled: ["", "disabled"],
                    checked: ["", "checked"]
                  }
                },
                data: { attrs: { value: null } },
                datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
                datalist: { attrs: { data: null } },
                dd: s,
                del: { attrs: { cite: null, datetime: null } },
                details: { attrs: { open: ["", "open"] } },
                dfn: s,
                dir: s,
                div: s,
                dl: s,
                dt: s,
                em: s,
                embed: { attrs: { src: null, type: null, width: null, height: null } },
                eventsource: { attrs: { src: null } },
                fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
                figcaption: s,
                figure: s,
                font: s,
                footer: s,
                form: {
                  attrs: {
                    action: null, name: null,
                    "accept-charset": charsets,
                    autocomplete: ["on", "off"],
                    enctype: encs,
                    method: methods,
                    novalidate: ["", "novalidate"],
                    target: targets
                  }
                },
                frame: s,
                frameset: s,
                h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
                head: {
                  attrs: {},
                  children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
                },
                header: s,
                hgroup: s,
                hr: s,
                html: {
                  attrs: { manifest: null },
                  children: ["head", "body"]
                },
                i: s,
                iframe: {
                  attrs: {
                    src: null, srcdoc: null, name: null, width: null, height: null,
                    sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
                    seamless: ["", "seamless"]
                  }
                },
                img: {
                  attrs: {
                    alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
                    crossorigin: ["anonymous", "use-credentials"]
                  }
                },
                input: {
                  attrs: {
                    alt: null, dirname: null, form: null, formaction: null,
                    height: null, list: null, max: null, maxlength: null, min: null,
                    name: null, pattern: null, placeholder: null, size: null, src: null,
                    step: null, value: null, width: null,
                    accept: ["audio/*", "video/*", "image/*"],
                    autocomplete: ["on", "off"],
                    autofocus: ["", "autofocus"],
                    checked: ["", "checked"],
                    disabled: ["", "disabled"],
                    formenctype: encs,
                    formmethod: methods,
                    formnovalidate: ["", "novalidate"],
                    formtarget: targets,
                    multiple: ["", "multiple"],
                    readonly: ["", "readonly"],
                    required: ["", "required"],
                    type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
                           "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
                           "file", "submit", "image", "reset", "button"]
                  }
                },
                ins: { attrs: { cite: null, datetime: null } },
                kbd: s,
                keygen: {
                  attrs: {
                    challenge: null, form: null, name: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    keytype: ["RSA"]
                  }
                },
                label: { attrs: { "for": null, form: null } },
                legend: s,
                li: { attrs: { value: null } },
                link: {
                  attrs: {
                    href: null, type: null,
                    hreflang: langs,
                    media: media,
                    sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
                  }
                },
                map: { attrs: { name: null } },
                mark: s,
                menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
                meta: {
                  attrs: {
                    content: null,
                    charset: charsets,
                    name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
                    "http-equiv": ["content-language", "content-type", "default-style", "refresh"]
                  }
                },
                meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
                nav: s,
                noframes: s,
                noscript: s,
                object: {
                  attrs: {
                    data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
                    typemustmatch: ["", "typemustmatch"]
                  }
                },
                ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
                optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
                option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
                output: { attrs: { "for": null, form: null, name: null } },
                p: s,
                param: { attrs: { name: null, value: null } },
                pre: s,
                progress: { attrs: { value: null, max: null } },
                q: { attrs: { cite: null } },
                rp: s,
                rt: s,
                ruby: s,
                s: s,
                samp: s,
                script: {
                  attrs: {
                    type: ["text/javascript"],
                    src: null,
                    async: ["", "async"],
                    defer: ["", "defer"],
                    charset: charsets
                  }
                },
                section: s,
                select: {
                  attrs: {
                    form: null, name: null, size: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    multiple: ["", "multiple"]
                  }
                },
                small: s,
                source: { attrs: { src: null, type: null, media: null } },
                span: s,
                strike: s,
                strong: s,
                style: {
                  attrs: {
                    type: ["text/css"],
                    media: media,
                    scoped: null
                  }
                },
                sub: s,
                summary: s,
                sup: s,
                table: s,
                tbody: s,
                td: { attrs: { colspan: null, rowspan: null, headers: null } },
                textarea: {
                  attrs: {
                    dirname: null, form: null, maxlength: null, name: null, placeholder: null,
                    rows: null, cols: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    readonly: ["", "readonly"],
                    required: ["", "required"],
                    wrap: ["soft", "hard"]
                  }
                },
                tfoot: s,
                th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
                thead: s,
                time: { attrs: { datetime: null } },
                title: s,
                tr: s,
                track: {
                  attrs: {
                    src: null, label: null, "default": null,
                    kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
                    srclang: langs
                  }
                },
                tt: s,
                u: s,
                ul: s,
                "var": s,
                video: {
                  attrs: {
                    src: null, poster: null, width: null, height: null,
                    crossorigin: ["anonymous", "use-credentials"],
                    preload: ["auto", "metadata", "none"],
                    autoplay: ["", "autoplay"],
                    mediagroup: ["movie"],
                    muted: ["", "muted"],
                    controls: ["", "controls"]
                  }
                },
                wbr: s
              };
            
              var globalAttrs = {
                accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
                "class": null,
                contenteditable: ["true", "false"],
                contextmenu: null,
                dir: ["ltr", "rtl", "auto"],
                draggable: ["true", "false", "auto"],
                dropzone: ["copy", "move", "link", "string:", "file:"],
                hidden: ["hidden"],
                id: null,
                inert: ["inert"],
                itemid: null,
                itemprop: null,
                itemref: null,
                itemscope: ["itemscope"],
                itemtype: null,
                lang: ["en", "es"],
                spellcheck: ["true", "false"],
                style: null,
                tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
                title: null,
                translate: ["yes", "no"],
                onclick: null,
                rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
              };
              function populate(obj) {
                for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
                  obj.attrs[attr] = globalAttrs[attr];
              }
            
              populate(s);
              for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
                populate(data[tag]);
            
              CodeMirror.htmlSchema = data;
              function htmlHint(cm, options) {
                var local = {schemaInfo: data};
                if (options) for (var opt in options) local[opt] = options[opt];
                return CodeMirror.hint.xml(cm, local);
              }
              CodeMirror.registerHelper("hint", "html", htmlHint);
            });
            
          • javascript-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var Pos = CodeMirror.Pos;
            
              function forEach(arr, f) {
                for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
              }
            
              function arrayContains(arr, item) {
                if (!Array.prototype.indexOf) {
                  var i = arr.length;
                  while (i--) {
                    if (arr[i] === item) {
                      return true;
                    }
                  }
                  return false;
                }
                return arr.indexOf(item) != -1;
              }
            
              function scriptHint(editor, keywords, getToken, options) {
                // Find the token at the cursor
                var cur = editor.getCursor(), token = getToken(editor, cur);
                if (/\b(?:string|comment)\b/.test(token.type)) return;
                token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
            
                // If it's not a 'word-style' token, ignore the token.
                if (!/^[\w$_]*$/.test(token.string)) {
                  token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
                           type: token.string == "." ? "property" : null};
                } else if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
            
                var tprop = token;
                // If it is a property, find out what it is a property of.
                while (tprop.type == "property") {
                  tprop = getToken(editor, Pos(cur.line, tprop.start));
                  if (tprop.string != ".") return;
                  tprop = getToken(editor, Pos(cur.line, tprop.start));
                  if (!context) var context = [];
                  context.push(tprop);
                }
                return {list: getCompletions(token, context, keywords, options),
                        from: Pos(cur.line, token.start),
                        to: Pos(cur.line, token.end)};
              }
            
              function javascriptHint(editor, options) {
                return scriptHint(editor, javascriptKeywords,
                                  function (e, cur) {return e.getTokenAt(cur);},
                                  options);
              };
              CodeMirror.registerHelper("hint", "javascript", javascriptHint);
            
              function getCoffeeScriptToken(editor, cur) {
              // This getToken, it is for coffeescript, imitates the behavior of
              // getTokenAt method in javascript.js, that is, returning "property"
              // type and treat "." as indepenent token.
                var token = editor.getTokenAt(cur);
                if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
                  token.end = token.start;
                  token.string = '.';
                  token.type = "property";
                }
                else if (/^\.[\w$_]*$/.test(token.string)) {
                  token.type = "property";
                  token.start++;
                  token.string = token.string.replace(/\./, '');
                }
                return token;
              }
            
              function coffeescriptHint(editor, options) {
                return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
              }
              CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
            
              var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
                                 "toUpperCase toLowerCase split concat match replace search").split(" ");
              var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
                                "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
              var funcProps = "prototype apply call bind".split(" ");
              var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
                              "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
              var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
                              "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
            
              function getCompletions(token, context, keywords, options) {
                var found = [], start = token.string, global = options && options.globalScope || window;
                function maybeAdd(str) {
                  if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
                }
                function gatherCompletions(obj) {
                  if (typeof obj == "string") forEach(stringProps, maybeAdd);
                  else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
                  else if (obj instanceof Function) forEach(funcProps, maybeAdd);
                  for (var name in obj) maybeAdd(name);
                }
            
                if (context && context.length) {
                  // If this is a property, see if it belongs to some object we can
                  // find in the current environment.
                  var obj = context.pop(), base;
                  if (obj.type && obj.type.indexOf("variable") === 0) {
                    if (options && options.additionalContext)
                      base = options.additionalContext[obj.string];
                    if (!options || options.useGlobalScope !== false)
                      base = base || global[obj.string];
                  } else if (obj.type == "string") {
                    base = "";
                  } else if (obj.type == "atom") {
                    base = 1;
                  } else if (obj.type == "function") {
                    if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
                        (typeof global.jQuery == 'function'))
                      base = global.jQuery();
                    else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
                      base = global._();
                  }
                  while (base != null && context.length)
                    base = base[context.pop().string];
                  if (base != null) gatherCompletions(base);
                } else {
                  // If not, just look in the global object and any local scope
                  // (reading into JS mode internals to get at the local and global variables)
                  for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
                  for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
                  if (!options || options.useGlobalScope !== false)
                    gatherCompletions(global);
                  forEach(keywords, maybeAdd);
                }
                return found;
              }
            });
            
          • show-hint.css
            .CodeMirror-hints {
              position: absolute;
              z-index: 10;
              overflow: hidden;
              list-style: none;
            
              margin: 0;
              padding: 2px;
            
              -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              border-radius: 3px;
              border: 1px solid silver;
            
              background: white;
              font-size: 90%;
              font-family: monospace;
            
              max-height: 20em;
              overflow-y: auto;
            }
            
            .CodeMirror-hint {
              margin: 0;
              padding: 0 4px;
              border-radius: 2px;
              max-width: 19em;
              overflow: hidden;
              white-space: pre;
              color: black;
              cursor: pointer;
            }
            
            li.CodeMirror-hint-active {
              background: #08f;
              color: white;
            }
            
          • show-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var HINT_ELEMENT_CLASS        = "CodeMirror-hint";
              var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
            
              // This is the old interface, kept around for now to stay
              // backwards-compatible.
              CodeMirror.showHint = function(cm, getHints, options) {
                if (!getHints) return cm.showHint(options);
                if (options && options.async) getHints.async = true;
                var newOpts = {hint: getHints};
                if (options) for (var prop in options) newOpts[prop] = options[prop];
                return cm.showHint(newOpts);
              };
            
              var asyncRunID = 0;
              function retrieveHints(getter, cm, options, then) {
                if (getter.async) {
                  var id = ++asyncRunID;
                  getter(cm, function(hints) {
                    if (asyncRunID == id) then(hints);
                  }, options);
                } else {
                  then(getter(cm, options));
                }
              }
            
              CodeMirror.defineExtension("showHint", function(options) {
                // We want a single cursor position.
                if (this.listSelections().length > 1 || this.somethingSelected()) return;
            
                if (this.state.completionActive) this.state.completionActive.close();
                var completion = this.state.completionActive = new Completion(this, options);
                var getHints = completion.options.hint;
                if (!getHints) return;
            
                CodeMirror.signal(this, "startCompletion", this);
                return retrieveHints(getHints, this, completion.options, function(hints) { completion.showHints(hints); });
              });
            
              function Completion(cm, options) {
                this.cm = cm;
                this.options = this.buildOptions(options);
                this.widget = this.onClose = null;
              }
            
              Completion.prototype = {
                close: function() {
                  if (!this.active()) return;
                  this.cm.state.completionActive = null;
            
                  if (this.widget) this.widget.close();
                  if (this.onClose) this.onClose();
                  CodeMirror.signal(this.cm, "endCompletion", this.cm);
                },
            
                active: function() {
                  return this.cm.state.completionActive == this;
                },
            
                pick: function(data, i) {
                  var completion = data.list[i];
                  if (completion.hint) completion.hint(this.cm, data, completion);
                  else this.cm.replaceRange(getText(completion), completion.from || data.from,
                                            completion.to || data.to, "complete");
                  CodeMirror.signal(data, "pick", completion);
                  this.close();
                },
            
                showHints: function(data) {
                  if (!data || !data.list.length || !this.active()) return this.close();
            
                  if (this.options.completeSingle && data.list.length == 1)
                    this.pick(data, 0);
                  else
                    this.showWidget(data);
                },
            
                showWidget: function(data) {
                  this.widget = new Widget(this, data);
                  CodeMirror.signal(data, "shown");
            
                  var debounce = 0, completion = this, finished;
                  var closeOn = this.options.closeCharacters;
                  var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
            
                  var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
                    return setTimeout(fn, 1000/60);
                  };
                  var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
            
                  function done() {
                    if (finished) return;
                    finished = true;
                    completion.close();
                    completion.cm.off("cursorActivity", activity);
                    if (data) CodeMirror.signal(data, "close");
                  }
            
                  function update() {
                    if (finished) return;
                    CodeMirror.signal(data, "update");
                    retrieveHints(completion.options.hint, completion.cm, completion.options, finishUpdate);
                  }
                  function finishUpdate(data_) {
                    data = data_;
                    if (finished) return;
                    if (!data || !data.list.length) return done();
                    if (completion.widget) completion.widget.close();
                    completion.widget = new Widget(completion, data);
                  }
            
                  function clearDebounce() {
                    if (debounce) {
                      cancelAnimationFrame(debounce);
                      debounce = 0;
                    }
                  }
            
                  function activity() {
                    clearDebounce();
                    var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
                    if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
                        pos.ch < startPos.ch || completion.cm.somethingSelected() ||
                        (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
                      completion.close();
                    } else {
                      debounce = requestAnimationFrame(update);
                      if (completion.widget) completion.widget.close();
                    }
                  }
                  this.cm.on("cursorActivity", activity);
                  this.onClose = done;
                },
            
                buildOptions: function(options) {
                  var editor = this.cm.options.hintOptions;
                  var out = {};
                  for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
                  if (editor) for (var prop in editor)
                    if (editor[prop] !== undefined) out[prop] = editor[prop];
                  if (options) for (var prop in options)
                    if (options[prop] !== undefined) out[prop] = options[prop];
                  return out;
                }
              };
            
              function getText(completion) {
                if (typeof completion == "string") return completion;
                else return completion.text;
              }
            
              function buildKeyMap(completion, handle) {
                var baseMap = {
                  Up: function() {handle.moveFocus(-1);},
                  Down: function() {handle.moveFocus(1);},
                  PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
                  PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
                  Home: function() {handle.setFocus(0);},
                  End: function() {handle.setFocus(handle.length - 1);},
                  Enter: handle.pick,
                  Tab: handle.pick,
                  Esc: handle.close
                };
                var custom = completion.options.customKeys;
                var ourMap = custom ? {} : baseMap;
                function addBinding(key, val) {
                  var bound;
                  if (typeof val != "string")
                    bound = function(cm) { return val(cm, handle); };
                  // This mechanism is deprecated
                  else if (baseMap.hasOwnProperty(val))
                    bound = baseMap[val];
                  else
                    bound = val;
                  ourMap[key] = bound;
                }
                if (custom)
                  for (var key in custom) if (custom.hasOwnProperty(key))
                    addBinding(key, custom[key]);
                var extra = completion.options.extraKeys;
                if (extra)
                  for (var key in extra) if (extra.hasOwnProperty(key))
                    addBinding(key, extra[key]);
                return ourMap;
              }
            
              function getHintElement(hintsElement, el) {
                while (el && el != hintsElement) {
                  if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
                  el = el.parentNode;
                }
              }
            
              function Widget(completion, data) {
                this.completion = completion;
                this.data = data;
                var widget = this, cm = completion.cm;
            
                var hints = this.hints = document.createElement("ul");
                hints.className = "CodeMirror-hints";
                this.selectedHint = data.selectedHint || 0;
            
                var completions = data.list;
                for (var i = 0; i < completions.length; ++i) {
                  var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
                  var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
                  if (cur.className != null) className = cur.className + " " + className;
                  elt.className = className;
                  if (cur.render) cur.render(elt, data, cur);
                  else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
                  elt.hintId = i;
                }
            
                var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
                var left = pos.left, top = pos.bottom, below = true;
                hints.style.left = left + "px";
                hints.style.top = top + "px";
                // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
                var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
                var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
                (completion.options.container || document.body).appendChild(hints);
                var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
                if (overlapY > 0) {
                  var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
                  if (curTop - height > 0) { // Fits above cursor
                    hints.style.top = (top = pos.top - height) + "px";
                    below = false;
                  } else if (height > winH) {
                    hints.style.height = (winH - 5) + "px";
                    hints.style.top = (top = pos.bottom - box.top) + "px";
                    var cursor = cm.getCursor();
                    if (data.from.ch != cursor.ch) {
                      pos = cm.cursorCoords(cursor);
                      hints.style.left = (left = pos.left) + "px";
                      box = hints.getBoundingClientRect();
                    }
                  }
                }
                var overlapX = box.right - winW;
                if (overlapX > 0) {
                  if (box.right - box.left > winW) {
                    hints.style.width = (winW - 5) + "px";
                    overlapX -= (box.right - box.left) - winW;
                  }
                  hints.style.left = (left = pos.left - overlapX) + "px";
                }
            
                cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
                  moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
                  setFocus: function(n) { widget.changeActive(n); },
                  menuSize: function() { return widget.screenAmount(); },
                  length: completions.length,
                  close: function() { completion.close(); },
                  pick: function() { widget.pick(); },
                  data: data
                }));
            
                if (completion.options.closeOnUnfocus) {
                  var closingOnBlur;
                  cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
                  cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
                }
            
                var startScroll = cm.getScrollInfo();
                cm.on("scroll", this.onScroll = function() {
                  var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
                  var newTop = top + startScroll.top - curScroll.top;
                  var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
                  if (!below) point += hints.offsetHeight;
                  if (point <= editor.top || point >= editor.bottom) return completion.close();
                  hints.style.top = newTop + "px";
                  hints.style.left = (left + startScroll.left - curScroll.left) + "px";
                });
            
                CodeMirror.on(hints, "dblclick", function(e) {
                  var t = getHintElement(hints, e.target || e.srcElement);
                  if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
                });
            
                CodeMirror.on(hints, "click", function(e) {
                  var t = getHintElement(hints, e.target || e.srcElement);
                  if (t && t.hintId != null) {
                    widget.changeActive(t.hintId);
                    if (completion.options.completeOnSingleClick) widget.pick();
                  }
                });
            
                CodeMirror.on(hints, "mousedown", function() {
                  setTimeout(function(){cm.focus();}, 20);
                });
            
                CodeMirror.signal(data, "select", completions[0], hints.firstChild);
                return true;
              }
            
              Widget.prototype = {
                close: function() {
                  if (this.completion.widget != this) return;
                  this.completion.widget = null;
                  this.hints.parentNode.removeChild(this.hints);
                  this.completion.cm.removeKeyMap(this.keyMap);
            
                  var cm = this.completion.cm;
                  if (this.completion.options.closeOnUnfocus) {
                    cm.off("blur", this.onBlur);
                    cm.off("focus", this.onFocus);
                  }
                  cm.off("scroll", this.onScroll);
                },
            
                pick: function() {
                  this.completion.pick(this.data, this.selectedHint);
                },
            
                changeActive: function(i, avoidWrap) {
                  if (i >= this.data.list.length)
                    i = avoidWrap ? this.data.list.length - 1 : 0;
                  else if (i < 0)
                    i = avoidWrap ? 0  : this.data.list.length - 1;
                  if (this.selectedHint == i) return;
                  var node = this.hints.childNodes[this.selectedHint];
                  node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
                  node = this.hints.childNodes[this.selectedHint = i];
                  node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
                  if (node.offsetTop < this.hints.scrollTop)
                    this.hints.scrollTop = node.offsetTop - 3;
                  else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
                    this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
                  CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
                },
            
                screenAmount: function() {
                  return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
                }
              };
            
              CodeMirror.registerHelper("hint", "auto", function(cm, options) {
                var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
                if (helpers.length) {
                  for (var i = 0; i < helpers.length; i++) {
                    var cur = helpers[i](cm, options);
                    if (cur && cur.list.length) return cur;
                  }
                } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
                  if (words) return CodeMirror.hint.fromList(cm, {words: words});
                } else if (CodeMirror.hint.anyword) {
                  return CodeMirror.hint.anyword(cm, options);
                }
              });
            
              CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                var found = [];
                for (var i = 0; i < options.words.length; i++) {
                  var word = options.words[i];
                  if (word.slice(0, token.string.length) == token.string)
                    found.push(word);
                }
            
                if (found.length) return {
                  list: found,
                  from: CodeMirror.Pos(cur.line, token.start),
                        to: CodeMirror.Pos(cur.line, token.end)
                };
              });
            
              CodeMirror.commands.autocomplete = CodeMirror.showHint;
            
              var defaultOptions = {
                hint: CodeMirror.hint.auto,
                completeSingle: true,
                alignWithWord: true,
                closeCharacters: /[\s()\[\]{};:>,]/,
                closeOnUnfocus: true,
                completeOnSingleClick: false,
                container: null,
                customKeys: null,
                extraKeys: null
              };
            
              CodeMirror.defineOption("hintOptions", null);
            });
            
          • sql-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var tables;
              var defaultTable;
              var keywords;
              var CONS = {
                QUERY_DIV: ";",
                ALIAS_KEYWORD: "AS"
              };
              var Pos = CodeMirror.Pos;
            
              function getKeywords(editor) {
                var mode = editor.doc.modeOption;
                if (mode === "sql") mode = "text/x-sql";
                return CodeMirror.resolveMode(mode).keywords;
              }
            
              function getText(item) {
                return typeof item == "string" ? item : item.text;
              }
            
              function getItem(list, item) {
                if (!list.slice) return list[item];
                for (var i = list.length - 1; i >= 0; i--) if (getText(list[i]) == item)
                  return list[i];
              }
            
              function shallowClone(object) {
                var result = {};
                for (var key in object) if (object.hasOwnProperty(key))
                  result[key] = object[key];
                return result;
              }
            
              function match(string, word) {
                var len = string.length;
                var sub = getText(word).substr(0, len);
                return string.toUpperCase() === sub.toUpperCase();
              }
            
              function addMatches(result, search, wordlist, formatter) {
                for (var word in wordlist) {
                  if (!wordlist.hasOwnProperty(word)) continue;
                  if (Array.isArray(wordlist)) {
                    word = wordlist[word];
                  }
                  if (match(search, word)) {
                    result.push(formatter(word));
                  }
                }
              }
            
              function cleanName(name) {
                // Get rid name from backticks(`) and preceding dot(.)
                if (name.charAt(0) == ".") {
                  name = name.substr(1);
                }
                return name.replace(/`/g, "");
              }
            
              function insertBackticks(name) {
                var nameParts = getText(name).split(".");
                for (var i = 0; i < nameParts.length; i++)
                  nameParts[i] = "`" + nameParts[i] + "`";
                var escaped = nameParts.join(".");
                if (typeof name == "string") return escaped;
                name = shallowClone(name);
                name.text = escaped;
                return name;
              }
            
              function nameCompletion(cur, token, result, editor) {
                // Try to complete table, colunm names and return start position of completion
                var useBacktick = false;
                var nameParts = [];
                var start = token.start;
                var cont = true;
                while (cont) {
                  cont = (token.string.charAt(0) == ".");
                  useBacktick = useBacktick || (token.string.charAt(0) == "`");
            
                  start = token.start;
                  nameParts.unshift(cleanName(token.string));
            
                  token = editor.getTokenAt(Pos(cur.line, token.start));
                  if (token.string == ".") {
                    cont = true;
                    token = editor.getTokenAt(Pos(cur.line, token.start));
                  }
                }
            
                // Try to complete table names
                var string = nameParts.join(".");
                addMatches(result, string, tables, function(w) {
                  return useBacktick ? insertBackticks(w) : w;
                });
            
                // Try to complete columns from defaultTable
                addMatches(result, string, defaultTable, function(w) {
                  return useBacktick ? insertBackticks(w) : w;
                });
            
                // Try to complete columns
                string = nameParts.pop();
                var table = nameParts.join(".");
            
                // Check if table is available. If not, find table by Alias
                if (!getItem(tables, table))
                  table = findTableByAlias(table, editor);
            
                var columns = getItem(tables, table);
                if (columns && Array.isArray(tables) && columns.columns)
                  columns = columns.columns;
            
                if (columns) {
                  addMatches(result, string, columns, function(w) {
                    if (typeof w == "string") {
                      w = table + "." + w;
                    } else {
                      w = shallowClone(w);
                      w.text = table + "." + w.text;
                    }
                    return useBacktick ? insertBackticks(w) : w;
                  });
                }
            
                return start;
              }
            
              function eachWord(lineText, f) {
                if (!lineText) return;
                var excepted = /[,;]/g;
                var words = lineText.split(" ");
                for (var i = 0; i < words.length; i++) {
                  f(words[i]?words[i].replace(excepted, '') : '');
                }
              }
            
              function convertCurToNumber(cur) {
                // max characters of a line is 999,999.
                return cur.line + cur.ch / Math.pow(10, 6);
              }
            
              function convertNumberToCur(num) {
                return Pos(Math.floor(num), +num.toString().split('.').pop());
              }
            
              function findTableByAlias(alias, editor) {
                var doc = editor.doc;
                var fullQuery = doc.getValue();
                var aliasUpperCase = alias.toUpperCase();
                var previousWord = "";
                var table = "";
                var separator = [];
                var validRange = {
                  start: Pos(0, 0),
                  end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
                };
            
                //add separator
                var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
                while(indexOfSeparator != -1) {
                  separator.push(doc.posFromIndex(indexOfSeparator));
                  indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
                }
                separator.unshift(Pos(0, 0));
                separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
            
                //find valid range
                var prevItem = 0;
                var current = convertCurToNumber(editor.getCursor());
                for (var i=0; i< separator.length; i++) {
                  var _v = convertCurToNumber(separator[i]);
                  if (current > prevItem && current <= _v) {
                    validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
                    break;
                  }
                  prevItem = _v;
                }
            
                var query = doc.getRange(validRange.start, validRange.end, false);
            
                for (var i = 0; i < query.length; i++) {
                  var lineText = query[i];
                  eachWord(lineText, function(word) {
                    var wordUpperCase = word.toUpperCase();
                    if (wordUpperCase === aliasUpperCase && getItem(tables, previousWord))
                      table = previousWord;
                    if (wordUpperCase !== CONS.ALIAS_KEYWORD)
                      previousWord = word;
                  });
                  if (table) break;
                }
                return table;
              }
            
              CodeMirror.registerHelper("hint", "sql", function(editor, options) {
                tables = (options && options.tables) || {};
                var defaultTableName = options && options.defaultTable;
                defaultTable = (defaultTableName && getItem(tables, defaultTableName)) || [];
                keywords = keywords || getKeywords(editor);
            
                var cur = editor.getCursor();
                var result = [];
                var token = editor.getTokenAt(cur), start, end, search;
                if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
            
                if (token.string.match(/^[.`\w@]\w*$/)) {
                  search = token.string;
                  start = token.start;
                  end = token.end;
                } else {
                  start = end = cur.ch;
                  search = "";
                }
                if (search.charAt(0) == "." || search.charAt(0) == "`") {
                  start = nameCompletion(cur, token, result, editor);
                } else {
                  addMatches(result, search, tables, function(w) {return w;});
                  addMatches(result, search, defaultTable, function(w) {return w;});
                  addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
                }
            
                return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
              });
            });
            
          • xml-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
            
              function getHints(cm, options) {
                var tags = options && options.schemaInfo;
                var quote = (options && options.quoteChar) || '"';
                if (!tags) return;
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
                var inner = CodeMirror.innerMode(cm.getMode(), token.state);
                if (inner.mode.name != "xml") return;
                var result = [], replaceToken = false, prefix;
                var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
                var tagName = tag && /^\w/.test(token.string), tagStart;
            
                if (tagName) {
                  var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
                  var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
                  if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
                } else if (tag && token.string == "<") {
                  tagType = "open";
                } else if (tag && token.string == "</") {
                  tagType = "close";
                }
            
                if (!tag && !inner.state.tagName || tagType) {
                  if (tagName)
                    prefix = token.string;
                  replaceToken = tagType;
                  var cx = inner.state.context, curTag = cx && tags[cx.tagName];
                  var childList = cx ? curTag && curTag.children : tags["!top"];
                  if (childList && tagType != "close") {
                    for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
                      result.push("<" + childList[i]);
                  } else if (tagType != "close") {
                    for (var name in tags)
                      if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
                        result.push("<" + name);
                  }
                  if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
                    result.push("</" + cx.tagName + ">");
                } else {
                  // Attribute completion
                  var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
                  var globalAttrs = tags["!attrs"];
                  if (!attrs && !globalAttrs) return;
                  if (!attrs) {
                    attrs = globalAttrs;
                  } else if (globalAttrs) { // Combine tag-local and global attributes
                    var set = {};
                    for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
                    for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
                    attrs = set;
                  }
                  if (token.type == "string" || token.string == "=") { // A value
                    var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
                                             Pos(cur.line, token.type == "string" ? token.start : token.end));
                    var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
                    if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
                    if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
                    if (token.type == "string") {
                      prefix = token.string;
                      var n = 0;
                      if (/['"]/.test(token.string.charAt(0))) {
                        quote = token.string.charAt(0);
                        prefix = token.string.slice(1);
                        n++;
                      }
                      var len = token.string.length;
                      if (/['"]/.test(token.string.charAt(len - 1))) {
                        quote = token.string.charAt(len - 1);
                        prefix = token.string.substr(n, len - 2);
                      }
                      replaceToken = true;
                    }
                    for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
                      result.push(quote + atValues[i] + quote);
                  } else { // An attribute name
                    if (token.type == "attribute") {
                      prefix = token.string;
                      replaceToken = true;
                    }
                    for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
                      result.push(attr);
                  }
                }
                return {
                  list: result,
                  from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
                  to: replaceToken ? Pos(cur.line, token.end) : cur
                };
              }
            
              CodeMirror.registerHelper("hint", "xml", getHints);
            });
            
        • lint
          • coffeescript-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
            
            // declare global: coffeelint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "coffeescript", function(text) {
              var found = [];
              var parseError = function(err) {
                var loc = err.lineNumber;
                found.push({from: CodeMirror.Pos(loc-1, 0),
                            to: CodeMirror.Pos(loc, 0),
                            severity: err.level,
                            message: err.message});
              };
              try {
                var res = coffeelint.lint(text);
                for(var i = 0; i < res.length; i++) {
                  parseError(res[i]);
                }
              } catch(e) {
                found.push({from: CodeMirror.Pos(e.location.first_line, 0),
                            to: CodeMirror.Pos(e.location.last_line, e.location.last_column),
                            severity: 'error',
                            message: e.message});
              }
              return found;
            });
            
            });
            
          • css-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on csslint.js from https://github.com/stubbornella/csslint
            
            // declare global: CSSLint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "css", function(text) {
              var found = [];
              if (!window.CSSLint) return found;
              var results = CSSLint.verify(text), messages = results.messages, message = null;
              for ( var i = 0; i < messages.length; i++) {
                message = messages[i];
                var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
                found.push({
                  from: CodeMirror.Pos(startLine, startCol),
                  to: CodeMirror.Pos(endLine, endCol),
                  message: message.message,
                  severity : message.type
                });
              }
              return found;
            });
            
            });
            
          • javascript-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              // declare global: JSHINT
            
              var bogus = [ "Dangerous comment" ];
            
              var warnings = [ [ "Expected '{'",
                                 "Statement body should be inside '{ }' braces." ] ];
            
              var errors = [ "Missing semicolon", "Extra comma", "Missing property name",
                             "Unmatched ", " and instead saw", " is not defined",
                             "Unclosed string", "Stopping, unable to continue" ];
            
              function validator(text, options) {
                if (!window.JSHINT) return [];
                JSHINT(text, options);
                var errors = JSHINT.data().errors, result = [];
                if (errors) parseErrors(errors, result);
                return result;
              }
            
              CodeMirror.registerHelper("lint", "javascript", validator);
            
              function cleanup(error) {
                // All problems are warnings by default
                fixWith(error, warnings, "warning", true);
                fixWith(error, errors, "error");
            
                return isBogus(error) ? null : error;
              }
            
              function fixWith(error, fixes, severity, force) {
                var description, fix, find, replace, found;
            
                description = error.description;
            
                for ( var i = 0; i < fixes.length; i++) {
                  fix = fixes[i];
                  find = (typeof fix === "string" ? fix : fix[0]);
                  replace = (typeof fix === "string" ? null : fix[1]);
                  found = description.indexOf(find) !== -1;
            
                  if (force || found) {
                    error.severity = severity;
                  }
                  if (found && replace) {
                    error.description = replace;
                  }
                }
              }
            
              function isBogus(error) {
                var description = error.description;
                for ( var i = 0; i < bogus.length; i++) {
                  if (description.indexOf(bogus[i]) !== -1) {
                    return true;
                  }
                }
                return false;
              }
            
              function parseErrors(errors, output) {
                for ( var i = 0; i < errors.length; i++) {
                  var error = errors[i];
                  if (error) {
                    var linetabpositions, index;
            
                    linetabpositions = [];
            
                    // This next block is to fix a problem in jshint. Jshint
                    // replaces
                    // all tabs with spaces then performs some checks. The error
                    // positions (character/space) are then reported incorrectly,
                    // not taking the replacement step into account. Here we look
                    // at the evidence line and try to adjust the character position
                    // to the correct value.
                    if (error.evidence) {
                      // Tab positions are computed once per line and cached
                      var tabpositions = linetabpositions[error.line];
                      if (!tabpositions) {
                        var evidence = error.evidence;
                        tabpositions = [];
                        // ugggh phantomjs does not like this
                        // forEachChar(evidence, function(item, index) {
                        Array.prototype.forEach.call(evidence, function(item,
                                                                        index) {
                          if (item === '\t') {
                            // First col is 1 (not 0) to match error
                            // positions
                            tabpositions.push(index + 1);
                          }
                        });
                        linetabpositions[error.line] = tabpositions;
                      }
                      if (tabpositions.length > 0) {
                        var pos = error.character;
                        tabpositions.forEach(function(tabposition) {
                          if (pos > tabposition) pos -= 1;
                        });
                        error.character = pos;
                      }
                    }
            
                    var start = error.character - 1, end = start + 1;
                    if (error.evidence) {
                      index = error.evidence.substring(start).search(/.\b/);
                      if (index > -1) {
                        end += index;
                      }
                    }
            
                    // Convert to format expected by validation service
                    error.description = error.reason;// + "(jshint)";
                    error.start = error.character;
                    error.end = end;
                    error = cleanup(error);
            
                    if (error)
                      output.push({message: error.description,
                                   severity: error.severity,
                                   from: CodeMirror.Pos(error.line - 1, start),
                                   to: CodeMirror.Pos(error.line - 1, end)});
                  }
                }
              }
            });
            
          • json-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on jsonlint.js from https://github.com/zaach/jsonlint
            
            // declare global: jsonlint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "json", function(text) {
              var found = [];
              jsonlint.parseError = function(str, hash) {
                var loc = hash.loc;
                found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
                            to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
                            message: str});
              };
              try { jsonlint.parse(text); }
              catch(e) {}
              return found;
            });
            
            });
            
          • lint.css
            /* The lint marker gutter */
            .CodeMirror-lint-markers {
              width: 16px;
            }
            
            .CodeMirror-lint-tooltip {
              background-color: infobackground;
              border: 1px solid black;
              border-radius: 4px 4px 4px 4px;
              color: infotext;
              font-family: monospace;
              font-size: 10pt;
              overflow: hidden;
              padding: 2px 5px;
              position: fixed;
              white-space: pre;
              white-space: pre-wrap;
              z-index: 100;
              max-width: 600px;
              opacity: 0;
              transition: opacity .4s;
              -moz-transition: opacity .4s;
              -webkit-transition: opacity .4s;
              -o-transition: opacity .4s;
              -ms-transition: opacity .4s;
            }
            
            .CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
              background-position: left bottom;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-lint-mark-error {
              background-image:
              url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
              ;
            }
            
            .CodeMirror-lint-mark-warning {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
              background-position: center center;
              background-repeat: no-repeat;
              cursor: pointer;
              display: inline-block;
              height: 16px;
              width: 16px;
              vertical-align: middle;
              position: relative;
            }
            
            .CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
              padding-left: 18px;
              background-position: top left;
              background-repeat: no-repeat;
            }
            
            .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-multiple {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
              background-repeat: no-repeat;
              background-position: right bottom;
              width: 100%; height: 100%;
            }
            
          • lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var GUTTER_ID = "CodeMirror-lint-markers";
            
              function showTooltip(e, content) {
                var tt = document.createElement("div");
                tt.className = "CodeMirror-lint-tooltip";
                tt.appendChild(content.cloneNode(true));
                document.body.appendChild(tt);
            
                function position(e) {
                  if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
                  tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
                  tt.style.left = (e.clientX + 5) + "px";
                }
                CodeMirror.on(document, "mousemove", position);
                position(e);
                if (tt.style.opacity != null) tt.style.opacity = 1;
                return tt;
              }
              function rm(elt) {
                if (elt.parentNode) elt.parentNode.removeChild(elt);
              }
              function hideTooltip(tt) {
                if (!tt.parentNode) return;
                if (tt.style.opacity == null) rm(tt);
                tt.style.opacity = 0;
                setTimeout(function() { rm(tt); }, 600);
              }
            
              function showTooltipFor(e, content, node) {
                var tooltip = showTooltip(e, content);
                function hide() {
                  CodeMirror.off(node, "mouseout", hide);
                  if (tooltip) { hideTooltip(tooltip); tooltip = null; }
                }
                var poll = setInterval(function() {
                  if (tooltip) for (var n = node;; n = n.parentNode) {
                    if (n && n.nodeType == 11) n = n.host;
                    if (n == document.body) return;
                    if (!n) { hide(); break; }
                  }
                  if (!tooltip) return clearInterval(poll);
                }, 400);
                CodeMirror.on(node, "mouseout", hide);
              }
            
              function LintState(cm, options, hasGutter) {
                this.marked = [];
                this.options = options;
                this.timeout = null;
                this.hasGutter = hasGutter;
                this.onMouseOver = function(e) { onMouseOver(cm, e); };
              }
            
              function parseOptions(cm, options) {
                if (options instanceof Function) return {getAnnotations: options};
                if (!options || options === true) options = {};
                if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
                if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
                return options;
              }
            
              function clearMarks(cm) {
                var state = cm.state.lint;
                if (state.hasGutter) cm.clearGutter(GUTTER_ID);
                for (var i = 0; i < state.marked.length; ++i)
                  state.marked[i].clear();
                state.marked.length = 0;
              }
            
              function makeMarker(labels, severity, multiple, tooltips) {
                var marker = document.createElement("div"), inner = marker;
                marker.className = "CodeMirror-lint-marker-" + severity;
                if (multiple) {
                  inner = marker.appendChild(document.createElement("div"));
                  inner.className = "CodeMirror-lint-marker-multiple";
                }
            
                if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
                  showTooltipFor(e, labels, inner);
                });
            
                return marker;
              }
            
              function getMaxSeverity(a, b) {
                if (a == "error") return a;
                else return b;
              }
            
              function groupByLine(annotations) {
                var lines = [];
                for (var i = 0; i < annotations.length; ++i) {
                  var ann = annotations[i], line = ann.from.line;
                  (lines[line] || (lines[line] = [])).push(ann);
                }
                return lines;
              }
            
              function annotationTooltip(ann) {
                var severity = ann.severity;
                if (!severity) severity = "error";
                var tip = document.createElement("div");
                tip.className = "CodeMirror-lint-message-" + severity;
                tip.appendChild(document.createTextNode(ann.message));
                return tip;
              }
            
              function startLinting(cm) {
                var state = cm.state.lint, options = state.options;
                var passOptions = options.options || options; // Support deprecated passing of `options` property in options
                if (options.async || options.getAnnotations.async)
                  options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
                else
                  updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));
              }
            
              function updateLinting(cm, annotationsNotSorted) {
                clearMarks(cm);
                var state = cm.state.lint, options = state.options;
            
                var annotations = groupByLine(annotationsNotSorted);
            
                for (var line = 0; line < annotations.length; ++line) {
                  var anns = annotations[line];
                  if (!anns) continue;
            
                  var maxSeverity = null;
                  var tipLabel = state.hasGutter && document.createDocumentFragment();
            
                  for (var i = 0; i < anns.length; ++i) {
                    var ann = anns[i];
                    var severity = ann.severity;
                    if (!severity) severity = "error";
                    maxSeverity = getMaxSeverity(maxSeverity, severity);
            
                    if (options.formatAnnotation) ann = options.formatAnnotation(ann);
                    if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
            
                    if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
                      className: "CodeMirror-lint-mark-" + severity,
                      __annotation: ann
                    }));
                  }
            
                  if (state.hasGutter)
                    cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
                                                                   state.options.tooltips));
                }
                if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
              }
            
              function onChange(cm) {
                var state = cm.state.lint;
                clearTimeout(state.timeout);
                state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
              }
            
              function popupSpanTooltip(ann, e) {
                var target = e.target || e.srcElement;
                showTooltipFor(e, annotationTooltip(ann), target);
              }
            
              function onMouseOver(cm, e) {
                var target = e.target || e.srcElement;
                if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
                var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
                var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
                for (var i = 0; i < spans.length; ++i) {
                  var ann = spans[i].__annotation;
                  if (ann) return popupSpanTooltip(ann, e);
                }
              }
            
              CodeMirror.defineOption("lint", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  clearMarks(cm);
                  cm.off("change", onChange);
                  CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
                  delete cm.state.lint;
                }
            
                if (val) {
                  var gutters = cm.getOption("gutters"), hasLintGutter = false;
                  for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
                  var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
                  cm.on("change", onChange);
                  if (state.options.tooltips != false)
                    CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
            
                  startLinting(cm);
                }
              });
            });
            
          • yaml-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            // Depends on js-yaml.js from https://github.com/nodeca/js-yaml
            
            // declare global: jsyaml
            
            CodeMirror.registerHelper("lint", "yaml", function(text) {
              var found = [];
              try { jsyaml.load(text); }
              catch(e) {
                  var loc = e.mark;
                  found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message });
              }
              return found;
            });
            
            });
            
        • merge
          • merge.css
            .CodeMirror-merge {
              position: relative;
              border: 1px solid #ddd;
              white-space: pre;
            }
            
            .CodeMirror-merge, .CodeMirror-merge .CodeMirror {
              height: 350px;
            }
            
            .CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
            .CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
            .CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
            .CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
            
            .CodeMirror-merge-pane {
              display: inline-block;
              white-space: normal;
              vertical-align: top;
            }
            .CodeMirror-merge-pane-rightmost {
              position: absolute;
              right: 0px;
              z-index: 1;
            }
            
            .CodeMirror-merge-gap {
              z-index: 2;
              display: inline-block;
              height: 100%;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              overflow: hidden;
              border-left: 1px solid #ddd;
              border-right: 1px solid #ddd;
              position: relative;
              background: #f8f8f8;
            }
            
            .CodeMirror-merge-scrolllock-wrap {
              position: absolute;
              bottom: 0; left: 50%;
            }
            .CodeMirror-merge-scrolllock {
              position: relative;
              left: -50%;
              cursor: pointer;
              color: #555;
              line-height: 1;
            }
            
            .CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
              position: absolute;
              left: 0; top: 0;
              right: 0; bottom: 0;
              line-height: 1;
            }
            
            .CodeMirror-merge-copy {
              position: absolute;
              cursor: pointer;
              color: #44c;
            }
            
            .CodeMirror-merge-copy-reverse {
              position: absolute;
              cursor: pointer;
              color: #44c;
            }
            
            .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
            .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
            
            .CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
              background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
              background-position: bottom left;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
              background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
              background-position: bottom left;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-merge-r-chunk { background: #ffffe0; }
            .CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
            .CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
            .CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
            
            .CodeMirror-merge-l-chunk { background: #eef; }
            .CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
            .CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
            .CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
            
            .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
            .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
            .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
            
            .CodeMirror-merge-collapsed-widget:before {
              content: "(...)";
            }
            .CodeMirror-merge-collapsed-widget {
              cursor: pointer;
              color: #88b;
              background: #eef;
              border: 1px solid #ddf;
              font-size: 90%;
              padding: 0 3px;
              border-radius: 4px;
            }
            .CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
            
          • merge.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("diff_match_patch"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "diff_match_patch"], mod);
              else // Plain browser env
                mod(CodeMirror, diff_match_patch);
            })(function(CodeMirror, diff_match_patch) {
              "use strict";
              var Pos = CodeMirror.Pos;
              var svgNS = "http://www.w3.org/2000/svg";
            
              function DiffView(mv, type) {
                this.mv = mv;
                this.type = type;
                this.classes = type == "left"
                  ? {chunk: "CodeMirror-merge-l-chunk",
                     start: "CodeMirror-merge-l-chunk-start",
                     end: "CodeMirror-merge-l-chunk-end",
                     insert: "CodeMirror-merge-l-inserted",
                     del: "CodeMirror-merge-l-deleted",
                     connect: "CodeMirror-merge-l-connect"}
                  : {chunk: "CodeMirror-merge-r-chunk",
                     start: "CodeMirror-merge-r-chunk-start",
                     end: "CodeMirror-merge-r-chunk-end",
                     insert: "CodeMirror-merge-r-inserted",
                     del: "CodeMirror-merge-r-deleted",
                     connect: "CodeMirror-merge-r-connect"};
              }
            
              DiffView.prototype = {
                constructor: DiffView,
                init: function(pane, orig, options) {
                  this.edit = this.mv.edit;
                  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
            
                  this.diff = getDiff(asString(orig), asString(options.value));
                  this.chunks = getChunks(this.diff);
                  this.diffOutOfDate = this.dealigned = false;
            
                  this.showDifferences = options.showDifferences !== false;
                  this.forceUpdate = registerUpdate(this);
                  setScrollLock(this, true, false);
                  registerScroll(this);
                },
                setShowDifferences: function(val) {
                  val = val !== false;
                  if (val != this.showDifferences) {
                    this.showDifferences = val;
                    this.forceUpdate("full");
                  }
                }
              };
            
              function ensureDiff(dv) {
                if (dv.diffOutOfDate) {
                  dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
                  dv.chunks = getChunks(dv.diff);
                  dv.diffOutOfDate = false;
                  CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
                }
              }
            
              var updating = false;
              function registerUpdate(dv) {
                var edit = {from: 0, to: 0, marked: []};
                var orig = {from: 0, to: 0, marked: []};
                var debounceChange, updatingFast = false;
                function update(mode) {
                  updating = true;
                  updatingFast = false;
                  if (mode == "full") {
                    if (dv.svg) clear(dv.svg);
                    if (dv.copyButtons) clear(dv.copyButtons);
                    clearMarks(dv.edit, edit.marked, dv.classes);
                    clearMarks(dv.orig, orig.marked, dv.classes);
                    edit.from = edit.to = orig.from = orig.to = 0;
                  }
                  ensureDiff(dv);
                  if (dv.showDifferences) {
                    updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
                    updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
                  }
                  makeConnections(dv);
            
                  if (dv.mv.options.connect == "align")
                    alignChunks(dv);
                  updating = false;
                }
                function setDealign(fast) {
                  if (updating) return;
                  dv.dealigned = true;
                  set(fast);
                }
                function set(fast) {
                  if (updating || updatingFast) return;
                  clearTimeout(debounceChange);
                  if (fast === true) updatingFast = true;
                  debounceChange = setTimeout(update, fast === true ? 20 : 250);
                }
                function change(_cm, change) {
                  if (!dv.diffOutOfDate) {
                    dv.diffOutOfDate = true;
                    edit.from = edit.to = orig.from = orig.to = 0;
                  }
                  // Update faster when a line was added/removed
                  setDealign(change.text.length - 1 != change.to.line - change.from.line);
                }
                dv.edit.on("change", change);
                dv.orig.on("change", change);
                dv.edit.on("markerAdded", setDealign);
                dv.edit.on("markerCleared", setDealign);
                dv.orig.on("markerAdded", setDealign);
                dv.orig.on("markerCleared", setDealign);
                dv.edit.on("viewportChange", function() { set(false); });
                dv.orig.on("viewportChange", function() { set(false); });
                update();
                return update;
              }
            
              function registerScroll(dv) {
                dv.edit.on("scroll", function() {
                  syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
                });
                dv.orig.on("scroll", function() {
                  syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
                });
              }
            
              function syncScroll(dv, type) {
                // Change handler will do a refresh after a timeout when diff is out of date
                if (dv.diffOutOfDate) return false;
                if (!dv.lockScroll) return true;
                var editor, other, now = +new Date;
                if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
                else { editor = dv.orig; other = dv.edit; }
                // Don't take action if the position of this editor was recently set
                // (to prevent feedback loops)
                if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
            
                var sInfo = editor.getScrollInfo();
                if (dv.mv.options.connect == "align") {
                  targetPos = sInfo.top;
                } else {
                  var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
                  var mid = editor.lineAtHeight(midY, "local");
                  var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
                  var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
                  var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
                  var ratio = (midY - off.top) / (off.bot - off.top);
                  var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
            
                  var botDist, mix;
                  // Some careful tweaking to make sure no space is left out of view
                  // when scrolling to top or bottom.
                  if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
                    targetPos = targetPos * mix + sInfo.top * (1 - mix);
                  } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
                    var otherInfo = other.getScrollInfo();
                    var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
                    if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
                      targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
                  }
                }
            
                other.scrollTo(sInfo.left, targetPos);
                other.state.scrollSetAt = now;
                other.state.scrollSetBy = dv;
                return true;
              }
            
              function getOffsets(editor, around) {
                var bot = around.after;
                if (bot == null) bot = editor.lastLine() + 1;
                return {top: editor.heightAtLine(around.before || 0, "local"),
                        bot: editor.heightAtLine(bot, "local")};
              }
            
              function setScrollLock(dv, val, action) {
                dv.lockScroll = val;
                if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
                dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da";
              }
            
              // Updating the marks for editor content
            
              function clearMarks(editor, arr, classes) {
                for (var i = 0; i < arr.length; ++i) {
                  var mark = arr[i];
                  if (mark instanceof CodeMirror.TextMarker) {
                    mark.clear();
                  } else if (mark.parent) {
                    editor.removeLineClass(mark, "background", classes.chunk);
                    editor.removeLineClass(mark, "background", classes.start);
                    editor.removeLineClass(mark, "background", classes.end);
                  }
                }
                arr.length = 0;
              }
            
              // FIXME maybe add a margin around viewport to prevent too many updates
              function updateMarks(editor, diff, state, type, classes) {
                var vp = editor.getViewport();
                editor.operation(function() {
                  if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
                    clearMarks(editor, state.marked, classes);
                    markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
                    state.from = vp.from; state.to = vp.to;
                  } else {
                    if (vp.from < state.from) {
                      markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
                      state.from = vp.from;
                    }
                    if (vp.to > state.to) {
                      markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
                      state.to = vp.to;
                    }
                  }
                });
              }
            
              function markChanges(editor, diff, type, marks, from, to, classes) {
                var pos = Pos(0, 0);
                var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
                var cls = type == DIFF_DELETE ? classes.del : classes.insert;
                function markChunk(start, end) {
                  var bfrom = Math.max(from, start), bto = Math.min(to, end);
                  for (var i = bfrom; i < bto; ++i) {
                    var line = editor.addLineClass(i, "background", classes.chunk);
                    if (i == start) editor.addLineClass(line, "background", classes.start);
                    if (i == end - 1) editor.addLineClass(line, "background", classes.end);
                    marks.push(line);
                  }
                  // When the chunk is empty, make sure a horizontal line shows up
                  if (start == end && bfrom == end && bto == end) {
                    if (bfrom)
                      marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
                    else
                      marks.push(editor.addLineClass(bfrom, "background", classes.start));
                  }
                }
            
                var chunkStart = 0;
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i], tp = part[0], str = part[1];
                  if (tp == DIFF_EQUAL) {
                    var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
                    moveOver(pos, str);
                    var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
                    if (cleanTo > cleanFrom) {
                      if (i) markChunk(chunkStart, cleanFrom);
                      chunkStart = cleanTo;
                    }
                  } else {
                    if (tp == type) {
                      var end = moveOver(pos, str, true);
                      var a = posMax(top, pos), b = posMin(bot, end);
                      if (!posEq(a, b))
                        marks.push(editor.markText(a, b, {className: cls}));
                      pos = end;
                    }
                  }
                }
                if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
              }
            
              // Updating the gap between editor and original
            
              function makeConnections(dv) {
                if (!dv.showDifferences) return;
            
                if (dv.svg) {
                  clear(dv.svg);
                  var w = dv.gap.offsetWidth;
                  attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
                }
                if (dv.copyButtons) clear(dv.copyButtons);
            
                var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
                var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
                for (var i = 0; i < dv.chunks.length; i++) {
                  var ch = dv.chunks[i];
                  if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
                      ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
                    drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
                }
              }
            
              function getMatchingOrigLine(editLine, chunks) {
                var editStart = 0, origStart = 0;
                for (var i = 0; i < chunks.length; i++) {
                  var chunk = chunks[i];
                  if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
                  if (chunk.editFrom > editLine) break;
                  editStart = chunk.editTo;
                  origStart = chunk.origTo;
                }
                return origStart + (editLine - editStart);
              }
            
              function findAlignedLines(dv, other) {
                var linesToAlign = [];
                for (var i = 0; i < dv.chunks.length; i++) {
                  var chunk = dv.chunks[i];
                  linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
                }
                if (other) {
                  for (var i = 0; i < other.chunks.length; i++) {
                    var chunk = other.chunks[i];
                    for (var j = 0; j < linesToAlign.length; j++) {
                      var align = linesToAlign[j];
                      if (align[1] == chunk.editTo) {
                        j = -1;
                        break;
                      } else if (align[1] > chunk.editTo) {
                        break;
                      }
                    }
                    if (j > -1)
                      linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
                  }
                }
                return linesToAlign;
              }
            
              function alignChunks(dv, force) {
                if (!dv.dealigned && !force) return;
                if (!dv.orig.curOp) return dv.orig.operation(function() {
                  alignChunks(dv, force);
                });
            
                dv.dealigned = false;
                var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
                if (other) {
                  ensureDiff(other);
                  other.dealigned = false;
                }
                var linesToAlign = findAlignedLines(dv, other);
            
                // Clear old aligners
                var aligners = dv.mv.aligners;
                for (var i = 0; i < aligners.length; i++)
                  aligners[i].clear();
                aligners.length = 0;
            
                var cm = [dv.orig, dv.edit], scroll = [];
                if (other) cm.push(other.orig);
                for (var i = 0; i < cm.length; i++)
                  scroll.push(cm[i].getScrollInfo().top);
            
                for (var ln = 0; ln < linesToAlign.length; ln++)
                  alignLines(cm, linesToAlign[ln], aligners);
            
                for (var i = 0; i < cm.length; i++)
                  cm[i].scrollTo(null, scroll[i]);
              }
            
              function alignLines(cm, lines, aligners) {
                var maxOffset = 0, offset = [];
                for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
                  var off = cm[i].heightAtLine(lines[i], "local");
                  offset[i] = off;
                  maxOffset = Math.max(maxOffset, off);
                }
                for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
                  var diff = maxOffset - offset[i];
                  if (diff > 1)
                    aligners.push(padAbove(cm[i], lines[i], diff));
                }
              }
            
              function padAbove(cm, line, size) {
                var above = true;
                if (line > cm.lastLine()) {
                  line--;
                  above = false;
                }
                var elt = document.createElement("div");
                elt.className = "CodeMirror-merge-spacer";
                elt.style.height = size + "px"; elt.style.minWidth = "1px";
                return cm.addLineWidget(line, elt, {height: size, above: above});
              }
            
              function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
                var flip = dv.type == "left";
                var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
                if (dv.svg) {
                  var topLpx = top;
                  var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
                  if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
                  var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
                  var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
                  if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
                  var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
                  var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
                  attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
                        "d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
                        "class", dv.classes.connect);
                }
                if (dv.copyButtons) {
                  var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
                                                            "CodeMirror-merge-copy"));
                  var editOriginals = dv.mv.options.allowEditingOriginals;
                  copy.title = editOriginals ? "Push to left" : "Revert chunk";
                  copy.chunk = chunk;
                  copy.style.top = top + "px";
            
                  if (editOriginals) {
                    var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
                    var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
                                                                     "CodeMirror-merge-copy-reverse"));
                    copyReverse.title = "Push to right";
                    copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
                                         origFrom: chunk.editFrom, origTo: chunk.editTo};
                    copyReverse.style.top = topReverse + "px";
                    dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
                  }
                }
              }
            
              function copyChunk(dv, to, from, chunk) {
                if (dv.diffOutOfDate) return;
                to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
                                     Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
              }
            
              // Merge view, containing 0, 1, or 2 diff views.
            
              var MergeView = CodeMirror.MergeView = function(node, options) {
                if (!(this instanceof MergeView)) return new MergeView(node, options);
            
                this.options = options;
                var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
            
                var hasLeft = origLeft != null, hasRight = origRight != null;
                var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
                var wrap = [], left = this.left = null, right = this.right = null;
                var self = this;
            
                if (hasLeft) {
                  left = this.left = new DiffView(this, "left");
                  var leftPane = elt("div", null, "CodeMirror-merge-pane");
                  wrap.push(leftPane);
                  wrap.push(buildGap(left));
                }
            
                var editPane = elt("div", null, "CodeMirror-merge-pane");
                wrap.push(editPane);
            
                if (hasRight) {
                  right = this.right = new DiffView(this, "right");
                  wrap.push(buildGap(right));
                  var rightPane = elt("div", null, "CodeMirror-merge-pane");
                  wrap.push(rightPane);
                }
            
                (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
            
                wrap.push(elt("div", null, null, "height: 0; clear: both;"));
            
                var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
                this.edit = CodeMirror(editPane, copyObj(options));
            
                if (left) left.init(leftPane, origLeft, options);
                if (right) right.init(rightPane, origRight, options);
            
                if (options.collapseIdentical) {
                  updating = true;
                  this.editor().operation(function() {
                    collapseIdenticalStretches(self, options.collapseIdentical);
                  });
                  updating = false;
                }
                if (options.connect == "align") {
                  this.aligners = [];
                  alignChunks(this.left || this.right, true);
                }
            
                var onResize = function() {
                  if (left) makeConnections(left);
                  if (right) makeConnections(right);
                };
                CodeMirror.on(window, "resize", onResize);
                var resizeInterval = setInterval(function() {
                  for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
                  if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
                }, 5000);
              };
            
              function buildGap(dv) {
                var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
                lock.title = "Toggle locked scrolling";
                var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
                CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
                var gapElts = [lockWrap];
                if (dv.mv.options.revertButtons !== false) {
                  dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
                  CodeMirror.on(dv.copyButtons, "click", function(e) {
                    var node = e.target || e.srcElement;
                    if (!node.chunk) return;
                    if (node.className == "CodeMirror-merge-copy-reverse") {
                      copyChunk(dv, dv.orig, dv.edit, node.chunk);
                      return;
                    }
                    copyChunk(dv, dv.edit, dv.orig, node.chunk);
                  });
                  gapElts.unshift(dv.copyButtons);
                }
                if (dv.mv.options.connect != "align") {
                  var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
                  if (svg && !svg.createSVGRect) svg = null;
                  dv.svg = svg;
                  if (svg) gapElts.push(svg);
                }
            
                return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
              }
            
              MergeView.prototype = {
                constuctor: MergeView,
                editor: function() { return this.edit; },
                rightOriginal: function() { return this.right && this.right.orig; },
                leftOriginal: function() { return this.left && this.left.orig; },
                setShowDifferences: function(val) {
                  if (this.right) this.right.setShowDifferences(val);
                  if (this.left) this.left.setShowDifferences(val);
                },
                rightChunks: function() {
                  if (this.right) { ensureDiff(this.right); return this.right.chunks; }
                },
                leftChunks: function() {
                  if (this.left) { ensureDiff(this.left); return this.left.chunks; }
                }
              };
            
              function asString(obj) {
                if (typeof obj == "string") return obj;
                else return obj.getValue();
              }
            
              // Operations on diffs
            
              var dmp = new diff_match_patch();
              function getDiff(a, b) {
                var diff = dmp.diff_main(a, b);
                dmp.diff_cleanupSemantic(diff);
                // The library sometimes leaves in empty parts, which confuse the algorithm
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i];
                  if (!part[1]) {
                    diff.splice(i--, 1);
                  } else if (i && diff[i - 1][0] == part[0]) {
                    diff.splice(i--, 1);
                    diff[i][1] += part[1];
                  }
                }
                return diff;
              }
            
              function getChunks(diff) {
                var chunks = [];
                var startEdit = 0, startOrig = 0;
                var edit = Pos(0, 0), orig = Pos(0, 0);
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i], tp = part[0];
                  if (tp == DIFF_EQUAL) {
                    var startOff = startOfLineClean(diff, i) ? 0 : 1;
                    var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
                    moveOver(edit, part[1], null, orig);
                    var endOff = endOfLineClean(diff, i) ? 1 : 0;
                    var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
                    if (cleanToEdit > cleanFromEdit) {
                      if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
                                          editFrom: startEdit, editTo: cleanFromEdit});
                      startEdit = cleanToEdit; startOrig = cleanToOrig;
                    }
                  } else {
                    moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
                  }
                }
                if (startEdit <= edit.line || startOrig <= orig.line)
                  chunks.push({origFrom: startOrig, origTo: orig.line + 1,
                               editFrom: startEdit, editTo: edit.line + 1});
                return chunks;
              }
            
              function endOfLineClean(diff, i) {
                if (i == diff.length - 1) return true;
                var next = diff[i + 1][1];
                if (next.length == 1 || next.charCodeAt(0) != 10) return false;
                if (i == diff.length - 2) return true;
                next = diff[i + 2][1];
                return next.length > 1 && next.charCodeAt(0) == 10;
              }
            
              function startOfLineClean(diff, i) {
                if (i == 0) return true;
                var last = diff[i - 1][1];
                if (last.charCodeAt(last.length - 1) != 10) return false;
                if (i == 1) return true;
                last = diff[i - 2][1];
                return last.charCodeAt(last.length - 1) == 10;
              }
            
              function chunkBoundariesAround(chunks, n, nInEdit) {
                var beforeE, afterE, beforeO, afterO;
                for (var i = 0; i < chunks.length; i++) {
                  var chunk = chunks[i];
                  var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
                  var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
                  if (afterE == null) {
                    if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
                    else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
                  }
                  if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
                  else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
                }
                return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
              }
            
              function collapseSingle(cm, from, to) {
                cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
                var widget = document.createElement("span");
                widget.className = "CodeMirror-merge-collapsed-widget";
                widget.title = "Identical text collapsed. Click to expand.";
                var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
                  inclusiveLeft: true,
                  inclusiveRight: true,
                  replacedWith: widget,
                  clearOnEnter: true
                });
                function clear() {
                  mark.clear();
                  cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
                }
                widget.addEventListener("click", clear);
                return {mark: mark, clear: clear};
              }
            
              function collapseStretch(size, editors) {
                var marks = [];
                function clear() {
                  for (var i = 0; i < marks.length; i++) marks[i].clear();
                }
                for (var i = 0; i < editors.length; i++) {
                  var editor = editors[i];
                  var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
                  marks.push(mark);
                  mark.mark.on("clear", clear);
                }
                return marks[0].mark;
              }
            
              function unclearNearChunks(dv, margin, off, clear) {
                for (var i = 0; i < dv.chunks.length; i++) {
                  var chunk = dv.chunks[i];
                  for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
                    var pos = l + off;
                    if (pos >= 0 && pos < clear.length) clear[pos] = false;
                  }
                }
              }
            
              function collapseIdenticalStretches(mv, margin) {
                if (typeof margin != "number") margin = 2;
                var clear = [], edit = mv.editor(), off = edit.firstLine();
                for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
                if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
                if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
            
                for (var i = 0; i < clear.length; i++) {
                  if (clear[i]) {
                    var line = i + off;
                    for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
                    if (size > margin) {
                      var editors = [{line: line, cm: edit}];
                      if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
                      if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
                      var mark = collapseStretch(size, editors);
                      if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
                    }
                  }
                }
              }
            
              // General utilities
            
              function elt(tag, content, className, style) {
                var e = document.createElement(tag);
                if (className) e.className = className;
                if (style) e.style.cssText = style;
                if (typeof content == "string") e.appendChild(document.createTextNode(content));
                else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
                return e;
              }
            
              function clear(node) {
                for (var count = node.childNodes.length; count > 0; --count)
                  node.removeChild(node.firstChild);
              }
            
              function attrs(elt) {
                for (var i = 1; i < arguments.length; i += 2)
                  elt.setAttribute(arguments[i], arguments[i+1]);
              }
            
              function copyObj(obj, target) {
                if (!target) target = {};
                for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
                return target;
              }
            
              function moveOver(pos, str, copy, other) {
                var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
                for (;;) {
                  var nl = str.indexOf("\n", at);
                  if (nl == -1) break;
                  ++out.line;
                  if (other) ++other.line;
                  at = nl + 1;
                }
                out.ch = (at ? 0 : out.ch) + (str.length - at);
                if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
                return out;
              }
            
              function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
              function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
              function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
            });
            
        • mode
          • loadmode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), "cjs");
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
              else // Plain browser env
                mod(CodeMirror, "plain");
            })(function(CodeMirror, env) {
              if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
            
              var loading = {};
              function splitCallback(cont, n) {
                var countDown = n;
                return function() { if (--countDown == 0) cont(); };
              }
              function ensureDeps(mode, cont) {
                var deps = CodeMirror.modes[mode].dependencies;
                if (!deps) return cont();
                var missing = [];
                for (var i = 0; i < deps.length; ++i) {
                  if (!CodeMirror.modes.hasOwnProperty(deps[i]))
                    missing.push(deps[i]);
                }
                if (!missing.length) return cont();
                var split = splitCallback(cont, missing.length);
                for (var i = 0; i < missing.length; ++i)
                  CodeMirror.requireMode(missing[i], split);
              }
            
              CodeMirror.requireMode = function(mode, cont) {
                if (typeof mode != "string") mode = mode.name;
                if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
                if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
            
                var file = CodeMirror.modeURL.replace(/%N/g, mode);
                if (env == "plain") {
                  var script = document.createElement("script");
                  script.src = file;
                  var others = document.getElementsByTagName("script")[0];
                  var list = loading[mode] = [cont];
                  CodeMirror.on(script, "load", function() {
                    ensureDeps(mode, function() {
                      for (var i = 0; i < list.length; ++i) list[i]();
                    });
                  });
                  others.parentNode.insertBefore(script, others);
                } else if (env == "cjs") {
                  require(file);
                  cont();
                } else if (env == "amd") {
                  requirejs([file], cont);
                }
              };
            
              CodeMirror.autoLoadMode = function(instance, mode) {
                if (!CodeMirror.modes.hasOwnProperty(mode))
                  CodeMirror.requireMode(mode, function() {
                    instance.setOption("mode", instance.getOption("mode"));
                  });
              };
            });
            
          • multiplex.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.multiplexingMode = function(outer /*, others */) {
              // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
              var others = Array.prototype.slice.call(arguments, 1);
              var n_others = others.length;
            
              function indexOf(string, pattern, from) {
                if (typeof pattern == "string") return string.indexOf(pattern, from);
                var m = pattern.exec(from ? string.slice(from) : string);
                return m ? m.index + from : -1;
              }
            
              return {
                startState: function() {
                  return {
                    outer: CodeMirror.startState(outer),
                    innerActive: null,
                    inner: null
                  };
                },
            
                copyState: function(state) {
                  return {
                    outer: CodeMirror.copyState(outer, state.outer),
                    innerActive: state.innerActive,
                    inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
                  };
                },
            
                token: function(stream, state) {
                  if (!state.innerActive) {
                    var cutOff = Infinity, oldContent = stream.string;
                    for (var i = 0; i < n_others; ++i) {
                      var other = others[i];
                      var found = indexOf(oldContent, other.open, stream.pos);
                      if (found == stream.pos) {
                        stream.match(other.open);
                        state.innerActive = other;
                        state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
                        return other.delimStyle;
                      } else if (found != -1 && found < cutOff) {
                        cutOff = found;
                      }
                    }
                    if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
                    var outerToken = outer.token(stream, state.outer);
                    if (cutOff != Infinity) stream.string = oldContent;
                    return outerToken;
                  } else {
                    var curInner = state.innerActive, oldContent = stream.string;
                    if (!curInner.close && stream.sol()) {
                      state.innerActive = state.inner = null;
                      return this.token(stream, state);
                    }
                    var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
                    if (found == stream.pos) {
                      stream.match(curInner.close);
                      state.innerActive = state.inner = null;
                      return curInner.delimStyle;
                    }
                    if (found > -1) stream.string = oldContent.slice(0, found);
                    var innerToken = curInner.mode.token(stream, state.inner);
                    if (found > -1) stream.string = oldContent;
            
                    if (curInner.innerStyle) {
                      if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
                      else innerToken = curInner.innerStyle;
                    }
            
                    return innerToken;
                  }
                },
            
                indent: function(state, textAfter) {
                  var mode = state.innerActive ? state.innerActive.mode : outer;
                  if (!mode.indent) return CodeMirror.Pass;
                  return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
                },
            
                blankLine: function(state) {
                  var mode = state.innerActive ? state.innerActive.mode : outer;
                  if (mode.blankLine) {
                    mode.blankLine(state.innerActive ? state.inner : state.outer);
                  }
                  if (!state.innerActive) {
                    for (var i = 0; i < n_others; ++i) {
                      var other = others[i];
                      if (other.open === "\n") {
                        state.innerActive = other;
                        state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
                      }
                    }
                  } else if (state.innerActive.close === "\n") {
                    state.innerActive = state.inner = null;
                  }
                },
            
                electricChars: outer.electricChars,
            
                innerMode: function(state) {
                  return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
                }
              };
            };
            
            });
            
          • multiplex_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              CodeMirror.defineMode("markdown_with_stex", function(){
                var inner = CodeMirror.getMode({}, "stex");
                var outer = CodeMirror.getMode({}, "markdown");
            
                var innerOptions = {
                  open: '$',
                  close: '$',
                  mode: inner,
                  delimStyle: 'delim',
                  innerStyle: 'inner'
                };
            
                return CodeMirror.multiplexingMode(outer, innerOptions);
              });
            
              var mode = CodeMirror.getMode({}, "markdown_with_stex");
            
              function MT(name) {
                test.mode(
                  name,
                  mode,
                  Array.prototype.slice.call(arguments, 1),
                  'multiplexing');
              }
            
              MT(
                "stexInsideMarkdown",
                "[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
            })();
            
          • overlay.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Utility function that allows modes to be combined. The mode given
            // as the base argument takes care of most of the normal mode
            // functionality, but a second (typically simple) mode is used, which
            // can override the style of text. Both modes get to parse all of the
            // text, but when both assign a non-null style to a piece of code, the
            // overlay wins, unless the combine argument was true and not overridden,
            // or state.overlay.combineTokens was true, in which case the styles are
            // combined.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.overlayMode = function(base, overlay, combine) {
              return {
                startState: function() {
                  return {
                    base: CodeMirror.startState(base),
                    overlay: CodeMirror.startState(overlay),
                    basePos: 0, baseCur: null,
                    overlayPos: 0, overlayCur: null,
                    streamSeen: null
                  };
                },
                copyState: function(state) {
                  return {
                    base: CodeMirror.copyState(base, state.base),
                    overlay: CodeMirror.copyState(overlay, state.overlay),
                    basePos: state.basePos, baseCur: null,
                    overlayPos: state.overlayPos, overlayCur: null
                  };
                },
            
                token: function(stream, state) {
                  if (stream != state.streamSeen ||
                      Math.min(state.basePos, state.overlayPos) < stream.start) {
                    state.streamSeen = stream;
                    state.basePos = state.overlayPos = stream.start;
                  }
            
                  if (stream.start == state.basePos) {
                    state.baseCur = base.token(stream, state.base);
                    state.basePos = stream.pos;
                  }
                  if (stream.start == state.overlayPos) {
                    stream.pos = stream.start;
                    state.overlayCur = overlay.token(stream, state.overlay);
                    state.overlayPos = stream.pos;
                  }
                  stream.pos = Math.min(state.basePos, state.overlayPos);
            
                  // state.overlay.combineTokens always takes precedence over combine,
                  // unless set to null
                  if (state.overlayCur == null) return state.baseCur;
                  else if (state.baseCur != null &&
                           state.overlay.combineTokens ||
                           combine && state.overlay.combineTokens == null)
                    return state.baseCur + " " + state.overlayCur;
                  else return state.overlayCur;
                },
            
                indent: base.indent && function(state, textAfter) {
                  return base.indent(state.base, textAfter);
                },
                electricChars: base.electricChars,
            
                innerMode: function(state) { return {state: state.base, mode: base}; },
            
                blankLine: function(state) {
                  if (base.blankLine) base.blankLine(state.base);
                  if (overlay.blankLine) overlay.blankLine(state.overlay);
                }
              };
            };
            
            });
            
          • simple.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineSimpleMode = function(name, states) {
                CodeMirror.defineMode(name, function(config) {
                  return CodeMirror.simpleMode(config, states);
                });
              };
            
              CodeMirror.simpleMode = function(config, states) {
                ensureState(states, "start");
                var states_ = {}, meta = states.meta || {}, hasIndentation = false;
                for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
                  var list = states_[state] = [], orig = states[state];
                  for (var i = 0; i < orig.length; i++) {
                    var data = orig[i];
                    list.push(new Rule(data, states));
                    if (data.indent || data.dedent) hasIndentation = true;
                  }
                }
                var mode = {
                  startState: function() {
                    return {state: "start", pending: null,
                            local: null, localState: null,
                            indent: hasIndentation ? [] : null};
                  },
                  copyState: function(state) {
                    var s = {state: state.state, pending: state.pending,
                             local: state.local, localState: null,
                             indent: state.indent && state.indent.slice(0)};
                    if (state.localState)
                      s.localState = CodeMirror.copyState(state.local.mode, state.localState);
                    if (state.stack)
                      s.stack = state.stack.slice(0);
                    for (var pers = state.persistentStates; pers; pers = pers.next)
                      s.persistentStates = {mode: pers.mode,
                                            spec: pers.spec,
                                            state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
                                            next: s.persistentStates};
                    return s;
                  },
                  token: tokenFunction(states_, config),
                  innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
                  indent: indentFunction(states_, meta)
                };
                if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
                  mode[prop] = meta[prop];
                return mode;
              };
            
              function ensureState(states, name) {
                if (!states.hasOwnProperty(name))
                  throw new Error("Undefined state " + name + "in simple mode");
              }
            
              function toRegex(val, caret) {
                if (!val) return /(?:)/;
                var flags = "";
                if (val instanceof RegExp) {
                  if (val.ignoreCase) flags = "i";
                  val = val.source;
                } else {
                  val = String(val);
                }
                return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
              }
            
              function asToken(val) {
                if (!val) return null;
                if (typeof val == "string") return val.replace(/\./g, " ");
                var result = [];
                for (var i = 0; i < val.length; i++)
                  result.push(val[i] && val[i].replace(/\./g, " "));
                return result;
              }
            
              function Rule(data, states) {
                if (data.next || data.push) ensureState(states, data.next || data.push);
                this.regex = toRegex(data.regex);
                this.token = asToken(data.token);
                this.data = data;
              }
            
              function tokenFunction(states, config) {
                return function(stream, state) {
                  if (state.pending) {
                    var pend = state.pending.shift();
                    if (state.pending.length == 0) state.pending = null;
                    stream.pos += pend.text.length;
                    return pend.token;
                  }
            
                  if (state.local) {
                    if (state.local.end && stream.match(state.local.end)) {
                      var tok = state.local.endToken || null;
                      state.local = state.localState = null;
                      return tok;
                    } else {
                      var tok = state.local.mode.token(stream, state.localState), m;
                      if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
                        stream.pos = stream.start + m.index;
                      return tok;
                    }
                  }
            
                  var curState = states[state.state];
                  for (var i = 0; i < curState.length; i++) {
                    var rule = curState[i];
                    var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
                    if (matches) {
                      if (rule.data.next) {
                        state.state = rule.data.next;
                      } else if (rule.data.push) {
                        (state.stack || (state.stack = [])).push(state.state);
                        state.state = rule.data.push;
                      } else if (rule.data.pop && state.stack && state.stack.length) {
                        state.state = state.stack.pop();
                      }
            
                      if (rule.data.mode)
                        enterLocalMode(config, state, rule.data.mode, rule.token);
                      if (rule.data.indent)
                        state.indent.push(stream.indentation() + config.indentUnit);
                      if (rule.data.dedent)
                        state.indent.pop();
                      if (matches.length > 2) {
                        state.pending = [];
                        for (var j = 2; j < matches.length; j++)
                          if (matches[j])
                            state.pending.push({text: matches[j], token: rule.token[j - 1]});
                        stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
                        return rule.token[0];
                      } else if (rule.token && rule.token.join) {
                        return rule.token[0];
                      } else {
                        return rule.token;
                      }
                    }
                  }
                  stream.next();
                  return null;
                };
              }
            
              function cmp(a, b) {
                if (a === b) return true;
                if (!a || typeof a != "object" || !b || typeof b != "object") return false;
                var props = 0;
                for (var prop in a) if (a.hasOwnProperty(prop)) {
                  if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
                  props++;
                }
                for (var prop in b) if (b.hasOwnProperty(prop)) props--;
                return props == 0;
              }
            
              function enterLocalMode(config, state, spec, token) {
                var pers;
                if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
                  if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
                var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
                var lState = pers ? pers.state : CodeMirror.startState(mode);
                if (spec.persistent && !pers)
                  state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
            
                state.localState = lState;
                state.local = {mode: mode,
                               end: spec.end && toRegex(spec.end),
                               endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
                               endToken: token && token.join ? token[token.length - 1] : token};
              }
            
              function indexOf(val, arr) {
                for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
              }
            
              function indentFunction(states, meta) {
                return function(state, textAfter, line) {
                  if (state.local && state.local.mode.indent)
                    return state.local.mode.indent(state.localState, textAfter, line);
                  if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
                    return CodeMirror.Pass;
            
                  var pos = state.indent.length - 1, rules = states[state.state];
                  scan: for (;;) {
                    for (var i = 0; i < rules.length; i++) {
                      var rule = rules[i];
                      if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
                        var m = rule.regex.exec(textAfter);
                        if (m && m[0]) {
                          pos--;
                          if (rule.next || rule.push) rules = states[rule.next || rule.push];
                          textAfter = textAfter.slice(m[0].length);
                          continue scan;
                        }
                      }
                    }
                    break;
                  }
                  return pos < 0 ? 0 : state.indent[pos];
                };
              }
            });
            
        • runmode
          • colorize.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./runmode"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./runmode"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;
            
              function textContent(node, out) {
                if (node.nodeType == 3) return out.push(node.nodeValue);
                for (var ch = node.firstChild; ch; ch = ch.nextSibling) {
                  textContent(ch, out);
                  if (isBlock.test(node.nodeType)) out.push("\n");
                }
              }
            
              CodeMirror.colorize = function(collection, defaultMode) {
                if (!collection) collection = document.body.getElementsByTagName("pre");
            
                for (var i = 0; i < collection.length; ++i) {
                  var node = collection[i];
                  var mode = node.getAttribute("data-lang") || defaultMode;
                  if (!mode) continue;
            
                  var text = [];
                  textContent(node, text);
                  node.innerHTML = "";
                  CodeMirror.runMode(text.join(""), mode, node);
            
                  node.className += " cm-s-default";
                }
              };
            });
            
          • runmode-standalone.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            window.CodeMirror = {};
            
            (function() {
            "use strict";
            
            function splitLines(string){ return string.split(/\r?\n|\r/); };
            
            function StringStream(string) {
              this.pos = this.start = 0;
              this.string = string;
              this.lineStart = 0;
            }
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == 0;},
              peek: function() {return this.string.charAt(this.pos) || null;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.start - this.lineStart;},
              indentation: function() {return 0;},
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
            CodeMirror.StringStream = StringStream;
            
            CodeMirror.startState = function (mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
            
            var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
            CodeMirror.defineMode = function (name, mode) {
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
            CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
            CodeMirror.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                spec = mimeModes[spec.name];
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
            CodeMirror.getMode = function (options, spec) {
              spec = CodeMirror.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) throw new Error("Unknown mode: " + spec);
              return mfactory(options, spec);
            };
            CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
            CodeMirror.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            CodeMirror.defineMIME("text/plain", "null");
            
            CodeMirror.runMode = function (string, modespec, callback, options) {
              var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
            
              if (callback.nodeType == 1) {
                var tabSize = (options && options.tabSize) || 4;
                var node = callback, col = 0;
                node.innerHTML = "";
                callback = function (text, style) {
                  if (text == "\n") {
                    node.appendChild(document.createElement("br"));
                    col = 0;
                    return;
                  }
                  var content = "";
                  // replace tabs
                  for (var pos = 0; ;) {
                    var idx = text.indexOf("\t", pos);
                    if (idx == -1) {
                      content += text.slice(pos);
                      col += text.length - pos;
                      break;
                    } else {
                      col += idx - pos;
                      content += text.slice(pos, idx);
                      var size = tabSize - col % tabSize;
                      col += size;
                      for (var i = 0; i < size; ++i) content += " ";
                      pos = idx + 1;
                    }
                  }
            
                  if (style) {
                    var sp = node.appendChild(document.createElement("span"));
                    sp.className = "cm-" + style.replace(/ +/g, " cm-");
                    sp.appendChild(document.createTextNode(content));
                  } else {
                    node.appendChild(document.createTextNode(content));
                  }
                };
              }
            
              var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new CodeMirror.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            })();
            
          • runmode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.runMode = function(string, modespec, callback, options) {
              var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
              var ie = /MSIE \d/.test(navigator.userAgent);
              var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
            
              if (callback.nodeType == 1) {
                var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
                var node = callback, col = 0;
                node.innerHTML = "";
                callback = function(text, style) {
                  if (text == "\n") {
                    // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
                    // Emitting a carriage return makes everything ok.
                    node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
                    col = 0;
                    return;
                  }
                  var content = "";
                  // replace tabs
                  for (var pos = 0;;) {
                    var idx = text.indexOf("\t", pos);
                    if (idx == -1) {
                      content += text.slice(pos);
                      col += text.length - pos;
                      break;
                    } else {
                      col += idx - pos;
                      content += text.slice(pos, idx);
                      var size = tabSize - col % tabSize;
                      col += size;
                      for (var i = 0; i < size; ++i) content += " ";
                      pos = idx + 1;
                    }
                  }
            
                  if (style) {
                    var sp = node.appendChild(document.createElement("span"));
                    sp.className = "cm-" + style.replace(/ +/g, " cm-");
                    sp.appendChild(document.createTextNode(content));
                  } else {
                    node.appendChild(document.createTextNode(content));
                  }
                };
              }
            
              var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new CodeMirror.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            
            });
            
          • runmode.node.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /* Just enough of CodeMirror to run runMode under node.js */
            
            // declare global: StringStream
            
            function splitLines(string){ return string.split(/\r?\n|\r/); };
            
            function StringStream(string) {
              this.pos = this.start = 0;
              this.string = string;
              this.lineStart = 0;
            }
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == 0;},
              peek: function() {return this.string.charAt(this.pos) || null;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.start - this.lineStart;},
              indentation: function() {return 0;},
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
            exports.StringStream = StringStream;
            
            exports.startState = function(mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
            
            var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
            exports.defineMode = function(name, mode) {
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
            exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
            
            exports.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            exports.defineMIME("text/plain", "null");
            
            exports.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                spec = mimeModes[spec.name];
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
            exports.getMode = function(options, spec) {
              spec = exports.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) throw new Error("Unknown mode: " + spec);
              return mfactory(options, spec);
            };
            exports.registerHelper = exports.registerGlobalHelper = Math.min;
            
            exports.runMode = function(string, modespec, callback, options) {
              var mode = exports.getMode({indentUnit: 2}, modespec);
              var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new exports.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            
            require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
            
        • scroll
          • annotatescrollbar.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineExtension("annotateScrollbar", function(options) {
                if (typeof options == "string") options = {className: options};
                return new Annotation(this, options);
              });
            
              CodeMirror.defineOption("scrollButtonHeight", 0);
            
              function Annotation(cm, options) {
                this.cm = cm;
                this.options = options;
                this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
                this.annotations = [];
                this.doRedraw = this.doUpdate = null;
                this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
                this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
                this.computeScale();
            
                function scheduleRedraw(delay) {
                  clearTimeout(self.doRedraw);
                  self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
                }
            
                var self = this;
                cm.on("refresh", this.resizeHandler = function() {
                  clearTimeout(self.doUpdate);
                  self.doUpdate = setTimeout(function() {
                    if (self.computeScale()) scheduleRedraw(20);
                  }, 100);
                });
                cm.on("markerAdded", this.resizeHandler);
                cm.on("markerCleared", this.resizeHandler);
                if (options.listenForChanges !== false)
                  cm.on("change", this.changeHandler = function() {
                    scheduleRedraw(250);
                  });
              }
            
              Annotation.prototype.computeScale = function() {
                var cm = this.cm;
                var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
                  cm.heightAtLine(cm.lastLine() + 1, "local");
                if (hScale != this.hScale) {
                  this.hScale = hScale;
                  return true;
                }
              };
            
              Annotation.prototype.update = function(annotations) {
                this.annotations = annotations;
                this.redraw();
              };
            
              Annotation.prototype.redraw = function(compute) {
                if (compute !== false) this.computeScale();
                var cm = this.cm, hScale = this.hScale;
            
                var frag = document.createDocumentFragment(), anns = this.annotations;
                if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
                  var ann = anns[i];
                  var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
                  var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
                  while (i < anns.length - 1) {
                    nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
                    if (nextTop > bottom + .9) break;
                    ann = anns[++i];
                    bottom = cm.charCoords(ann.to, "local").bottom * hScale;
                  }
                  if (bottom == top) continue;
                  var height = Math.max(bottom - top, 3);
            
                  var elt = frag.appendChild(document.createElement("div"));
                  elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
                    + (top + this.buttonHeight) + "px; height: " + height + "px";
                  elt.className = this.options.className;
                }
                this.div.textContent = "";
                this.div.appendChild(frag);
              };
            
              Annotation.prototype.clear = function() {
                this.cm.off("refresh", this.resizeHandler);
                this.cm.off("markerAdded", this.resizeHandler);
                this.cm.off("markerCleared", this.resizeHandler);
                if (this.changeHandler) this.cm.off("change", this.changeHandler);
                this.div.parentNode.removeChild(this.div);
              };
            });
            
          • scrollpastend.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.off("change", onChange);
                  cm.off("refresh", updateBottomMargin);
                  cm.display.lineSpace.parentNode.style.paddingBottom = "";
                  cm.state.scrollPastEndPadding = null;
                }
                if (val) {
                  cm.on("change", onChange);
                  cm.on("refresh", updateBottomMargin);
                  updateBottomMargin(cm);
                }
              });
            
              function onChange(cm, change) {
                if (CodeMirror.changeEnd(change).line == cm.lastLine())
                  updateBottomMargin(cm);
              }
            
              function updateBottomMargin(cm) {
                var padding = "";
                if (cm.lineCount() > 1) {
                  var totalH = cm.display.scroller.clientHeight - 30,
                      lastLineH = cm.getLineHandle(cm.lastLine()).height;
                  padding = (totalH - lastLineH) + "px";
                }
                if (cm.state.scrollPastEndPadding != padding) {
                  cm.state.scrollPastEndPadding = padding;
                  cm.display.lineSpace.parentNode.style.paddingBottom = padding;
                  cm.setSize();
                }
              }
            });
            
          • simplescrollbars.css
            .CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {
              position: absolute;
              background: #ccc;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              border: 1px solid #bbb;
              border-radius: 2px;
            }
            
            .CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {
              position: absolute;
              z-index: 6;
              background: #eee;
            }
            
            .CodeMirror-simplescroll-horizontal {
              bottom: 0; left: 0;
              height: 8px;
            }
            .CodeMirror-simplescroll-horizontal div {
              bottom: 0;
              height: 100%;
            }
            
            .CodeMirror-simplescroll-vertical {
              right: 0; top: 0;
              width: 8px;
            }
            .CodeMirror-simplescroll-vertical div {
              right: 0;
              width: 100%;
            }
            
            
            .CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {
              display: none;
            }
            
            .CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
              position: absolute;
              background: #bcd;
              border-radius: 3px;
            }
            
            .CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {
              position: absolute;
              z-index: 6;
            }
            
            .CodeMirror-overlayscroll-horizontal {
              bottom: 0; left: 0;
              height: 6px;
            }
            .CodeMirror-overlayscroll-horizontal div {
              bottom: 0;
              height: 100%;
            }
            
            .CodeMirror-overlayscroll-vertical {
              right: 0; top: 0;
              width: 6px;
            }
            .CodeMirror-overlayscroll-vertical div {
              right: 0;
              width: 100%;
            }
            
          • simplescrollbars.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function Bar(cls, orientation, scroll) {
                this.orientation = orientation;
                this.scroll = scroll;
                this.screen = this.total = this.size = 1;
                this.pos = 0;
            
                this.node = document.createElement("div");
                this.node.className = cls + "-" + orientation;
                this.inner = this.node.appendChild(document.createElement("div"));
            
                var self = this;
                CodeMirror.on(this.inner, "mousedown", function(e) {
                  if (e.which != 1) return;
                  CodeMirror.e_preventDefault(e);
                  var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
                  var start = e[axis], startpos = self.pos;
                  function done() {
                    CodeMirror.off(document, "mousemove", move);
                    CodeMirror.off(document, "mouseup", done);
                  }
                  function move(e) {
                    if (e.which != 1) return done();
                    self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
                  }
                  CodeMirror.on(document, "mousemove", move);
                  CodeMirror.on(document, "mouseup", done);
                });
            
                CodeMirror.on(this.node, "click", function(e) {
                  CodeMirror.e_preventDefault(e);
                  var innerBox = self.inner.getBoundingClientRect(), where;
                  if (self.orientation == "horizontal")
                    where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
                  else
                    where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
                  self.moveTo(self.pos + where * self.screen);
                });
            
                function onWheel(e) {
                  var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
                  var oldPos = self.pos;
                  self.moveTo(self.pos + moved);
                  if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
                }
                CodeMirror.on(this.node, "mousewheel", onWheel);
                CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
              }
            
              Bar.prototype.moveTo = function(pos, update) {
                if (pos < 0) pos = 0;
                if (pos > this.total - this.screen) pos = this.total - this.screen;
                if (pos == this.pos) return;
                this.pos = pos;
                this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
                  (pos * (this.size / this.total)) + "px";
                if (update !== false) this.scroll(pos, this.orientation);
              };
            
              Bar.prototype.update = function(scrollSize, clientSize, barSize) {
                this.screen = clientSize;
                this.total = scrollSize;
                this.size = barSize;
            
                // FIXME clip to min size?
                this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
                  this.screen * (this.size / this.total) + "px";
                this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
                  this.pos * (this.size / this.total) + "px";
              };
            
              function SimpleScrollbars(cls, place, scroll) {
                this.addClass = cls;
                this.horiz = new Bar(cls, "horizontal", scroll);
                place(this.horiz.node);
                this.vert = new Bar(cls, "vertical", scroll);
                place(this.vert.node);
                this.width = null;
              }
            
              SimpleScrollbars.prototype.update = function(measure) {
                if (this.width == null) {
                  var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
                  if (style) this.width = parseInt(style.height);
                }
                var width = this.width || 0;
            
                var needsH = measure.scrollWidth > measure.clientWidth + 1;
                var needsV = measure.scrollHeight > measure.clientHeight + 1;
                this.vert.node.style.display = needsV ? "block" : "none";
                this.horiz.node.style.display = needsH ? "block" : "none";
            
                if (needsV) {
                  this.vert.update(measure.scrollHeight, measure.clientHeight,
                                   measure.viewHeight - (needsH ? width : 0));
                  this.vert.node.style.display = "block";
                  this.vert.node.style.bottom = needsH ? width + "px" : "0";
                }
                if (needsH) {
                  this.horiz.update(measure.scrollWidth, measure.clientWidth,
                                    measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
                  this.horiz.node.style.right = needsV ? width + "px" : "0";
                  this.horiz.node.style.left = measure.barLeft + "px";
                }
            
                return {right: needsV ? width : 0, bottom: needsH ? width : 0};
              };
            
              SimpleScrollbars.prototype.setScrollTop = function(pos) {
                this.vert.moveTo(pos, false);
              };
            
              SimpleScrollbars.prototype.setScrollLeft = function(pos) {
                this.horiz.moveTo(pos, false);
              };
            
              SimpleScrollbars.prototype.clear = function() {
                var parent = this.horiz.node.parentNode;
                parent.removeChild(this.horiz.node);
                parent.removeChild(this.vert.node);
              };
            
              CodeMirror.scrollbarModel.simple = function(place, scroll) {
                return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
              };
              CodeMirror.scrollbarModel.overlay = function(place, scroll) {
                return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
              };
            });
            
        • search
          • match-highlighter.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Highlighting text that matches the selection
            //
            // Defines an option highlightSelectionMatches, which, when enabled,
            // will style strings that match the selection throughout the
            // document.
            //
            // The option can be set to true to simply enable it, or to a
            // {minChars, style, wordsOnly, showToken, delay} object to explicitly
            // configure it. minChars is the minimum amount of characters that should be
            // selected for the behavior to occur, and style is the token style to
            // apply to the matches. This will be prefixed by "cm-" to create an
            // actual CSS class name. If wordsOnly is enabled, the matches will be
            // highlighted only if the selected text is a word. showToken, when enabled,
            // will cause the current token to be highlighted when nothing is selected.
            // delay is used to specify how much time to wait, in milliseconds, before
            // highlighting the matches.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var DEFAULT_MIN_CHARS = 2;
              var DEFAULT_TOKEN_STYLE = "matchhighlight";
              var DEFAULT_DELAY = 100;
              var DEFAULT_WORDS_ONLY = false;
            
              function State(options) {
                if (typeof options == "object") {
                  this.minChars = options.minChars;
                  this.style = options.style;
                  this.showToken = options.showToken;
                  this.delay = options.delay;
                  this.wordsOnly = options.wordsOnly;
                }
                if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
                if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
                if (this.delay == null) this.delay = DEFAULT_DELAY;
                if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
                this.overlay = this.timeout = null;
              }
            
              CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  var over = cm.state.matchHighlighter.overlay;
                  if (over) cm.removeOverlay(over);
                  clearTimeout(cm.state.matchHighlighter.timeout);
                  cm.state.matchHighlighter = null;
                  cm.off("cursorActivity", cursorActivity);
                }
                if (val) {
                  cm.state.matchHighlighter = new State(val);
                  highlightMatches(cm);
                  cm.on("cursorActivity", cursorActivity);
                }
              });
            
              function cursorActivity(cm) {
                var state = cm.state.matchHighlighter;
                clearTimeout(state.timeout);
                state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
              }
            
              function highlightMatches(cm) {
                cm.operation(function() {
                  var state = cm.state.matchHighlighter;
                  if (state.overlay) {
                    cm.removeOverlay(state.overlay);
                    state.overlay = null;
                  }
                  if (!cm.somethingSelected() && state.showToken) {
                    var re = state.showToken === true ? /[\w$]/ : state.showToken;
                    var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
                    while (start && re.test(line.charAt(start - 1))) --start;
                    while (end < line.length && re.test(line.charAt(end))) ++end;
                    if (start < end)
                      cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
                    return;
                  }
                  var from = cm.getCursor("from"), to = cm.getCursor("to");
                  if (from.line != to.line) return;
                  if (state.wordsOnly && !isWord(cm, from, to)) return;
                  var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
                  if (selection.length >= state.minChars)
                    cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
                });
              }
            
              function isWord(cm, from, to) {
                var str = cm.getRange(from, to);
                if (str.match(/^\w+$/) !== null) {
                    if (from.ch > 0) {
                        var pos = {line: from.line, ch: from.ch - 1};
                        var chr = cm.getRange(pos, from);
                        if (chr.match(/\W/) === null) return false;
                    }
                    if (to.ch < cm.getLine(from.line).length) {
                        var pos = {line: to.line, ch: to.ch + 1};
                        var chr = cm.getRange(to, pos);
                        if (chr.match(/\W/) === null) return false;
                    }
                    return true;
                } else return false;
              }
            
              function boundariesAround(stream, re) {
                return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
                  (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
              }
            
              function makeOverlay(query, hasBoundary, style) {
                return {token: function(stream) {
                  if (stream.match(query) &&
                      (!hasBoundary || boundariesAround(stream, hasBoundary)))
                    return style;
                  stream.next();
                  stream.skipTo(query.charAt(0)) || stream.skipToEnd();
                }};
              }
            });
            
          • matchesonscrollbar.css
            .CodeMirror-search-match {
              background: gold;
              border-top: 1px solid orange;
              border-bottom: 1px solid orange;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              opacity: .5;
            }
            
          • matchesonscrollbar.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
                if (typeof options == "string") options = {className: options};
                if (!options) options = {};
                return new SearchAnnotation(this, query, caseFold, options);
              });
            
              function SearchAnnotation(cm, query, caseFold, options) {
                this.cm = cm;
                var annotateOptions = {listenForChanges: false};
                for (var prop in options) annotateOptions[prop] = options[prop];
                if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
                this.annotation = cm.annotateScrollbar(annotateOptions);
                this.query = query;
                this.caseFold = caseFold;
                this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
                this.matches = [];
                this.update = null;
            
                this.findMatches();
                this.annotation.update(this.matches);
            
                var self = this;
                cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
              }
            
              var MAX_MATCHES = 1000;
            
              SearchAnnotation.prototype.findMatches = function() {
                if (!this.gap) return;
                for (var i = 0; i < this.matches.length; i++) {
                  var match = this.matches[i];
                  if (match.from.line >= this.gap.to) break;
                  if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
                }
                var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
                while (cursor.findNext()) {
                  var match = {from: cursor.from(), to: cursor.to()};
                  if (match.from.line >= this.gap.to) break;
                  this.matches.splice(i++, 0, match);
                  if (this.matches.length > MAX_MATCHES) break;
                }
                this.gap = null;
              };
            
              function offsetLine(line, changeStart, sizeChange) {
                if (line <= changeStart) return line;
                return Math.max(changeStart, line + sizeChange);
              }
            
              SearchAnnotation.prototype.onChange = function(change) {
                var startLine = change.from.line;
                var endLine = CodeMirror.changeEnd(change).line;
                var sizeChange = endLine - change.to.line;
                if (this.gap) {
                  this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
                  this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
                } else {
                  this.gap = {from: change.from.line, to: endLine + 1};
                }
            
                if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
                  var match = this.matches[i];
                  var newFrom = offsetLine(match.from.line, startLine, sizeChange);
                  if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
                  var newTo = offsetLine(match.to.line, startLine, sizeChange);
                  if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
                }
                clearTimeout(this.update);
                var self = this;
                this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
              };
            
              SearchAnnotation.prototype.updateAfterChange = function() {
                this.findMatches();
                this.annotation.update(this.matches);
              };
            
              SearchAnnotation.prototype.clear = function() {
                this.cm.off("change", this.changeHandler);
                this.annotation.clear();
              };
            });
            
          • search.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Define search commands. Depends on dialog.js or another
            // implementation of the openDialog method.
            
            // Replace works a little oddly -- it will do the replace on the next
            // Ctrl-G (or whatever is bound to findNext) press. You prevent a
            // replace by making sure the match is no longer selected when hitting
            // Ctrl-G.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              function searchOverlay(query, caseInsensitive) {
                if (typeof query == "string")
                  query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
                else if (!query.global)
                  query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
            
                return {token: function(stream) {
                  query.lastIndex = stream.pos;
                  var match = query.exec(stream.string);
                  if (match && match.index == stream.pos) {
                    stream.pos += match[0].length;
                    return "searching";
                  } else if (match) {
                    stream.pos = match.index;
                  } else {
                    stream.skipToEnd();
                  }
                }};
              }
            
              function SearchState() {
                this.posFrom = this.posTo = this.query = null;
                this.overlay = null;
              }
              function getSearchState(cm) {
                return cm.state.search || (cm.state.search = new SearchState());
              }
              function queryCaseInsensitive(query) {
                return typeof query == "string" && query == query.toLowerCase();
              }
              function getSearchCursor(cm, query, pos) {
                // Heuristic: if the query string is all lowercase, do a case insensitive search.
                return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
              }
              function dialog(cm, text, shortText, deflt, f) {
                if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
                else f(prompt(shortText, deflt));
              }
              function confirmDialog(cm, text, shortText, fs) {
                if (cm.openConfirm) cm.openConfirm(text, fs);
                else if (confirm(shortText)) fs[0]();
              }
              function parseQuery(query) {
                var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
                if (isRE) {
                  try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
                  catch(e) {} // Not a regular expression after all, do a string search
                }
                if (typeof query == "string" ? query == "" : query.test(""))
                  query = /x^/;
                return query;
              }
              var queryDialog =
                'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
              function doSearch(cm, rev) {
                var state = getSearchState(cm);
                if (state.query) return findNext(cm, rev);
                dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
                  cm.operation(function() {
                    if (!query || state.query) return;
                    state.query = parseQuery(query);
                    cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
                    state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
                    cm.addOverlay(state.overlay);
                    if (cm.showMatchesOnScrollbar) {
                      if (state.annotate) { state.annotate.clear(); state.annotate = null; }
                      state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
                    }
                    state.posFrom = state.posTo = cm.getCursor();
                    findNext(cm, rev);
                  });
                });
              }
              function findNext(cm, rev) {cm.operation(function() {
                var state = getSearchState(cm);
                var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
                if (!cursor.find(rev)) {
                  cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
                  if (!cursor.find(rev)) return;
                }
                cm.setSelection(cursor.from(), cursor.to());
                cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
                state.posFrom = cursor.from(); state.posTo = cursor.to();
              });}
              function clearSearch(cm) {cm.operation(function() {
                var state = getSearchState(cm);
                if (!state.query) return;
                state.query = null;
                cm.removeOverlay(state.overlay);
                if (state.annotate) { state.annotate.clear(); state.annotate = null; }
              });}
            
              var replaceQueryDialog =
                'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
              var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
              var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
              function replace(cm, all) {
                if (cm.getOption("readOnly")) return;
                dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
                  if (!query) return;
                  query = parseQuery(query);
                  dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
                    if (all) {
                      cm.operation(function() {
                        for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
                          if (typeof query != "string") {
                            var match = cm.getRange(cursor.from(), cursor.to()).match(query);
                            cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
                          } else cursor.replace(text);
                        }
                      });
                    } else {
                      clearSearch(cm);
                      var cursor = getSearchCursor(cm, query, cm.getCursor());
                      var advance = function() {
                        var start = cursor.from(), match;
                        if (!(match = cursor.findNext())) {
                          cursor = getSearchCursor(cm, query);
                          if (!(match = cursor.findNext()) ||
                              (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
                        }
                        cm.setSelection(cursor.from(), cursor.to());
                        cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
                        confirmDialog(cm, doReplaceConfirm, "Replace?",
                                      [function() {doReplace(match);}, advance]);
                      };
                      var doReplace = function(match) {
                        cursor.replace(typeof query == "string" ? text :
                                       text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
                        advance();
                      };
                      advance();
                    }
                  });
                });
              }
            
              CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
              CodeMirror.commands.findNext = doSearch;
              CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
              CodeMirror.commands.clearSearch = clearSearch;
              CodeMirror.commands.replace = replace;
              CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
            });
            
          • searchcursor.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var Pos = CodeMirror.Pos;
            
              function SearchCursor(doc, query, pos, caseFold) {
                this.atOccurrence = false; this.doc = doc;
                if (caseFold == null && typeof query == "string") caseFold = false;
            
                pos = pos ? doc.clipPos(pos) : Pos(0, 0);
                this.pos = {from: pos, to: pos};
            
                // The matches method is filled in based on the type of query.
                // It takes a position and a direction, and returns an object
                // describing the next occurrence of the query, or null if no
                // more matches were found.
                if (typeof query != "string") { // Regexp match
                  if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
                  this.matches = function(reverse, pos) {
                    if (reverse) {
                      query.lastIndex = 0;
                      var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
                      for (;;) {
                        query.lastIndex = cutOff;
                        var newMatch = query.exec(line);
                        if (!newMatch) break;
                        match = newMatch;
                        start = match.index;
                        cutOff = match.index + (match[0].length || 1);
                        if (cutOff == line.length) break;
                      }
                      var matchLen = (match && match[0].length) || 0;
                      if (!matchLen) {
                        if (start == 0 && line.length == 0) {match = undefined;}
                        else if (start != doc.getLine(pos.line).length) {
                          matchLen++;
                        }
                      }
                    } else {
                      query.lastIndex = pos.ch;
                      var line = doc.getLine(pos.line), match = query.exec(line);
                      var matchLen = (match && match[0].length) || 0;
                      var start = match && match.index;
                      if (start + matchLen != line.length && !matchLen) matchLen = 1;
                    }
                    if (match && matchLen)
                      return {from: Pos(pos.line, start),
                              to: Pos(pos.line, start + matchLen),
                              match: match};
                  };
                } else { // String query
                  var origQuery = query;
                  if (caseFold) query = query.toLowerCase();
                  var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
                  var target = query.split("\n");
                  // Different methods for single-line and multi-line queries
                  if (target.length == 1) {
                    if (!query.length) {
                      // Empty string would match anything and never progress, so
                      // we define it to match nothing instead.
                      this.matches = function() {};
                    } else {
                      this.matches = function(reverse, pos) {
                        if (reverse) {
                          var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
                          var match = line.lastIndexOf(query);
                          if (match > -1) {
                            match = adjustPos(orig, line, match);
                            return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
                          }
                         } else {
                           var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
                           var match = line.indexOf(query);
                           if (match > -1) {
                             match = adjustPos(orig, line, match) + pos.ch;
                             return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
                           }
                        }
                      };
                    }
                  } else {
                    var origTarget = origQuery.split("\n");
                    this.matches = function(reverse, pos) {
                      var last = target.length - 1;
                      if (reverse) {
                        if (pos.line - (target.length - 1) < doc.firstLine()) return;
                        if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
                        var to = Pos(pos.line, origTarget[last].length);
                        for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
                          if (target[i] != fold(doc.getLine(ln))) return;
                        var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
                        if (fold(line.slice(cut)) != target[0]) return;
                        return {from: Pos(ln, cut), to: to};
                      } else {
                        if (pos.line + (target.length - 1) > doc.lastLine()) return;
                        var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
                        if (fold(line.slice(cut)) != target[0]) return;
                        var from = Pos(pos.line, cut);
                        for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
                          if (target[i] != fold(doc.getLine(ln))) return;
                        if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
                        return {from: from, to: Pos(ln, origTarget[last].length)};
                      }
                    };
                  }
                }
              }
            
              SearchCursor.prototype = {
                findNext: function() {return this.find(false);},
                findPrevious: function() {return this.find(true);},
            
                find: function(reverse) {
                  var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
                  function savePosAndFail(line) {
                    var pos = Pos(line, 0);
                    self.pos = {from: pos, to: pos};
                    self.atOccurrence = false;
                    return false;
                  }
            
                  for (;;) {
                    if (this.pos = this.matches(reverse, pos)) {
                      this.atOccurrence = true;
                      return this.pos.match || true;
                    }
                    if (reverse) {
                      if (!pos.line) return savePosAndFail(0);
                      pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
                    }
                    else {
                      var maxLine = this.doc.lineCount();
                      if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
                      pos = Pos(pos.line + 1, 0);
                    }
                  }
                },
            
                from: function() {if (this.atOccurrence) return this.pos.from;},
                to: function() {if (this.atOccurrence) return this.pos.to;},
            
                replace: function(newText) {
                  if (!this.atOccurrence) return;
                  var lines = CodeMirror.splitLines(newText);
                  this.doc.replaceRange(lines, this.pos.from, this.pos.to);
                  this.pos.to = Pos(this.pos.from.line + lines.length - 1,
                                    lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
                }
              };
            
              // Maps a position in a case-folded line back to a position in the original line
              // (compensating for codepoints increasing in number during folding)
              function adjustPos(orig, folded, pos) {
                if (orig.length == folded.length) return pos;
                for (var pos1 = Math.min(pos, orig.length);;) {
                  var len1 = orig.slice(0, pos1).toLowerCase().length;
                  if (len1 < pos) ++pos1;
                  else if (len1 > pos) --pos1;
                  else return pos1;
                }
              }
            
              CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
                return new SearchCursor(this.doc, query, pos, caseFold);
              });
              CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
                return new SearchCursor(this, query, pos, caseFold);
              });
            
              CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
                var ranges = [], next;
                var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
                while (next = cur.findNext()) {
                  if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
                  ranges.push({anchor: cur.from(), head: cur.to()});
                }
                if (ranges.length)
                  this.setSelections(ranges, 0);
              });
            });
            
        • selection
          • active-line.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Because sometimes you need to style the cursor's line.
            //
            // Adds an option 'styleActiveLine' which, when enabled, gives the
            // active line's wrapping <div> the CSS class "CodeMirror-activeline",
            // and gives its background <div> the class "CodeMirror-activeline-background".
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var WRAP_CLASS = "CodeMirror-activeline";
              var BACK_CLASS = "CodeMirror-activeline-background";
            
              CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.state.activeLines = [];
                  updateActiveLines(cm, cm.listSelections());
                  cm.on("beforeSelectionChange", selectionChange);
                } else if (!val && prev) {
                  cm.off("beforeSelectionChange", selectionChange);
                  clearActiveLines(cm);
                  delete cm.state.activeLines;
                }
              });
            
              function clearActiveLines(cm) {
                for (var i = 0; i < cm.state.activeLines.length; i++) {
                  cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
                  cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
                }
              }
            
              function sameArray(a, b) {
                if (a.length != b.length) return false;
                for (var i = 0; i < a.length; i++)
                  if (a[i] != b[i]) return false;
                return true;
              }
            
              function updateActiveLines(cm, ranges) {
                var active = [];
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (!range.empty()) continue;
                  var line = cm.getLineHandleVisualStart(range.head.line);
                  if (active[active.length - 1] != line) active.push(line);
                }
                if (sameArray(cm.state.activeLines, active)) return;
                cm.operation(function() {
                  clearActiveLines(cm);
                  for (var i = 0; i < active.length; i++) {
                    cm.addLineClass(active[i], "wrap", WRAP_CLASS);
                    cm.addLineClass(active[i], "background", BACK_CLASS);
                  }
                  cm.state.activeLines = active;
                });
              }
            
              function selectionChange(cm, sel) {
                updateActiveLines(cm, sel.ranges);
              }
            });
            
          • mark-selection.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Because sometimes you need to mark the selected *text*.
            //
            // Adds an option 'styleSelectedText' which, when enabled, gives
            // selected text the CSS class given as option value, or
            // "CodeMirror-selectedtext" when the value is not a string.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.state.markedSelection = [];
                  cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
                  reset(cm);
                  cm.on("cursorActivity", onCursorActivity);
                  cm.on("change", onChange);
                } else if (!val && prev) {
                  cm.off("cursorActivity", onCursorActivity);
                  cm.off("change", onChange);
                  clear(cm);
                  cm.state.markedSelection = cm.state.markedSelectionStyle = null;
                }
              });
            
              function onCursorActivity(cm) {
                cm.operation(function() { update(cm); });
              }
            
              function onChange(cm) {
                if (cm.state.markedSelection.length)
                  cm.operation(function() { clear(cm); });
              }
            
              var CHUNK_SIZE = 8;
              var Pos = CodeMirror.Pos;
              var cmp = CodeMirror.cmpPos;
            
              function coverRange(cm, from, to, addAt) {
                if (cmp(from, to) == 0) return;
                var array = cm.state.markedSelection;
                var cls = cm.state.markedSelectionStyle;
                for (var line = from.line;;) {
                  var start = line == from.line ? from : Pos(line, 0);
                  var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
                  var end = atEnd ? to : Pos(endLine, 0);
                  var mark = cm.markText(start, end, {className: cls});
                  if (addAt == null) array.push(mark);
                  else array.splice(addAt++, 0, mark);
                  if (atEnd) break;
                  line = endLine;
                }
              }
            
              function clear(cm) {
                var array = cm.state.markedSelection;
                for (var i = 0; i < array.length; ++i) array[i].clear();
                array.length = 0;
              }
            
              function reset(cm) {
                clear(cm);
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++)
                  coverRange(cm, ranges[i].from(), ranges[i].to());
              }
            
              function update(cm) {
                if (!cm.somethingSelected()) return clear(cm);
                if (cm.listSelections().length > 1) return reset(cm);
            
                var from = cm.getCursor("start"), to = cm.getCursor("end");
            
                var array = cm.state.markedSelection;
                if (!array.length) return coverRange(cm, from, to);
            
                var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
                if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
                    cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
                  return reset(cm);
            
                while (cmp(from, coverStart.from) > 0) {
                  array.shift().clear();
                  coverStart = array[0].find();
                }
                if (cmp(from, coverStart.from) < 0) {
                  if (coverStart.to.line - from.line < CHUNK_SIZE) {
                    array.shift().clear();
                    coverRange(cm, from, coverStart.to, 0);
                  } else {
                    coverRange(cm, from, coverStart.from, 0);
                  }
                }
            
                while (cmp(to, coverEnd.to) < 0) {
                  array.pop().clear();
                  coverEnd = array[array.length - 1].find();
                }
                if (cmp(to, coverEnd.to) > 0) {
                  if (to.line - coverEnd.from.line < CHUNK_SIZE) {
                    array.pop().clear();
                    coverRange(cm, coverEnd.from, to);
                  } else {
                    coverRange(cm, coverEnd.to, to);
                  }
                }
              }
            });
            
          • selection-pointer.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
                var data = cm.state.selectionPointer;
                if (data) {
                  CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
                  CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
                  CodeMirror.off(window, "scroll", data.windowScroll);
                  cm.off("cursorActivity", reset);
                  cm.off("scroll", reset);
                  cm.state.selectionPointer = null;
                  cm.display.lineDiv.style.cursor = "";
                }
                if (val) {
                  data = cm.state.selectionPointer = {
                    value: typeof val == "string" ? val : "default",
                    mousemove: function(event) { mousemove(cm, event); },
                    mouseout: function(event) { mouseout(cm, event); },
                    windowScroll: function() { reset(cm); },
                    rects: null,
                    mouseX: null, mouseY: null,
                    willUpdate: false
                  };
                  CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
                  CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
                  CodeMirror.on(window, "scroll", data.windowScroll);
                  cm.on("cursorActivity", reset);
                  cm.on("scroll", reset);
                }
              });
            
              function mousemove(cm, event) {
                var data = cm.state.selectionPointer;
                if (event.buttons == null ? event.which : event.buttons) {
                  data.mouseX = data.mouseY = null;
                } else {
                  data.mouseX = event.clientX;
                  data.mouseY = event.clientY;
                }
                scheduleUpdate(cm);
              }
            
              function mouseout(cm, event) {
                if (!cm.getWrapperElement().contains(event.relatedTarget)) {
                  var data = cm.state.selectionPointer;
                  data.mouseX = data.mouseY = null;
                  scheduleUpdate(cm);
                }
              }
            
              function reset(cm) {
                cm.state.selectionPointer.rects = null;
                scheduleUpdate(cm);
              }
            
              function scheduleUpdate(cm) {
                if (!cm.state.selectionPointer.willUpdate) {
                  cm.state.selectionPointer.willUpdate = true;
                  setTimeout(function() {
                    update(cm);
                    cm.state.selectionPointer.willUpdate = false;
                  }, 50);
                }
              }
            
              function update(cm) {
                var data = cm.state.selectionPointer;
                if (!data) return;
                if (data.rects == null && data.mouseX != null) {
                  data.rects = [];
                  if (cm.somethingSelected()) {
                    for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
                      data.rects.push(sel.getBoundingClientRect());
                  }
                }
                var inside = false;
                if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
                  var rect = data.rects[i];
                  if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
                      rect.top <= data.mouseY && rect.bottom >= data.mouseY)
                    inside = true;
                }
                var cursor = inside ? data.value : "";
                if (cm.display.lineDiv.style.cursor != cursor)
                  cm.display.lineDiv.style.cursor = cursor;
              }
            });
            
        • tern
          • tern.css
            .CodeMirror-Tern-completion {
              padding-left: 22px;
              position: relative;
            }
            .CodeMirror-Tern-completion:before {
              position: absolute;
              left: 2px;
              bottom: 2px;
              border-radius: 50%;
              font-size: 12px;
              font-weight: bold;
              height: 15px;
              width: 15px;
              line-height: 16px;
              text-align: center;
              color: white;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
            }
            .CodeMirror-Tern-completion-unknown:before {
              content: "?";
              background: #4bb;
            }
            .CodeMirror-Tern-completion-object:before {
              content: "O";
              background: #77c;
            }
            .CodeMirror-Tern-completion-fn:before {
              content: "F";
              background: #7c7;
            }
            .CodeMirror-Tern-completion-array:before {
              content: "A";
              background: #c66;
            }
            .CodeMirror-Tern-completion-number:before {
              content: "1";
              background: #999;
            }
            .CodeMirror-Tern-completion-string:before {
              content: "S";
              background: #999;
            }
            .CodeMirror-Tern-completion-bool:before {
              content: "B";
              background: #999;
            }
            
            .CodeMirror-Tern-completion-guess {
              color: #999;
            }
            
            .CodeMirror-Tern-tooltip {
              border: 1px solid silver;
              border-radius: 3px;
              color: #444;
              padding: 2px 5px;
              font-size: 90%;
              font-family: monospace;
              background-color: white;
              white-space: pre-wrap;
            
              max-width: 40em;
              position: absolute;
              z-index: 10;
              -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              box-shadow: 2px 3px 5px rgba(0,0,0,.2);
            
              transition: opacity 1s;
              -moz-transition: opacity 1s;
              -webkit-transition: opacity 1s;
              -o-transition: opacity 1s;
              -ms-transition: opacity 1s;
            }
            
            .CodeMirror-Tern-hint-doc {
              max-width: 25em;
              margin-top: -3px;
            }
            
            .CodeMirror-Tern-fname { color: black; }
            .CodeMirror-Tern-farg { color: #70a; }
            .CodeMirror-Tern-farg-current { text-decoration: underline; }
            .CodeMirror-Tern-type { color: #07c; }
            .CodeMirror-Tern-fhint-guess { opacity: .7; }
            
          • tern.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Glue code between CodeMirror and Tern.
            //
            // Create a CodeMirror.TernServer to wrap an actual Tern server,
            // register open documents (CodeMirror.Doc instances) with it, and
            // call its methods to activate the assisting functions that Tern
            // provides.
            //
            // Options supported (all optional):
            // * defs: An array of JSON definition data structures.
            // * plugins: An object mapping plugin names to configuration
            //   options.
            // * getFile: A function(name, c) that can be used to access files in
            //   the project that haven't been loaded yet. Simply do c(null) to
            //   indicate that a file is not available.
            // * fileFilter: A function(value, docName, doc) that will be applied
            //   to documents before passing them on to Tern.
            // * switchToDoc: A function(name, doc) that should, when providing a
            //   multi-file view, switch the view or focus to the named file.
            // * showError: A function(editor, message) that can be used to
            //   override the way errors are displayed.
            // * completionTip: Customize the content in tooltips for completions.
            //   Is passed a single argument—the completion's data as returned by
            //   Tern—and may return a string, DOM node, or null to indicate that
            //   no tip should be shown. By default the docstring is shown.
            // * typeTip: Like completionTip, but for the tooltips shown for type
            //   queries.
            // * responseFilter: A function(doc, query, request, error, data) that
            //   will be applied to the Tern responses before treating them
            //
            //
            // It is possible to run the Tern server in a web worker by specifying
            // these additional options:
            // * useWorker: Set to true to enable web worker mode. You'll probably
            //   want to feature detect the actual value you use here, for example
            //   !!window.Worker.
            // * workerScript: The main script of the worker. Point this to
            //   wherever you are hosting worker.js from this directory.
            // * workerDeps: An array of paths pointing (relative to workerScript)
            //   to the Acorn and Tern libraries and any Tern plugins you want to
            //   load. Or, if you minified those into a single script and included
            //   them in the workerScript, simply leave this undefined.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              // declare global: tern
            
              CodeMirror.TernServer = function(options) {
                var self = this;
                this.options = options || {};
                var plugins = this.options.plugins || (this.options.plugins = {});
                if (!plugins.doc_comment) plugins.doc_comment = true;
                if (this.options.useWorker) {
                  this.server = new WorkerServer(this);
                } else {
                  this.server = new tern.Server({
                    getFile: function(name, c) { return getFile(self, name, c); },
                    async: true,
                    defs: this.options.defs || [],
                    plugins: plugins
                  });
                }
                this.docs = Object.create(null);
                this.trackChange = function(doc, change) { trackChange(self, doc, change); };
            
                this.cachedArgHints = null;
                this.activeArgHints = null;
                this.jumpStack = [];
            
                this.getHint = function(cm, c) { return hint(self, cm, c); };
                this.getHint.async = true;
              };
            
              CodeMirror.TernServer.prototype = {
                addDoc: function(name, doc) {
                  var data = {doc: doc, name: name, changed: null};
                  this.server.addFile(name, docValue(this, data));
                  CodeMirror.on(doc, "change", this.trackChange);
                  return this.docs[name] = data;
                },
            
                delDoc: function(id) {
                  var found = resolveDoc(this, id);
                  if (!found) return;
                  CodeMirror.off(found.doc, "change", this.trackChange);
                  delete this.docs[found.name];
                  this.server.delFile(found.name);
                },
            
                hideDoc: function(id) {
                  closeArgHints(this);
                  var found = resolveDoc(this, id);
                  if (found && found.changed) sendDoc(this, found);
                },
            
                complete: function(cm) {
                  cm.showHint({hint: this.getHint});
                },
            
                showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
            
                showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
            
                updateArgHints: function(cm) { updateArgHints(this, cm); },
            
                jumpToDef: function(cm) { jumpToDef(this, cm); },
            
                jumpBack: function(cm) { jumpBack(this, cm); },
            
                rename: function(cm) { rename(this, cm); },
            
                selectName: function(cm) { selectName(this, cm); },
            
                request: function (cm, query, c, pos) {
                  var self = this;
                  var doc = findDoc(this, cm.getDoc());
                  var request = buildRequest(this, doc, query, pos);
            
                  this.server.request(request, function (error, data) {
                    if (!error && self.options.responseFilter)
                      data = self.options.responseFilter(doc, query, request, error, data);
                    c(error, data);
                  });
                },
            
                destroy: function () {
                  if (this.worker) {
                    this.worker.terminate();
                    this.worker = null;
                  }
                }
              };
            
              var Pos = CodeMirror.Pos;
              var cls = "CodeMirror-Tern-";
              var bigDoc = 250;
            
              function getFile(ts, name, c) {
                var buf = ts.docs[name];
                if (buf)
                  c(docValue(ts, buf));
                else if (ts.options.getFile)
                  ts.options.getFile(name, c);
                else
                  c(null);
              }
            
              function findDoc(ts, doc, name) {
                for (var n in ts.docs) {
                  var cur = ts.docs[n];
                  if (cur.doc == doc) return cur;
                }
                if (!name) for (var i = 0;; ++i) {
                  n = "[doc" + (i || "") + "]";
                  if (!ts.docs[n]) { name = n; break; }
                }
                return ts.addDoc(name, doc);
              }
            
              function resolveDoc(ts, id) {
                if (typeof id == "string") return ts.docs[id];
                if (id instanceof CodeMirror) id = id.getDoc();
                if (id instanceof CodeMirror.Doc) return findDoc(ts, id);
              }
            
              function trackChange(ts, doc, change) {
                var data = findDoc(ts, doc);
            
                var argHints = ts.cachedArgHints;
                if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
                  ts.cachedArgHints = null;
            
                var changed = data.changed;
                if (changed == null)
                  data.changed = changed = {from: change.from.line, to: change.from.line};
                var end = change.from.line + (change.text.length - 1);
                if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
                if (end >= changed.to) changed.to = end + 1;
                if (changed.from > change.from.line) changed.from = change.from.line;
            
                if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
                  if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
                }, 200);
              }
            
              function sendDoc(ts, doc) {
                ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
                  if (error) window.console.error(error);
                  else doc.changed = null;
                });
              }
            
              // Completion
            
              function hint(ts, cm, c) {
                ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  var completions = [], after = "";
                  var from = data.start, to = data.end;
                  if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
                      cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
                    after = "\"]";
            
                  for (var i = 0; i < data.completions.length; ++i) {
                    var completion = data.completions[i], className = typeToIcon(completion.type);
                    if (data.guess) className += " " + cls + "guess";
                    completions.push({text: completion.name + after,
                                      displayText: completion.name,
                                      className: className,
                                      data: completion});
                  }
            
                  var obj = {from: from, to: to, list: completions};
                  var tooltip = null;
                  CodeMirror.on(obj, "close", function() { remove(tooltip); });
                  CodeMirror.on(obj, "update", function() { remove(tooltip); });
                  CodeMirror.on(obj, "select", function(cur, node) {
                    remove(tooltip);
                    var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
                    if (content) {
                      tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
                                            node.getBoundingClientRect().top + window.pageYOffset, content);
                      tooltip.className += " " + cls + "hint-doc";
                    }
                  });
                  c(obj);
                });
              }
            
              function typeToIcon(type) {
                var suffix;
                if (type == "?") suffix = "unknown";
                else if (type == "number" || type == "string" || type == "bool") suffix = type;
                else if (/^fn\(/.test(type)) suffix = "fn";
                else if (/^\[/.test(type)) suffix = "array";
                else suffix = "object";
                return cls + "completion " + cls + "completion-" + suffix;
              }
            
              // Type queries
            
              function showContextInfo(ts, cm, pos, queryName, c) {
                ts.request(cm, queryName, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  if (ts.options.typeTip) {
                    var tip = ts.options.typeTip(data);
                  } else {
                    var tip = elt("span", null, elt("strong", null, data.type || "not found"));
                    if (data.doc)
                      tip.appendChild(document.createTextNode(" — " + data.doc));
                    if (data.url) {
                      tip.appendChild(document.createTextNode(" "));
                      var child = tip.appendChild(elt("a", null, "[docs]"));
                      child.href = data.url;
                      child.target = "_blank";
                    }
                  }
                  tempTooltip(cm, tip);
                  if (c) c();
                }, pos);
              }
            
              // Maintaining argument hints
            
              function updateArgHints(ts, cm) {
                closeArgHints(ts);
            
                if (cm.somethingSelected()) return;
                var state = cm.getTokenAt(cm.getCursor()).state;
                var inner = CodeMirror.innerMode(cm.getMode(), state);
                if (inner.mode.name != "javascript") return;
                var lex = inner.state.lexical;
                if (lex.info != "call") return;
            
                var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
                for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
                  var str = cm.getLine(line), extra = 0;
                  for (var pos = 0;;) {
                    var tab = str.indexOf("\t", pos);
                    if (tab == -1) break;
                    extra += tabSize - (tab + extra) % tabSize - 1;
                    pos = tab + 1;
                  }
                  ch = lex.column - extra;
                  if (str.charAt(ch) == "(") {found = true; break;}
                }
                if (!found) return;
            
                var start = Pos(line, ch);
                var cache = ts.cachedArgHints;
                if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
                  return showArgHints(ts, cm, argPos);
            
                ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
                  if (error || !data.type || !(/^fn\(/).test(data.type)) return;
                  ts.cachedArgHints = {
                    start: pos,
                    type: parseFnType(data.type),
                    name: data.exprName || data.name || "fn",
                    guess: data.guess,
                    doc: cm.getDoc()
                  };
                  showArgHints(ts, cm, argPos);
                });
              }
            
              function showArgHints(ts, cm, pos) {
                closeArgHints(ts);
            
                var cache = ts.cachedArgHints, tp = cache.type;
                var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
                              elt("span", cls + "fname", cache.name), "(");
                for (var i = 0; i < tp.args.length; ++i) {
                  if (i) tip.appendChild(document.createTextNode(", "));
                  var arg = tp.args[i];
                  tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
                  if (arg.type != "?") {
                    tip.appendChild(document.createTextNode(":\u00a0"));
                    tip.appendChild(elt("span", cls + "type", arg.type));
                  }
                }
                tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
                if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
                var place = cm.cursorCoords(null, "page");
                ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
              }
            
              function parseFnType(text) {
                var args = [], pos = 3;
            
                function skipMatching(upto) {
                  var depth = 0, start = pos;
                  for (;;) {
                    var next = text.charAt(pos);
                    if (upto.test(next) && !depth) return text.slice(start, pos);
                    if (/[{\[\(]/.test(next)) ++depth;
                    else if (/[}\]\)]/.test(next)) --depth;
                    ++pos;
                  }
                }
            
                // Parse arguments
                if (text.charAt(pos) != ")") for (;;) {
                  var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
                  if (name) {
                    pos += name[0].length;
                    name = name[1];
                  }
                  args.push({name: name, type: skipMatching(/[\),]/)});
                  if (text.charAt(pos) == ")") break;
                  pos += 2;
                }
            
                var rettype = text.slice(pos).match(/^\) -> (.*)$/);
            
                return {args: args, rettype: rettype && rettype[1]};
              }
            
              // Moving to the definition of something
            
              function jumpToDef(ts, cm) {
                function inner(varName) {
                  var req = {type: "definition", variable: varName || null};
                  var doc = findDoc(ts, cm.getDoc());
                  ts.server.request(buildRequest(ts, doc, req), function(error, data) {
                    if (error) return showError(ts, cm, error);
                    if (!data.file && data.url) { window.open(data.url); return; }
            
                    if (data.file) {
                      var localDoc = ts.docs[data.file], found;
                      if (localDoc && (found = findContext(localDoc.doc, data))) {
                        ts.jumpStack.push({file: doc.name,
                                           start: cm.getCursor("from"),
                                           end: cm.getCursor("to")});
                        moveTo(ts, doc, localDoc, found.start, found.end);
                        return;
                      }
                    }
                    showError(ts, cm, "Could not find a definition.");
                  });
                }
            
                if (!atInterestingExpression(cm))
                  dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
                else
                  inner();
              }
            
              function jumpBack(ts, cm) {
                var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
                if (!doc) return;
                moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
              }
            
              function moveTo(ts, curDoc, doc, start, end) {
                doc.doc.setSelection(start, end);
                if (curDoc != doc && ts.options.switchToDoc) {
                  closeArgHints(ts);
                  ts.options.switchToDoc(doc.name, doc.doc);
                }
              }
            
              // The {line,ch} representation of positions makes this rather awkward.
              function findContext(doc, data) {
                var before = data.context.slice(0, data.contextOffset).split("\n");
                var startLine = data.start.line - (before.length - 1);
                var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
            
                var text = doc.getLine(startLine).slice(start.ch);
                for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
                  text += "\n" + doc.getLine(cur);
                if (text.slice(0, data.context.length) == data.context) return data;
            
                var cursor = doc.getSearchCursor(data.context, 0, false);
                var nearest, nearestDist = Infinity;
                while (cursor.findNext()) {
                  var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
                  if (!dist) dist = Math.abs(from.ch - start.ch);
                  if (dist < nearestDist) { nearest = from; nearestDist = dist; }
                }
                if (!nearest) return null;
            
                if (before.length == 1)
                  nearest.ch += before[0].length;
                else
                  nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
                if (data.start.line == data.end.line)
                  var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
                else
                  var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
                return {start: nearest, end: end};
              }
            
              function atInterestingExpression(cm) {
                var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
                if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
                return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
              }
            
              // Variable renaming
            
              function rename(ts, cm) {
                var token = cm.getTokenAt(cm.getCursor());
                if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable");
                dialog(cm, "New name for " + token.string, function(newName) {
                  ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
                    if (error) return showError(ts, cm, error);
                    applyChanges(ts, data.changes);
                  });
                });
              }
            
              function selectName(ts, cm) {
                var name = findDoc(ts, cm.doc).name;
                ts.request(cm, {type: "refs"}, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  var ranges = [], cur = 0;
                  for (var i = 0; i < data.refs.length; i++) {
                    var ref = data.refs[i];
                    if (ref.file == name) {
                      ranges.push({anchor: ref.start, head: ref.end});
                      if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
                        cur = ranges.length - 1;
                    }
                  }
                  cm.setSelections(ranges, cur);
                });
              }
            
              var nextChangeOrig = 0;
              function applyChanges(ts, changes) {
                var perFile = Object.create(null);
                for (var i = 0; i < changes.length; ++i) {
                  var ch = changes[i];
                  (perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
                }
                for (var file in perFile) {
                  var known = ts.docs[file], chs = perFile[file];;
                  if (!known) continue;
                  chs.sort(function(a, b) { return cmpPos(b.start, a.start); });
                  var origin = "*rename" + (++nextChangeOrig);
                  for (var i = 0; i < chs.length; ++i) {
                    var ch = chs[i];
                    known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
                  }
                }
              }
            
              // Generic request-building helper
            
              function buildRequest(ts, doc, query, pos) {
                var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
                if (!allowFragments) delete query.fullDocs;
                if (typeof query == "string") query = {type: query};
                query.lineCharPositions = true;
                if (query.end == null) {
                  query.end = pos || doc.doc.getCursor("end");
                  if (doc.doc.somethingSelected())
                    query.start = doc.doc.getCursor("start");
                }
                var startPos = query.start || query.end;
            
                if (doc.changed) {
                  if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
                      doc.changed.to - doc.changed.from < 100 &&
                      doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
                    files.push(getFragmentAround(doc, startPos, query.end));
                    query.file = "#0";
                    var offsetLines = files[0].offsetLines;
                    if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
                    query.end = Pos(query.end.line - offsetLines, query.end.ch);
                  } else {
                    files.push({type: "full",
                                name: doc.name,
                                text: docValue(ts, doc)});
                    query.file = doc.name;
                    doc.changed = null;
                  }
                } else {
                  query.file = doc.name;
                }
                for (var name in ts.docs) {
                  var cur = ts.docs[name];
                  if (cur.changed && cur != doc) {
                    files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
                    cur.changed = null;
                  }
                }
            
                return {query: query, files: files};
              }
            
              function getFragmentAround(data, start, end) {
                var doc = data.doc;
                var minIndent = null, minLine = null, endLine, tabSize = 4;
                for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
                  var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
                  if (fn < 0) continue;
                  var indent = CodeMirror.countColumn(line, null, tabSize);
                  if (minIndent != null && minIndent <= indent) continue;
                  minIndent = indent;
                  minLine = p;
                }
                if (minLine == null) minLine = min;
                var max = Math.min(doc.lastLine(), end.line + 20);
                if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
                  endLine = max;
                else for (endLine = end.line + 1; endLine < max; ++endLine) {
                  var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
                  if (indent <= minIndent) break;
                }
                var from = Pos(minLine, 0);
            
                return {type: "part",
                        name: data.name,
                        offsetLines: from.line,
                        text: doc.getRange(from, Pos(endLine, 0))};
              }
            
              // Generic utilities
            
              var cmpPos = CodeMirror.cmpPos;
            
              function elt(tagname, cls /*, ... elts*/) {
                var e = document.createElement(tagname);
                if (cls) e.className = cls;
                for (var i = 2; i < arguments.length; ++i) {
                  var elt = arguments[i];
                  if (typeof elt == "string") elt = document.createTextNode(elt);
                  e.appendChild(elt);
                }
                return e;
              }
            
              function dialog(cm, text, f) {
                if (cm.openDialog)
                  cm.openDialog(text + ": <input type=text>", f);
                else
                  f(prompt(text, ""));
              }
            
              // Tooltips
            
              function tempTooltip(cm, content) {
                if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
                var where = cm.cursorCoords();
                var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
                function maybeClear() {
                  old = true;
                  if (!mouseOnTip) clear();
                }
                function clear() {
                  cm.state.ternTooltip = null;
                  if (!tip.parentNode) return;
                  cm.off("cursorActivity", clear);
                  cm.off('blur', clear);
                  cm.off('scroll', clear);
                  fadeOut(tip);
                }
                var mouseOnTip = false, old = false;
                CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
                CodeMirror.on(tip, "mouseout", function(e) {
                  if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
                    if (old) clear();
                    else mouseOnTip = false;
                  }
                });
                setTimeout(maybeClear, 1700);
                cm.on("cursorActivity", clear);
                cm.on('blur', clear);
                cm.on('scroll', clear);
              }
            
              function makeTooltip(x, y, content) {
                var node = elt("div", cls + "tooltip", content);
                node.style.left = x + "px";
                node.style.top = y + "px";
                document.body.appendChild(node);
                return node;
              }
            
              function remove(node) {
                var p = node && node.parentNode;
                if (p) p.removeChild(node);
              }
            
              function fadeOut(tooltip) {
                tooltip.style.opacity = "0";
                setTimeout(function() { remove(tooltip); }, 1100);
              }
            
              function showError(ts, cm, msg) {
                if (ts.options.showError)
                  ts.options.showError(cm, msg);
                else
                  tempTooltip(cm, String(msg));
              }
            
              function closeArgHints(ts) {
                if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
              }
            
              function docValue(ts, doc) {
                var val = doc.doc.getValue();
                if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
                return val;
              }
            
              // Worker wrapper
            
              function WorkerServer(ts) {
                var worker = ts.worker = new Worker(ts.options.workerScript);
                worker.postMessage({type: "init",
                                    defs: ts.options.defs,
                                    plugins: ts.options.plugins,
                                    scripts: ts.options.workerDeps});
                var msgId = 0, pending = {};
            
                function send(data, c) {
                  if (c) {
                    data.id = ++msgId;
                    pending[msgId] = c;
                  }
                  worker.postMessage(data);
                }
                worker.onmessage = function(e) {
                  var data = e.data;
                  if (data.type == "getFile") {
                    getFile(ts, data.name, function(err, text) {
                      send({type: "getFile", err: String(err), text: text, id: data.id});
                    });
                  } else if (data.type == "debug") {
                    window.console.log(data.message);
                  } else if (data.id && pending[data.id]) {
                    pending[data.id](data.err, data.body);
                    delete pending[data.id];
                  }
                };
                worker.onerror = function(e) {
                  for (var id in pending) pending[id](e);
                  pending = {};
                };
            
                this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
                this.delFile = function(name) { send({type: "del", name: name}); };
                this.request = function(body, c) { send({type: "req", body: body}, c); };
              }
            });
            
          • worker.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // declare global: tern, server
            
            var server;
            
            this.onmessage = function(e) {
              var data = e.data;
              switch (data.type) {
              case "init": return startServer(data.defs, data.plugins, data.scripts);
              case "add": return server.addFile(data.name, data.text);
              case "del": return server.delFile(data.name);
              case "req": return server.request(data.body, function(err, reqData) {
                postMessage({id: data.id, body: reqData, err: err && String(err)});
              });
              case "getFile":
                var c = pending[data.id];
                delete pending[data.id];
                return c(data.err, data.text);
              default: throw new Error("Unknown message type: " + data.type);
              }
            };
            
            var nextId = 0, pending = {};
            function getFile(file, c) {
              postMessage({type: "getFile", name: file, id: ++nextId});
              pending[nextId] = c;
            }
            
            function startServer(defs, plugins, scripts) {
              if (scripts) importScripts.apply(null, scripts);
            
              server = new tern.Server({
                getFile: getFile,
                async: true,
                defs: defs,
                plugins: plugins
              });
            }
            
            var console = {
              log: function(v) { postMessage({type: "debug", message: v}); }
            };
            
        • wrap
          • hardwrap.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
            
              function findParagraph(cm, pos, options) {
                var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
                for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
                  var line = cm.getLine(start);
                  if (startRE && startRE.test(line)) break;
                  if (!/\S/.test(line)) { ++start; break; }
                }
                var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
                for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
                  var line = cm.getLine(end);
                  if (endRE && endRE.test(line)) { ++end; break; }
                  if (!/\S/.test(line)) break;
                }
                return {from: start, to: end};
              }
            
              function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
                for (var at = column; at > 0; --at)
                  if (wrapOn.test(text.slice(at - 1, at + 1))) break;
                if (at == 0) at = column;
                var endOfText = at;
                if (killTrailingSpace)
                  while (text.charAt(endOfText - 1) == " ") --endOfText;
                return {from: endOfText, to: at};
              }
            
              function wrapRange(cm, from, to, options) {
                from = cm.clipPos(from); to = cm.clipPos(to);
                var column = options.column || 80;
                var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
                var killTrailing = options.killTrailingSpace !== false;
                var changes = [], curLine = "", curNo = from.line;
                var lines = cm.getRange(from, to, false);
                if (!lines.length) return null;
                var leadingSpace = lines[0].match(/^[ \t]*/)[0];
            
                for (var i = 0; i < lines.length; ++i) {
                  var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
                  if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
                    curLine += " ";
                    spaceInserted = 1;
                  }
                  var spaceTrimmed = "";
                  if (i) {
                    spaceTrimmed = text.match(/^\s*/)[0];
                    text = text.slice(spaceTrimmed.length);
                  }
                  curLine += text;
                  if (i) {
                    var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
                      findBreakPoint(curLine, column, wrapOn, killTrailing);
                    // If this isn't broken, or is broken at a different point, remove old break
                    if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
                      changes.push({text: [spaceInserted ? " " : ""],
                                    from: Pos(curNo, oldLen),
                                    to: Pos(curNo + 1, spaceTrimmed.length)});
                    } else {
                      curLine = leadingSpace + text;
                      ++curNo;
                    }
                  }
                  while (curLine.length > column) {
                    var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
                    changes.push({text: ["", leadingSpace],
                                  from: Pos(curNo, bp.from),
                                  to: Pos(curNo, bp.to)});
                    curLine = leadingSpace + curLine.slice(bp.to);
                    ++curNo;
                  }
                }
                if (changes.length) cm.operation(function() {
                  for (var i = 0; i < changes.length; ++i) {
                    var change = changes[i];
                    cm.replaceRange(change.text, change.from, change.to);
                  }
                });
                return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
              }
            
              CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
                options = options || {};
                if (!pos) pos = this.getCursor();
                var para = findParagraph(this, pos, options);
                return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
              });
            
              CodeMirror.commands.wrapLines = function(cm) {
                cm.operation(function() {
                  var ranges = cm.listSelections(), at = cm.lastLine() + 1;
                  for (var i = ranges.length - 1; i >= 0; i--) {
                    var range = ranges[i], span;
                    if (range.empty()) {
                      var para = findParagraph(cm, range.head, {});
                      span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
                    } else {
                      span = {from: range.from(), to: range.to()};
                    }
                    if (span.to.line >= at) continue;
                    at = span.from.line;
                    wrapRange(cm, span.from, span.to, {});
                  }
                });
              };
            
              CodeMirror.defineExtension("wrapRange", function(from, to, options) {
                return wrapRange(this, from, to, options || {});
              });
            
              CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
                options = options || {};
                var cm = this, paras = [];
                for (var line = from.line; line <= to.line;) {
                  var para = findParagraph(cm, Pos(line, 0), options);
                  paras.push(para);
                  line = para.to;
                }
                var madeChange = false;
                if (paras.length) cm.operation(function() {
                  for (var i = paras.length - 1; i >= 0; --i)
                    madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
                });
                return madeChange;
              });
            });
            
      • bin
        • authors.sh
          # Combine existing list of authors with everyone known in git, sort, add header.
          tail --lines=+3 AUTHORS > AUTHORS.tmp
          git log --format='%aN' >> AUTHORS.tmp
          echo -e "List of CodeMirror contributors. Updated before every release.\n" > AUTHORS
          sort -u AUTHORS.tmp >> AUTHORS
          rm -f AUTHORS.tmp
          
        • compress
          #!/usr/bin/env node
          
          // Compression helper for CodeMirror
          //
          // Example:
          //
          //   bin/compress codemirror runmode javascript xml
          //
          // Will take lib/codemirror.js, addon/runmode/runmode.js,
          // mode/javascript/javascript.js, and mode/xml/xml.js, run them though
          // the online minifier at http://marijnhaverbeke.nl/uglifyjs, and spit
          // out the result.
          //
          //   bin/compress codemirror --local /path/to/bin/UglifyJS
          //
          // Will use a local minifier instead of the online default one.
          //
          // Script files are specified without .js ending. Prefixing them with
          // their full (local) path is optional. So you may say lib/codemirror
          // or mode/xml/xml to be more precise. In fact, even the .js suffix
          // may be speficied, if wanted.
          
          "use strict";
          
          var fs = require("fs");
          
          function help(ok) {
            console.log("usage: " + process.argv[1] + " [--local /path/to/uglifyjs] files...");
            process.exit(ok ? 0 : 1);
          }
          
          var local = null, args = [], extraArgs = null, files = [], blob = "";
          
          for (var i = 2; i < process.argv.length; ++i) {
            var arg = process.argv[i];
            if (arg == "--local" && i + 1 < process.argv.length) {
              var parts = process.argv[++i].split(/\s+/);
              local = parts[0];
              extraArgs = parts.slice(1);
              if (!extraArgs.length) extraArgs = ["-c", "-m"];
            } else if (arg == "--help") {
              help(true);
            } else if (arg[0] != "-") {
              files.push({name: arg, re: new RegExp("(?:\\/|^)" + arg + (/\.js$/.test(arg) ? "$" : "\\.js$"))});
            } else help(false);
          }
          
          function walk(dir) {
            fs.readdirSync(dir).forEach(function(fname) {
              if (/^[_\.]/.test(fname)) return;
              var file = dir + fname;
              if (fs.statSync(file).isDirectory()) return walk(file + "/");
              if (files.some(function(spec, i) {
                var match = spec.re.test(file);
                if (match) files.splice(i, 1);
                return match;
              })) {
                if (local) args.push(file);
                else blob += fs.readFileSync(file, "utf8");
              }
            });
          }
          
          walk("lib/");
          walk("addon/");
          walk("mode/");
          
          if (!local && !blob) help(false);
          
          if (files.length) {
            console.log("Some speficied files were not found: " +
                        files.map(function(a){return a.name;}).join(", "));
            process.exit(1);
          }
            
          if (local) {
            require("child_process").spawn(local, args.concat(extraArgs), {stdio: ["ignore", process.stdout, process.stderr]});
          } else {
            var data = new Buffer("js_code=" + require("querystring").escape(blob), "utf8");
            var req = require("http").request({
              host: "marijnhaverbeke.nl",
              port: 80,
              method: "POST",
              path: "/uglifyjs",
              headers: {"content-type": "application/x-www-form-urlencoded",
                        "content-length": data.length}
            });
            req.on("response", function(resp) {
              resp.on("data", function (chunk) { process.stdout.write(chunk); });
            });
            req.end(data);
          }
          
        • lint
          #!/usr/bin/env node
          
          process.exit(require("../test/lint").ok ? 0 : 1);
          
        • release
          #!/usr/bin/env node
          
          var fs = require("fs"), child = require("child_process");
          
          var number, bumpOnly;
          
          for (var i = 2; i < process.argv.length; i++) {
            if (process.argv[i] == "-bump") bumpOnly = true;
            else if (/^\d+\.\d+\.\d+$/.test(process.argv[i])) number = process.argv[i];
            else { console.log("Bogus command line arg: " + process.argv[i]); process.exit(1); }
          }
          
          if (!number) { console.log("Must give a version"); process.exit(1); }
          
          function rewrite(file, f) {
            fs.writeFileSync(file, f(fs.readFileSync(file, "utf8")), "utf8");
          }
          
          rewrite("lib/codemirror.js", function(lib) {
            return lib.replace(/CodeMirror\.version = "\d+\.\d+\.\d+"/,
                               "CodeMirror.version = \"" + number + "\"");
          });
          function rewriteJSON(pack) {
            return pack.replace(/"version":"\d+\.\d+\.\d+"/, "\"version\":\"" + number + "\"");
          }
          rewrite("package.json", rewriteJSON);
          rewrite("bower.json", rewriteJSON);
          rewrite("doc/manual.html", function(manual) {
            return manual.replace(/>version \d+\.\d+\.\d+<\/span>/, ">version " + number + "</span>");
          });
          
          if (bumpOnly) process.exit(0);
          
          child.exec("bash bin/authors.sh", function(){});
          
          var simple = number.slice(0, number.lastIndexOf("."));
          
          rewrite("doc/compress.html", function(cmp) {
            return cmp.replace(/<option value="http:\/\/codemirror.net\/">HEAD<\/option>/,
                               "<option value=\"http://codemirror.net/\">HEAD</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=" + number + ";f=\">" + simple + "</option>");
          });
          
          rewrite("index.html", function(index) {
            return index.replace(/\.zip">\d+\.\d+<\/a>/,
                                 ".zip\">" + simple + "</a>");
          });
          
        • source-highlight
          #!/usr/bin/env node
          
          // Simple command-line code highlighting tool. Reads code from stdin,
          // spits html to stdout. For example:
          //
          //   echo 'function foo(a) { return a; }' | bin/source-highlight -s javascript
          //   bin/source-highlight -s 
          
          var fs = require("fs");
          
          var CodeMirror = require("../addon/runmode/runmode.node.js");
          require("../mode/meta.js");
          
          var sPos = process.argv.indexOf("-s");
          if (sPos == -1 || sPos == process.argv.length - 1) {
             console.error("Usage: source-highlight -s language");
             process.exit(1);
          }
          var lang = process.argv[sPos + 1].toLowerCase(), modeName = lang;
          CodeMirror.modeInfo.forEach(function(info) {
            if (info.mime == lang) {
              modeName = info.mode;
            } else if (info.name.toLowerCase() == lang) {
              modeName = info.mode;
              lang = info.mime;
            }
          });
          
          if (!CodeMirror.modes[modeName])
            require("../mode/" + modeName + "/" + modeName + ".js");
          
          function esc(str) {
            return str.replace(/[<&]/g, function(ch) { return ch == "&" ? "&amp;" : "&lt;"; });
          }
          
          var code = fs.readFileSync("/dev/stdin", "utf8");
          var curStyle = null, accum = "";
          function flush() {
            if (curStyle) process.stdout.write("<span class=\"" + curStyle.replace(/(^|\s+)/g, "$1cm-") + "\">" + esc(accum) + "</span>");
            else process.stdout.write(esc(accum));
          }
          
          CodeMirror.runMode(code, lang, function(text, style) {
            if (style != curStyle) {
              flush();
              curStyle = style; accum = text;
            } else {
              accum += text;
            }
          });
          flush();
          
      • demo
        • activeline.html
          <!doctype html>
          
          <title>CodeMirror: Active Line Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/selection/active-line.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Active Line</a>
            </ul>
          </div>
          
          <article>
          <h2>Active Line Demo</h2>
          <form><textarea id="code" name="code">
          <?xml version="1.0" encoding="UTF-8"?>
          <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
               xmlns:georss="http://www.georss.org/georss"
               xmlns:twitter="http://api.twitter.com">
            <channel>
              <title>Twitter / codemirror</title>
              <link>http://twitter.com/codemirror</link>
              <atom:link type="application/rss+xml"
                         href="http://twitter.com/statuses/user_timeline/242283288.rss" rel="self"/>
              <description>Twitter updates from CodeMirror / codemirror.</description>
              <language>en-us</language>
              <ttl>40</ttl>
            <item>
              <title>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This one
                uses CodeMirror as its editor.</title>
              <description>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This
                one uses CodeMirror as its editor.</description>
              <pubDate>Thu, 17 Mar 2011 23:34:47 +0000</pubDate>
              <guid>http://twitter.com/codemirror/statuses/48527733722058752</guid>
              <link>http://twitter.com/codemirror/statuses/48527733722058752</link>
              <twitter:source>web</twitter:source>
              <twitter:place/>
            </item>
            <item>
              <title>codemirror: Posted a description of the CodeMirror 2 internals at
                http://codemirror.net/2/internals.html</title>
              <description>codemirror: Posted a description of the CodeMirror 2 internals at
                http://codemirror.net/2/internals.html</description>
              <pubDate>Wed, 02 Mar 2011 12:15:09 +0000</pubDate>
              <guid>http://twitter.com/codemirror/statuses/42920879788789760</guid>
              <link>http://twitter.com/codemirror/statuses/42920879788789760</link>
              <twitter:source>web</twitter:source>
              <twitter:place/>
            </item>
            </channel>
          </rss></textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "application/xml",
            styleActiveLine: true,
            lineNumbers: true,
            lineWrapping: true
          });
          </script>
          
              <p>Styling the current cursor line.</p>
          
            </article>
          
        • anywordhint.html
          <!doctype html>
          
          <title>CodeMirror: Any Word Completion Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/anyword-hint.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Any Word Completion</a>
            </ul>
          </div>
          
          <article>
          <h2>Any Word Completion Demo</h2>
          <form><textarea id="code" name="code">
          (function() {
            "use strict";
          
            var WORD = /[\w$]+/g, RANGE = 500;
          
            CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
              var word = options && options.word || WORD;
              var range = options && options.range || RANGE;
              var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
              var start = cur.ch, end = start;
              while (end < curLine.length && word.test(curLine.charAt(end))) ++end;
              while (start && word.test(curLine.charAt(start - 1))) --start;
              var curWord = start != end && curLine.slice(start, end);
          
              var list = [], seen = {};
              function scan(dir) {
                var line = cur.line, end = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
                for (; line != end; line += dir) {
                  var text = editor.getLine(line), m;
                  word.lastIndex = 0;
                  while (m = word.exec(text)) {
                    if ((!curWord || m[0].indexOf(curWord) == 0) && !seen.hasOwnProperty(m[0])) {
                      seen[m[0]] = true;
                      list.push(m[0]);
                    }
                  }
                }
              }
              scan(-1);
              scan(1);
              return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
            });
          })();
          </textarea></form>
          
          <p>Press <strong>ctrl-space</strong> to activate autocompletion. The
          completion uses
          the <a href="../doc/manual.html#addon_anyword-hint">anyword-hint.js</a>
          module, which simply looks at nearby words in the buffer and completes
          to those.</p>
          
              <script>
                CodeMirror.commands.autocomplete = function(cm) {
                  cm.showHint({hint: CodeMirror.hint.anyword});
                }
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  extraKeys: {"Ctrl-Space": "autocomplete"}
                });
              </script>
            </article>
          
        • bidi.html
          <!doctype html>
          
          <title>CodeMirror: Bi-directional Text Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Bi-directional Text</a>
            </ul>
          </div>
          
          <article>
          <h2>Bi-directional Text Demo</h2>
          <form><textarea id="code" name="code"><!-- Piece of the CodeMirror manual, 'translated' into Arabic by
               Google Translate -->
          
          <dl>
            <dt id=option_value><code>value (string or Doc)</code></dt>
            <dd>قيمة البداية المحرر. يمكن أن تكون سلسلة، أو. كائن مستند.</dd>
            <dt id=option_mode><code>mode (string or object)</code></dt>
            <dd>وضع الاستخدام. عندما لا تعطى، وهذا الافتراضي إلى الطريقة الاولى
            التي تم تحميلها. قد يكون من سلسلة، والتي إما أسماء أو ببساطة هو وضع
            MIME نوع المرتبطة اسطة. بدلا من ذلك، قد يكون من كائن يحتوي على
            خيارات التكوين لواسطة، مع <code>name</code> الخاصية التي وضع أسماء
            (على سبيل المثال <code>{name: "javascript", json: true}</code>).
            صفحات التجريبي لكل وضع تحتوي على معلومات حول ما معلمات تكوين وضع
            يدعمها. يمكنك أن تطلب CodeMirror التي تم تعريفها طرق وأنواع MIME
            الكشف على <code>CodeMirror.modes</code>
            و <code>CodeMirror.mimeModes</code> الكائنات. وضع خرائط الأسماء
            الأولى لمنشئات الخاصة بهم، وخرائط لأنواع MIME 2 المواصفات
            واسطة.</dd>
            <dt id=option_theme><code>theme (string)</code></dt>
            <dd>موضوع لنمط المحرر مع. يجب عليك التأكد من الملف CSS تحديد
            المقابلة <code>.cm-s-[name]</code> يتم تحميل أنماط (انظر
            <a href="../theme/"><code>theme</code></a> الدليل في التوزيع).
            الافتراضي هو <code>"default"</code> ، والتي تم تضمينها في
            الألوان <code>codemirror.css</code>. فمن الممكن استخدام فئات متعددة
            في تطبيق السمات مرة واحدة على سبيل المثال <code>"foo bar"</code>
            سيتم تعيين كل من <code>cm-s-foo</code> و <code>cm-s-bar</code>
            الطبقات إلى المحرر.</dd>
          </dl>
          </textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "text/html",
            lineNumbers: true
          });
          </script>
          
            <p>Demonstration of bi-directional text support. See
            the <a href="http://marijnhaverbeke.nl/blog/cursor-in-bidi-text.html">related
            blog post</a> for more background.</p>
          
            <p><strong>Note:</strong> There is
            a <a href="https://github.com/codemirror/CodeMirror/issues/1757">known
            bug</a> with cursor motion and mouse clicks in bi-directional lines
            that are line wrapped.</p>
          
          </article>
          
        • btree.html
          <!doctype html>
          
          <title>CodeMirror: B-Tree visualization</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <style type="text/css">
                .lineblock { display: inline-block; margin: 1px; height: 5px; }
                .CodeMirror {border: 1px solid #aaa; height: 400px}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">B-Tree visualization</a>
            </ul>
          </div>
          
          <article>
          <h2>B-Tree visualization</h2>
          <form><textarea id="code" name="code">type here, see a summary of the document b-tree below</textarea></form>
                </div>
                <div style="display: inline-block; height: 402px; overflow-y: auto" id="output"></div>
              </div>
          
              <script id="me">
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            lineWrapping: true
          });
          var updateTimeout;
          editor.on("change", function(cm) {
            clearTimeout(updateTimeout);
            updateTimeout = setTimeout(updateVisual, 200);
          });
          updateVisual();
          
          function updateVisual() {
            var out = document.getElementById("output");
            out.innerHTML = "";
          
            function drawTree(out, node) {
              if (node.lines) {
                out.appendChild(document.createElement("div")).innerHTML =
                  "<b>leaf</b>: " + node.lines.length + " lines, " + Math.round(node.height) + " px";
                var lines = out.appendChild(document.createElement("div"));
                lines.style.lineHeight = "6px"; lines.style.marginLeft = "10px";
                for (var i = 0; i < node.lines.length; ++i) {
                  var line = node.lines[i], lineElt = lines.appendChild(document.createElement("div"));
                  lineElt.className = "lineblock";
                  var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16);
                  if (col.length == 1) col = "0" + col;
                  lineElt.style.background = "#" + col + col + col;
                  lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";
                }
              } else {
                out.appendChild(document.createElement("div")).innerHTML =
                  "<b>node</b>: " + node.size + " lines, " + Math.round(node.height) + " px";
                var sub = out.appendChild(document.createElement("div"));
                sub.style.paddingLeft = "20px";
                for (var i = 0; i < node.children.length; ++i)
                  drawTree(sub, node.children[i]);
              }
            }
            drawTree(out, editor.getDoc());
          }
          
          function fillEditor() {
            var sc = document.getElementById("me");
            var doc = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "") + "\n";
            doc += doc; doc += doc; doc += doc; doc += doc; doc += doc; doc += doc;
            editor.setValue(doc);
          }
              </script>
          
          <p><button onclick="fillEditor()">Add a lot of content</button></p>
          
            </article>
          
        • buffers.html
          <!doctype html>
          
          <title>CodeMirror: Multiple Buffer & Split View Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <style type="text/css" id=style>
                .CodeMirror {border: 1px solid black; height: 250px;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Multiple Buffer & Split View</a>
            </ul>
          </div>
          
          <article>
          <h2>Multiple Buffer & Split View Demo</h2>
          
          
              <div id=code_top></div>
              <div>
                Select buffer: <select id=buffers_top></select>
                &nbsp; &nbsp; <button onclick="newBuf('top')">New buffer</button>
              </div>
              <div id=code_bot></div>
              <div>
                Select buffer: <select id=buffers_bot></select>
                &nbsp; &nbsp; <button onclick="newBuf('bot')">New buffer</button>
              </div>
          
              <script id=script>
          var sel_top = document.getElementById("buffers_top");
          CodeMirror.on(sel_top, "change", function() {
            selectBuffer(ed_top, sel_top.options[sel_top.selectedIndex].value);
          });
          
          var sel_bot = document.getElementById("buffers_bot");
          CodeMirror.on(sel_bot, "change", function() {
            selectBuffer(ed_bot, sel_bot.options[sel_bot.selectedIndex].value);
          });
          
          var buffers = {};
          
          function openBuffer(name, text, mode) {
            buffers[name] = CodeMirror.Doc(text, mode);
            var opt = document.createElement("option");
            opt.appendChild(document.createTextNode(name));
            sel_top.appendChild(opt);
            sel_bot.appendChild(opt.cloneNode(true));
          }
          
          function newBuf(where) {
            var name = prompt("Name for the buffer", "*scratch*");
            if (name == null) return;
            if (buffers.hasOwnProperty(name)) {
              alert("There's already a buffer by that name.");
              return;
            }
            openBuffer(name, "", "javascript");
            selectBuffer(where == "top" ? ed_top : ed_bot, name);
            var sel = where == "top" ? sel_top : sel_bot;
            sel.value = name;
          }
          
          function selectBuffer(editor, name) {
            var buf = buffers[name];
            if (buf.getEditor()) buf = buf.linkedDoc({sharedHist: true});
            var old = editor.swapDoc(buf);
            var linked = old.iterLinkedDocs(function(doc) {linked = doc;});
            if (linked) {
              // Make sure the document in buffers is the one the other view is looking at
              for (var name in buffers) if (buffers[name] == old) buffers[name] = linked;
              old.unlinkDoc(linked);
            }
            editor.focus();
          }
          
          function nodeContent(id) {
            var node = document.getElementById(id), val = node.textContent || node.innerText;
            val = val.slice(val.match(/^\s*/)[0].length, val.length - val.match(/\s*$/)[0].length) + "\n";
            return val;
          }
          openBuffer("js", nodeContent("script"), "javascript");
          openBuffer("css", nodeContent("style"), "css");
          
          var ed_top = CodeMirror(document.getElementById("code_top"), {lineNumbers: true});
          selectBuffer(ed_top, "js");
          var ed_bot = CodeMirror(document.getElementById("code_bot"), {lineNumbers: true});
          selectBuffer(ed_bot, "js");
          </script>
          
              <p>Demonstration of
              using <a href="../doc/manual.html#linkedDoc">linked documents</a>
              to provide a split view on a document, and
              using <a href="../doc/manual.html#swapDoc"><code>swapDoc</code></a>
              to use a single editor to display multiple documents.</p>
          
            </article>
          
        • changemode.html
          <!doctype html>
          
          <title>CodeMirror: Mode-Changing Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/scheme/scheme.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Mode-Changing</a>
            </ul>
          </div>
          
          <article>
          <h2>Mode-Changing Demo</h2>
          <form><textarea id="code" name="code">
          ;; If there is Scheme code in here, the editor will be in Scheme mode.
          ;; If you put in JS instead, it'll switch to JS mode.
          
          (define (double x)
            (* x x))
          </textarea></form>
          
          <p>On changes to the content of the above editor, a (crude) script
          tries to auto-detect the language used, and switches the editor to
          either JavaScript or Scheme mode based on that.</p>
          
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              mode: "scheme",
              lineNumbers: true
            });
            var pending;
            editor.on("change", function() {
              clearTimeout(pending);
              pending = setTimeout(update, 400);
            });
            function looksLikeScheme(code) {
              return !/^\s*\(\s*function\b/.test(code) && /^\s*[;\(]/.test(code);
            }
            function update() {
              editor.setOption("mode", looksLikeScheme(editor.getValue()) ? "scheme" : "javascript");
            }
          </script>
            </article>
          
        • closebrackets.html
          <!doctype html>
          
          <title>CodeMirror: Closebrackets Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/closebrackets.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Closebrackets</a>
            </ul>
          </div>
          
          <article>
          <h2>Closebrackets Demo</h2>
          <form><textarea id="code" name="code">function Grid(width, height) {
            this.width = width;
            this.height = height;
            this.cells = new Array(width * height);
          }
          Grid.prototype.valueAt = function(point) {
            return this.cells[point.y * this.width + point.x];
          };
          Grid.prototype.setValueAt = function(point, value) {
            this.cells[point.y * this.width + point.x] = value;
          };
          Grid.prototype.isInside = function(point) {
            return point.x >= 0 && point.y >= 0 &&
                   point.x < this.width && point.y < this.height;
          };
          Grid.prototype.moveValue = function(from, to) {
            this.setValueAt(to, this.valueAt(from));
            this.setValueAt(from, undefined);
          };</textarea></form>
          
              <script type="text/javascript">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {autoCloseBrackets: true});
              </script>
            </article>
          
        • closetag.html
          <!doctype html>
          
          <title>CodeMirror: Close-Tag Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/closetag.js"></script>
          <script src="../addon/fold/xml-fold.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Close-Tag</a>
            </ul>
          </div>
          
          <article>
          <h2>Close-Tag Demo</h2>
          <form><textarea id="code" name="code"><html</textarea></form>
          
              <script type="text/javascript">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: 'text/html',
                  autoCloseTags: true
                });
              </script>
            </article>
          
        • complete.html
          <!doctype html>
          
          <title>CodeMirror: Autocomplete Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/javascript-hint.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Autocomplete</a>
            </ul>
          </div>
          
          <article>
          <h2>Autocomplete Demo</h2>
          <form><textarea id="code" name="code">
          function getCompletions(token, context) {
            var found = [], start = token.string;
            function maybeAdd(str) {
              if (str.indexOf(start) == 0) found.push(str);
            }
            function gatherCompletions(obj) {
              if (typeof obj == "string") forEach(stringProps, maybeAdd);
              else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
              else if (obj instanceof Function) forEach(funcProps, maybeAdd);
              for (var name in obj) maybeAdd(name);
            }
          
            if (context) {
              // If this is a property, see if it belongs to some object we can
              // find in the current environment.
              var obj = context.pop(), base;
              if (obj.className == "js-variable")
                base = window[obj.string];
              else if (obj.className == "js-string")
                base = "";
              else if (obj.className == "js-atom")
                base = 1;
              while (base != null && context.length)
                base = base[context.pop().string];
              if (base != null) gatherCompletions(base);
            }
            else {
              // If not, just look in the window object and any local scope
              // (reading into JS mode internals to get at the local variables)
              for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
              gatherCompletions(window);
              forEach(keywords, maybeAdd);
            }
            return found;
          }
          </textarea></form>
          
          <p>Press <strong>ctrl-space</strong> to activate autocompletion. Built
          on top of the <a href="../doc/manual.html#addon_show-hint"><code>show-hint</code></a>
          and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
          addons.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  extraKeys: {"Ctrl-Space": "autocomplete"},
                  mode: {name: "javascript", globalVars: true}
                });
              </script>
            </article>
          
        • emacs.html
          <!doctype html>
          
          <title>CodeMirror: Emacs bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <script src="../keymap/emacs.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Emacs bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Emacs bindings demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
            static char buf[BUFSIZ];
            static char *bufp = buf;
            static int n = 0;
            if (n == 0) {  /* buffer is empty */
              n = read(0, buf, sizeof buf);
              bufp = buf;
            }
            return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          
          <p>The emacs keybindings are enabled by
          including <a href="../keymap/emacs.js">keymap/emacs.js</a> and setting
          the <code>keyMap</code> option to <code>"emacs"</code>. Because
          CodeMirror's internal API is quite different from Emacs, they are only
          a loose approximation of actual emacs bindings, though.</p>
          
          <p>Also note that a lot of browsers disallow certain keys from being
          captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the
          result that idiomatic use of Emacs keys will constantly close your tab
          or open a new window.</p>
          
              <script>
                CodeMirror.commands.save = function() {
                  var elt = editor.getWrapperElement();
                  elt.style.background = "#def";
                  setTimeout(function() { elt.style.background = ""; }, 300);
                };
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  mode: "text/x-csrc",
                  keyMap: "emacs"
                });
              </script>
          
            </article>
          
        • folding.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: Code Folding Demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/fold/foldgutter.css" />
            <script src="../lib/codemirror.js"></script>
            <script src="../addon/fold/foldcode.js"></script>
            <script src="../addon/fold/foldgutter.js"></script>
            <script src="../addon/fold/brace-fold.js"></script>
            <script src="../addon/fold/xml-fold.js"></script>
            <script src="../addon/fold/markdown-fold.js"></script>
            <script src="../addon/fold/comment-fold.js"></script>
            <script src="../mode/javascript/javascript.js"></script>
            <script src="../mode/xml/xml.js"></script>
            <script src="../mode/markdown/markdown.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
          </head>
          
          <body>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Code Folding</a>
            </ul>
          </div>
          
          <article>
            <h2>Code Folding Demo</h2>
            <form>
              <div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br>
              <textarea id="code" name="code"></textarea></div>
              <div style="max-width: 50em; margin-bottom: 1em">HTML:<br>
              <textarea id="code-html" name="code-html"></textarea></div>
              <div style="max-width: 50em">Markdown:<br>
              <textarea id="code-markdown" name="code"></textarea></div>
            </form>
            <script id="script">
          /*
           * Demonstration of code folding
           */
          window.onload = function() {
            var te = document.getElementById("code");
            var sc = document.getElementById("script");
            te.value = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "");
            sc.innerHTML = "";
            var te_html = document.getElementById("code-html");
            te_html.value = document.documentElement.innerHTML;
            var te_markdown = document.getElementById("code-markdown");
            te_markdown.value = "# Foo\n## Bar\n\nblah blah\n\n## Baz\n\nblah blah\n\n# Quux\n\nblah blah\n"
          
            window.editor = CodeMirror.fromTextArea(te, {
              mode: "javascript",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
            editor.foldCode(CodeMirror.Pos(13, 0));
          
            window.editor_html = CodeMirror.fromTextArea(te_html, {
              mode: "text/html",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
            editor_html.foldCode(CodeMirror.Pos(0, 0));
            editor_html.foldCode(CodeMirror.Pos(21, 0));
          
            window.editor_markdown = CodeMirror.fromTextArea(te_markdown, {
              mode: "markdown",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
          };
            </script>
          </article>
          </body>
          
        • fullscreen.html
          <!doctype html>
          
          <title>CodeMirror: Full Screen Editing</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/display/fullscreen.css">
          <link rel="stylesheet" href="../theme/night.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/display/fullscreen.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Full Screen Editing</a>
            </ul>
          </div>
          
          <article>
          <h2>Full Screen Editing</h2>
          <form><textarea id="code" name="code" rows="5">
          <dl>
            <dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
            <dd>Whether, when indenting, the first N*<code>tabSize</code>
            spaces should be replaced by N tabs. Default is false.</dd>
          
            <dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
            <dd>Configures whether the editor should re-indent the current
            line when a character is typed that might change its proper
            indentation (only works if the mode supports indentation).
            Default is true.</dd>
          
            <dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
            <dd>A regular expression used to determine which characters
            should be replaced by a
            special <a href="#option_specialCharPlaceholder">placeholder</a>.
            Mostly useful for non-printing special characters. The default
            is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
            <dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
            <dd>A function that, given a special character identified by
            the <a href="#option_specialChars"><code>specialChars</code></a>
            option, produces a DOM node that is used to represent the
            character. By default, a red dot (<span style="color: red">•</span>)
            is shown, with a title tooltip to indicate the character code.</dd>
          
            <dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
            <dd>Determines whether horizontal cursor movement through
            right-to-left (Arabic, Hebrew) text is visual (pressing the left
            arrow moves the cursor left) or logical (pressing the left arrow
            moves to the next lower index in the string, which is visually
            right in right-to-left text). The default is <code>false</code>
            on Windows, and <code>true</code> on other platforms.</dd>
          </dl>
          </textarea></form>
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                theme: "night",
                extraKeys: {
                  "F11": function(cm) {
                    cm.setOption("fullScreen", !cm.getOption("fullScreen"));
                  },
                  "Esc": function(cm) {
                    if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
                  }
                }
              });
            </script>
          
              <p>Demonstration of
              the <a href="../doc/manual.html#addon_fullscreen">fullscreen</a>
              addon. Press <strong>F11</strong> when cursor is in the editor to
              toggle full screen editing. <strong>Esc</strong> can also be used
              to <i>exit</i> full screen editing.</p>
            </article>
          
        • hardwrap.html
          <!doctype html>
          
          <title>CodeMirror: Hard-wrapping Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../addon/wrap/hardwrap.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Hard-wrapping</a>
            </ul>
          </div>
          
          <article>
          <h2>Hard-wrapping Demo</h2>
          <form><textarea id="code" name="code">Lorem ipsum dolor sit amet, vim augue dictas constituto ex,
          sit falli simul viderer te. Graeco scaevola maluisset sit
          ut, in idque viris praesent sea. Ea sea eirmod indoctum
          repudiare. Vel noluisse suscipit pericula ut. In ius nulla
          alienum molestie. Mei essent discere democritum id.
          
          Equidem ponderum expetendis ius in, mea an erroribus
          constituto, congue timeam perfecto ad est. Ius ut primis
          timeam, per in ullum mediocrem. An case vero labitur pri,
          vel dicit laoreet et. An qui prompta conclusionemque, eam
          timeam sapientem in, cum dictas epicurei eu.
          
          Usu cu vide dictas deseruisse, eum choro graece adipiscing
          ut. Cibo qualisque ius ad, et dicat scripta mea, eam nihil
          mentitum aliquando cu. Debet aperiam splendide at quo, ad
          paulo nostro commodo duo. Sea adhuc utinam conclusionemque
          id, quas doming malorum nec ad. Tollit eruditi vivendum ad
          ius, eos soleat ignota ad.
          </textarea></form>
          
          <p>Demonstration of
          the <a href="../doc/manual.html#addon_hardwrap">hardwrap</a> addon.
          The above editor has its change event hooked up to
          the <code>wrapParagraphsInRange</code> method, so that the paragraphs
          are reflown as you are typing.</p>
          
          <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "markdown",
            lineNumbers: true,
            extraKeys: {
              "Ctrl-Q": function(cm) { cm.wrapParagraph(cm.getCursor(), options); }
            }
          });
          var wait, options = {column: 60};
          editor.on("change", function(cm, change) {
            clearTimeout(wait);
            wait = setTimeout(function() {
              console.log(cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options));
            }, 200);
          });
          </script>
          
          </article>
          
        • html5complete.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: HTML completion demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/hint/show-hint.css">
            <script src="../lib/codemirror.js"></script>
            <script src="../addon/hint/show-hint.js"></script>
            <script src="../addon/hint/xml-hint.js"></script>
            <script src="../addon/hint/html-hint.js"></script>
            <script src="../mode/xml/xml.js"></script>
            <script src="../mode/javascript/javascript.js"></script>
            <script src="../mode/css/css.js"></script>
            <script src="../mode/htmlmixed/htmlmixed.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
            </style>
          </head>
          
          <body>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
              <ul>
                <li><a href="../index.html">Home</a>
                <li><a href="../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a class=active href="#">HTML completion</a>
              </ul>
            </div>
          
            <article>
              <h2>HTML completion demo</h2>
          
              <p>Shows the <a href="xmlcomplete.html">XML completer</a>
              parameterized with information about the tags in HTML.
              Press <strong>ctrl-space</strong> to activate completion.</p>
          
              <div id="code"></div>
          
              <script type="text/javascript">
                window.onload = function() {
                  editor = CodeMirror(document.getElementById("code"), {
                    mode: "text/html",
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                    value: document.documentElement.innerHTML
                  });
                };
              </script>
            </article>
          </body>
          
        • indentwrap.html
          <!doctype html>
          
          <title>CodeMirror: Indented wrapped line demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror pre > * { text-indent: 0px; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Indented wrapped line</a>
            </ul>
          </div>
          
          <article>
          <h2>Indented wrapped line demo</h2>
          <form><textarea id="code" name="code">
          <!doctype html>
          <body>
            <h2 id="overview">Overview</h2>
          
            <p>CodeMirror is a code-editor component that can be embedded in Web pages. The core library provides <em>only</em> the editor component, no accompanying buttons, auto-completion, or other IDE functionality. It does provide a rich API on top of which such functionality can be straightforwardly implemented. See the <a href="#addons">add-ons</a> included in the distribution, and the <a href="https://github.com/jagthedrummer/codemirror-ui">CodeMirror UI</a> project, for reusable implementations of extra features.</p>
          
            <p>CodeMirror works with language-specific modes. Modes are JavaScript programs that help color (and optionally indent) text written in a given language. The distribution comes with a number of modes (see the <a href="../mode/"><code>mode/</code></a> directory), and it isn't hard to <a href="#modeapi">write new ones</a> for other languages.</p>
          </body>
          </textarea></form>
          
              <p>This page uses a hack on top of the <code>"renderLine"</code>
              event to make wrapped text line up with the base indentation of
              the line.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  lineWrapping: true,
                  mode: "text/html"
                });
                var charWidth = editor.defaultCharWidth(), basePadding = 4;
                editor.on("renderLine", function(cm, line, elt) {
                  var off = CodeMirror.countColumn(line.text, null, cm.getOption("tabSize")) * charWidth;
                  elt.style.textIndent = "-" + off + "px";
                  elt.style.paddingLeft = (basePadding + off) + "px";
                });
                editor.refresh();
              </script>
          
            </article>
          
        • lint.html
          <!doctype html>
          
          <title>CodeMirror: Linter Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/lint/lint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
          <script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>
          <script src="https://rawgithub.com/stubbornella/csslint/master/release/csslint.js"></script>
          <script src="../addon/lint/lint.js"></script>
          <script src="../addon/lint/javascript-lint.js"></script>
          <script src="../addon/lint/json-lint.js"></script>
          <script src="../addon/lint/css-lint.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Linter</a>
            </ul>
          </div>
          
          <article>
          <h2>Linter Demo</h2>
          
          
              <p><textarea id="code-js">var widgets = []
          function updateHints() {
            editor.operation(function(){
              for (var i = 0; i < widgets.length; ++i)
                editor.removeLineWidget(widgets[i]);
              widgets.length = 0;
          
              JSHINT(editor.getValue());
              for (var i = 0; i < JSHINT.errors.length; ++i) {
                var err = JSHINT.errors[i];
                if (!err) continue;
                var msg = document.createElement("div");
                var icon = msg.appendChild(document.createElement("span"));
                icon.innerHTML = "!!";
                icon.className = "lint-error-icon";
                msg.appendChild(document.createTextNode(err.reason));
                msg.className = "lint-error";
                widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
              }
            });
            var info = editor.getScrollInfo();
            var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
            if (info.top + info.clientHeight < after)
              editor.scrollTo(null, after - info.clientHeight + 3);
          }
          </textarea></p>
          
              <p><textarea id="code-json">[
           {
            _id: "post 1",
            "author": "Bob",
            "content": "...",
            "page_views": 5
           },
           {
            "_id": "post 2",
            "author": "Bob",
            "content": "...",
            "page_views": 9
           },
           {
            "_id": "post 3",
            "author": "Bob",
            "content": "...",
            "page_views": 8
           }
          ]
          </textarea></p>
          
              <p><textarea id="code-css">@charset "UTF-8";
          
          @import url("booya.css") print, screen;
          @import "whatup.css" screen;
          @import "wicked.css";
          
          /*Error*/
          @charset "UTF-8";
          
          
          @namespace "http://www.w3.org/1999/xhtml";
          @namespace svg "http://www.w3.org/2000/svg";
          
          /*Warning: empty ruleset */
          .foo {
          }
          
          h1 {
              font-weight: bold;
          }
          
          /*Warning: qualified heading */
          .foo h1 {
              font-weight: bold;
          }
          
          /*Warning: adjoining classes */
          .foo.bar {
              zoom: 1;
          }
          
          li.inline {
              width: 100%;  /*Warning: 100% can be problematic*/
          }
          
          li.last {
            display: inline;
            padding-left: 3px !important;
            padding-right: 3px;
            border-right: 0px;
          }
          
          @media print {
              li.inline {
                color: black;
              }
          }
          
          @page {
            margin: 10%;
            counter-increment: page;
          
            @top-center {
              font-family: sans-serif;
              font-weight: bold;
              font-size: 2em;
              content: counter(page);
            }
          }
          </textarea></p>
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code-js"), {
              lineNumbers: true,
              mode: "javascript",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
          
            var editor_json = CodeMirror.fromTextArea(document.getElementById("code-json"), {
              lineNumbers: true,
              mode: "application/json",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
            
            var editor_css = CodeMirror.fromTextArea(document.getElementById("code-css"), {
              lineNumbers: true,
              mode: "css",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
          </script>
          
            </article>
          
        • loadmode.html
          <!doctype html>
          
          <title>CodeMirror: Lazy Mode Loading Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/loadmode.js"></script>
          <script src="../mode/meta.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Lazy Mode Loading</a>
            </ul>
          </div>
          
          <article>
          <h2>Lazy Mode Loading Demo</h2>
          <p style="color: gray">Current mode: <span id="modeinfo">text/plain</span></p>
          <form><textarea id="code" name="code">This is the editor.
          // It starts out in plain text mode,
          #  use the control below to load and apply a mode
            "you'll see the highlighting of" this text /*change*/.
          </textarea></form>
          <p>Filename, mime, or mode name: <input type=text value=foo.js id=mode> <button type=button onclick="change()">change mode</button></p>
          
              <script>
          CodeMirror.modeURL = "../mode/%N/%N.js";
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true
          });
          var modeInput = document.getElementById("mode");
          CodeMirror.on(modeInput, "keypress", function(e) {
            if (e.keyCode == 13) change();
          });
          function change() {
            var val = modeInput.value, m, mode, spec;
            if (m = /.+\.([^.]+)$/.exec(val)) {
              var info = CodeMirror.findModeByExtension(m[1]);
              if (info) {
                mode = info.mode;
                spec = info.mime;
              }
            } else if (/\//.test(val)) {
              var info = CodeMirror.findModeByMIME(val);
              if (info) {
                mode = info.mode;
                spec = val;
              }
            } else {
              mode = spec = val;
            }
            if (mode) {
              editor.setOption("mode", spec);
              CodeMirror.autoLoadMode(editor, mode);
              document.getElementById("modeinfo").textContent = spec;
            } else {
              alert("Could not find a mode corresponding to " + val);
            }
          }
          </script>
            </article>
          
        • marker.html
          <!doctype html>
          
          <title>CodeMirror: Breakpoint Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <style type="text/css">
                .breakpoints {width: .8em;}
                .breakpoint { color: #822; }
                .CodeMirror {border: 1px solid #aaa;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Breakpoint</a>
            </ul>
          </div>
          
          <article>
          <h2>Breakpoint Demo</h2>
          <form><textarea id="code" name="code">
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            gutters: ["CodeMirror-linenumbers", "breakpoints"]
          });
          editor.on("gutterClick", function(cm, n) {
            var info = cm.lineInfo(n);
            cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
          });
          
          function makeMarker() {
            var marker = document.createElement("div");
            marker.style.color = "#822";
            marker.innerHTML = "●";
            return marker;
          }
          </textarea></form>
          
          <p>Click the line-number gutter to add or remove 'breakpoints'.</p>
          
              <script>eval(document.getElementById("code").value);</script>
          
            </article>
          
        • markselection.html
          <!doctype html>
          
          <title>CodeMirror: Selection Marking Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/selection/mark-selection.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror-selected  { background-color: blue !important; }
                .CodeMirror-selectedtext { color: white; }
                .styled-background { background-color: #ff7; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Selection Marking</a>
            </ul>
          </div>
          
          <article>
          <h2>Selection Marking Demo</h2>
          <form><textarea id="code" name="code">
          Select something from here. You'll see that the selection's foreground
          color changes to white! Since, by default, CodeMirror only puts an
          independent "marker" layer behind the text, you'll need something like
          this to change its colour.
          
          Also notice that turning this addon on (with the default style) allows
          you to safely give text a background color without screwing up the
          visibility of the selection.</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            styleSelectedText: true
          });
          editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});
          </script>
          
              <p>Simple addon to easily mark (and style) selected text. <a href="../doc/manual.html#addon_mark-selection">Docs</a>.</p>
          
            </article>
          
        • matchhighlighter.html
          <!doctype html>
          
          <title>CodeMirror: Match Highlighter Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/match-highlighter.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror-focused .cm-matchhighlight {
                  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
                  background-position: bottom;
                  background-repeat: repeat-x;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Match Highlighter</a>
            </ul>
          </div>
          
          <article>
          <h2>Match Highlighter Demo</h2>
          <form><textarea id="code" name="code">Select this text: hardToSpotVar
          	And everywhere else in your code where hardToSpotVar appears will automatically illuminate.
          Give it a try!  No more hardToSpotVars.</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            highlightSelectionMatches: {showToken: /\w/}
          });
          </script>
          
              <p>Search and highlight occurences of the selected text.</p>
          
            </article>
          
        • matchtags.html
          <!doctype html>
          
          <title>CodeMirror: Tag Matcher Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/fold/xml-fold.js"></script>
          <script src="../addon/edit/matchtags.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Tag Matcher</a>
            </ul>
          </div>
          
          <article>
          <h2>Tag Matcher Demo</h2>
          
          
              <div id="editor"></div>
          
              <script>
          window.onload = function() {
            editor = CodeMirror(document.getElementById("editor"), {
              value: "<html>\n  " + document.documentElement.innerHTML + "\n</html>",
              mode: "text/html",
              matchTags: {bothTags: true},
              extraKeys: {"Ctrl-J": "toMatchingTag"}
            });
          };
              </script>
          
              <p>Put the cursor on or inside a pair of tags to highlight them.
              Press Ctrl-J to jump to the tag that matches the one under the
              cursor.</p>
            </article>
          
        • merge.html
          <!doctype html>
          
          <title>CodeMirror: merge view demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel=stylesheet href="../lib/codemirror.css">
          <link rel=stylesheet href="../addon/merge/merge.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="//cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>
          <script src="../addon/merge/merge.js"></script>
          <style>
              .CodeMirror { line-height: 1.2; }
              @media screen and (min-width: 1300px) {
                article { max-width: 1000px; }
                #nav { border-right: 499px solid transparent; }
              }
              span.clicky {
                cursor: pointer;
                background: #d70;
                color: white;
                padding: 0 3px;
                border-radius: 3px;
              }
            </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">merge view</a>
            </ul>
          </div>
          
          <article>
          <h2>merge view demo</h2>
          
          
          <div id=view></div>
          
          <p>The <a href="../doc/manual.html#addon_merge"><code>merge</code></a>
          addon provides an interface for displaying and merging diffs,
          either <span class=clicky onclick="panes = 2; initUI()">two-way</span>
          or <span class=clicky onclick="panes = 3; initUI()">three-way</span>.
          The left (or center) pane is editable, and the differences with the
          other pane(s) are <span class=clicky
          onclick="toggleDifferences()">optionally</span> shown live as you edit
          it. In the two-way configuration, there are also options to pad changed
          sections to <span class=clicky onclick="connect = connect ? null :
          'align'; initUI()">align</span> them, and to <span class=clicky
          onclick="collapse = !collapse; initUI()">collapse</span> unchanged
          stretches of text.</p>
          
          <p>This addon depends on
          the <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a>
          library to compute the diffs.</p>
          
          <script>
          var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false;
          function initUI() {
            if (value == null) return;
            var target = document.getElementById("view");
            target.innerHTML = "";
            dv = CodeMirror.MergeView(target, {
              value: value,
              origLeft: panes == 3 ? orig1 : null,
              orig: orig2,
              lineNumbers: true,
              mode: "text/html",
              highlightDifferences: highlight,
              connect: connect,
              collapseIdentical: collapse
            });
          }
          
          function toggleDifferences() {
            dv.setShowDifferences(highlight = !highlight);
          }
          
          window.onload = function() {
            value = document.documentElement.innerHTML;
            orig1 = "<!doctype html>\n\n" + value.replace(/\.\.\//g, "codemirror/").replace("yellow", "orange");
            orig2 = value.replace(/\u003cscript/g, "\u003cscript type=text/javascript ")
              .replace("white", "purple;\n      font: comic sans;\n      text-decoration: underline;\n      height: 15em");
            initUI();
          };
          
          function mergeViewHeight(mergeView) {
            function editorHeight(editor) {
              if (!editor) return 0;
              return editor.getScrollInfo().height;
            }
            return Math.max(editorHeight(mergeView.leftOriginal()),
                            editorHeight(mergeView.editor()),
                            editorHeight(mergeView.rightOriginal()));
          }
          
          function resize(mergeView) {
            var height = mergeViewHeight(mergeView);
            for(;;) {
              if (mergeView.leftOriginal())
                mergeView.leftOriginal().setSize(null, height);
              mergeView.editor().setSize(null, height);
              if (mergeView.rightOriginal())
                mergeView.rightOriginal().setSize(null, height);
          
              var newHeight = mergeViewHeight(mergeView);
              if (newHeight >= height) break;
              else height = newHeight;
            }
            mergeView.wrap.style.height = height + "px";
          }
          </script>
          </article>
          
        • multiplex.html
          <!doctype html>
          
          <title>CodeMirror: Multiplexing Parser Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/multiplex.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .cm-delimit {color: #fa4;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Multiplexing Parser</a>
            </ul>
          </div>
          
          <article>
          <h2>Multiplexing Parser Demo</h2>
          <form><textarea id="code" name="code">
          <html>
            <body style="<<magic>>">
              <h1><< this is not <html >></h1>
              <<
                  multiline
                  not html
                  at all : &amp;amp; <link/>
              >>
              <p>this is html again</p>
            </body>
          </html>
          </textarea></form>
          
              <script>
          CodeMirror.defineMode("demo", function(config) {
            return CodeMirror.multiplexingMode(
              CodeMirror.getMode(config, "text/html"),
              {open: "<<", close: ">>",
               mode: CodeMirror.getMode(config, "text/plain"),
               delimStyle: "delimit"}
              // .. more multiplexed styles can follow here
            );
          });
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "demo",
            lineNumbers: true,
            lineWrapping: true
          });
          </script>
          
              <p>Demonstration of a multiplexing mode, which, at certain
              boundary strings, switches to one or more inner modes. The out
              (HTML) mode does not get fed the content of the <code>&lt;&lt;
              >></code> blocks. See
              the <a href="../doc/manual.html#addon_multiplex">manual</a> and
              the <a href="../addon/mode/multiplex.js">source</a> for more
              information.</p>
          
              <p>
                <strong>Parsing/Highlighting Tests:</strong>
                <a href="../test/index.html#multiplexing_*">normal</a>,
                <a href="../test/index.html#verbose,multiplexing_*">verbose</a>.
              </p>
          
            </article>
          
        • mustache.html
          <!doctype html>
          
          <title>CodeMirror: Overlay Parser Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/overlay.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .cm-mustache {color: #0ca;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Overlay Parser</a>
            </ul>
          </div>
          
          <article>
          <h2>Overlay Parser Demo</h2>
          <form><textarea id="code" name="code">
          <html>
            <body>
              <h1>{{title}}</h1>
              <p>These are links to {{things}}:</p>
              <ul>{{#links}}
                <li><a href="{{url}}">{{text}}</a></li>
              {{/links}}</ul>
            </body>
          </html>
          </textarea></form>
          
              <script>
          CodeMirror.defineMode("mustache", function(config, parserConfig) {
            var mustacheOverlay = {
              token: function(stream, state) {
                var ch;
                if (stream.match("{{")) {
                  while ((ch = stream.next()) != null)
                    if (ch == "}" && stream.next() == "}") {
                      stream.eat("}");
                      return "mustache";
                    }
                }
                while (stream.next() != null && !stream.match("{{", false)) {}
                return null;
              }
            };
            return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), mustacheOverlay);
          });
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "mustache"});
          </script>
          
              <p>Demonstration of a mode that parses HTML, highlighting
              the <a href="http://mustache.github.com/">Mustache</a> templating
              directives inside of it by using the code
              in <a href="../addon/mode/overlay.js"><code>overlay.js</code></a>. View
              source to see the 15 lines of code needed to accomplish this.</p>
          
            </article>
          
        • panel.html
          <!doctype html>
          
          <title>CodeMirror: Panel Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../addon/display/panel.js"></script>
          <style type="text/css">
            .border {border: 1px solid black; border-bottom: 1px solid black;}
            .add { background: orange; padding: 1px 3px; color: white !important; border-radius: 4px; }
            .panel {
              background-image: linear-gradient(to bottom, #ffffaa, #ffffdd);
              padding: 3px 7px;
            }
            .panel.top { border-bottom: 1px solid #dd6; }
            .panel.bottom { border-top: 1px solid #dd6; }
            .panel span { cursor: pointer; }
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Panel</a>
            </ul>
          </div>
          
          <article>
          <h2>Panel Demo</h2>
          <form><div class="border"><textarea id="code" name="code"></textarea></div></form>
          
          <script id="localscript">var textarea = document.getElementById("code");
          var script = document.getElementById("localscript");
          textarea.value = (script.textContent ||
                            script.innerText ||
                            script.innerHTML);
          editor = CodeMirror.fromTextArea(textarea, {
            lineNumbers: true
          });
          
          function addPanel(where) {
            var node = document.createElement("div");
            node.className = "panel " + where;
            var close = node.appendChild(document.createElement("span"));
            close.textContent = "✖ Remove this panel";
            var widget = editor.addPanel(node, {position: where});
            CodeMirror.on(close, "click", function() { widget.clear(); });
          }</script>
          
          <p>The <a href="../doc/manual.html#addon_panel"><code>panel</code></a>
          addon allows you to display panels <a class=add
          href="javascript:addPanel('top')">above</a> or <a class=add
          href="javascript:addPanel('bottom')">below</a> an editor. Click the
          links in the previous paragraph to add panels to the editor.</p>
          
          </article>
          
        • placeholder.html
          <!doctype html>
          
          <title>CodeMirror: Placeholder demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/display/placeholder.js"></script>
          <style type="text/css">
                .CodeMirror { border: 1px solid silver; }
                .CodeMirror-empty { outline: 1px solid #c22; }
                .CodeMirror-empty.CodeMirror-focused { outline: none; }
                .CodeMirror pre.CodeMirror-placeholder { color: #999; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Placeholder</a>
            </ul>
          </div>
          
          <article>
          <h2>Placeholder demo</h2>
          <form><textarea id="code" name="code" placeholder="Code goes here..."></textarea></form>
          
              <p>The <a href="../doc/manual.html#addon_placeholder">placeholder</a>
              plug-in adds an option <code>placeholder</code> that can be set to
              make text appear in the editor when it is empty and not focused.
              If the source textarea has a <code>placeholder</code> attribute,
              it will automatically be inherited.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true
                });
              </script>
          
            </article>
          
        • preview.html
          <!doctype html>
          
          <title>CodeMirror: HTML5 preview</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel=stylesheet href=../lib/codemirror.css>
          <script src=../lib/codemirror.js></script>
          <script src=../mode/xml/xml.js></script>
          <script src=../mode/javascript/javascript.js></script>
          <script src=../mode/css/css.js></script>
          <script src=../mode/htmlmixed/htmlmixed.js></script>
          <style type=text/css>
                .CodeMirror {
                  float: left;
                  width: 50%;
                  border: 1px solid black;
                }
                iframe {
                  width: 49%;
                  float: left;
                  height: 300px;
                  border: 1px solid black;
                  border-left: 0px;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">HTML5 preview</a>
            </ul>
          </div>
          
          <article>
          <h2>HTML5 preview</h2>
          
              <textarea id=code name=code>
          <!doctype html>
          <html>
            <head>
              <meta charset=utf-8>
              <title>HTML5 canvas demo</title>
              <style>p {font-family: monospace;}</style>
            </head>
            <body>
              <p>Canvas pane goes here:</p>
              <canvas id=pane width=300 height=200></canvas>
              <script>
                var canvas = document.getElementById('pane');
                var context = canvas.getContext('2d');
          
                context.fillStyle = 'rgb(250,0,0)';
                context.fillRect(10, 10, 55, 50);
          
                context.fillStyle = 'rgba(0, 0, 250, 0.5)';
                context.fillRect(30, 30, 55, 50);
              </script>
            </body>
          </html></textarea>
              <iframe id=preview></iframe>
              <script>
                var delay;
                // Initialize CodeMirror editor with a nice html5 canvas demo.
                var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                  mode: 'text/html'
                });
                editor.on("change", function() {
                  clearTimeout(delay);
                  delay = setTimeout(updatePreview, 300);
                });
                
                function updatePreview() {
                  var previewFrame = document.getElementById('preview');
                  var preview =  previewFrame.contentDocument ||  previewFrame.contentWindow.document;
                  preview.open();
                  preview.write(editor.getValue());
                  preview.close();
                }
                setTimeout(updatePreview, 300);
              </script>
            </article>
          
        • requirejs.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: HTML completion demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/hint/show-hint.css">
            <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
            </style>
          </head>
          
          <body>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
              <ul>
                <li><a href="../index.html">Home</a>
                <li><a href="../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a class=active href="#">HTML completion</a>
              </ul>
            </div>
          
            <article>
              <h2>RequireJS module loading demo</h2>
          
              <p>This demo does the same thing as
              the <a href="html5complete.html">HTML5 completion demo</a>, but
              loads its dependencies
              with <a href="http://requirejs.org/">Require.js</a>, rather than
              explicitly. Press <strong>ctrl-space</strong> to activate
              completion.</p>
          
              <div id="code"></div>
          
              <script type="text/javascript">
                require(["../lib/codemirror", "../mode/htmlmixed/htmlmixed",
                         "../addon/hint/show-hint", "../addon/hint/html-hint"], function(CodeMirror) {
                  editor = CodeMirror(document.getElementById("code"), {
                    mode: "text/html",
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                    value: document.documentElement.innerHTML
                  });
                });
              </script>
            </article>
          </body>
          
        • resize.html
          <!doctype html>
          
          <title>CodeMirror: Autoresize Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/css/css.js"></script>
          <style type="text/css">
                .CodeMirror {
                  border: 1px solid #eee;
                  height: auto;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Autoresize</a>
            </ul>
          </div>
          
          <article>
          <h2>Autoresize Demo</h2>
          <form><textarea id="code" name="code">
          .CodeMirror {
            border: 1px solid #eee;
            height: auto;
          }
          </textarea></form>
          
          <p>By setting an editor's <code>height</code> style
          to <code>auto</code> and giving
          the <a href="../doc/manual.html#option_viewportMargin"><code>viewportMargin</code></a>
          a value of <code>Infinity</code>, CodeMirror can be made to
          automatically resize to fit its content.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  viewportMargin: Infinity
                });
              </script>
          
            </article>
          
        • rulers.html
          <!doctype html>
          
          <title>CodeMirror: Ruler Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/display/rulers.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Ruler demo</a>
            </ul>
          </div>
          
          <article>
          <h2>Ruler Demo</h2>
          
          <script type="text/javascript">
            var nums = "0123456789", space = "          ";
            var colors = ["#fcc", "#f5f577", "#cfc", "#aff", "#ccf", "#fcf"];
            var rulers = [], value = "";
            for (var i = 1; i <= 6; i++) {
              rulers.push({color: colors[i], column: i * 10, lineStyle: "dashed"});
              for (var j = 1; j < i; j++) value += space;
              value += nums + "\n";
            }
            var editor = CodeMirror(document.body.lastChild, {
              rulers: rulers,
              value: value + value + value,
              lineNumbers: true
          });
          </script>
          
          <p>Demonstration of
          the <a href="../doc/manual.html#addon_rulers">rulers</a> addon, which
          displays vertical lines at given column offsets.</p>
          
          </article>
          
        • runmode.html
          <!doctype html>
          
          <title>CodeMirror: Mode Runner Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/runmode/runmode.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Mode Runner</a>
            </ul>
          </div>
          
          <article>
          <h2>Mode Runner Demo</h2>
          
          
              <textarea id="code" style="width: 90%; height: 7em; border: 1px solid black; padding: .2em .4em;">
          <foobar>
            <blah>Enter your xml here and press the button below to display
              it as highlighted by the CodeMirror XML mode</blah>
            <tag2 foo="2" bar="&amp;quot;bar&amp;quot;"/>
          </foobar></textarea><br>
              <button onclick="doHighlight();">Highlight!</button>
              <pre id="output" class="cm-s-default"></pre>
          
              <script>
          function doHighlight() {
            CodeMirror.runMode(document.getElementById("code").value, "application/xml",
                               document.getElementById("output"));
          }
          </script>
          
              <p>Running a CodeMirror mode outside of the editor.
              The <code>CodeMirror.runMode</code> function, defined
              in <code><a href="../addon/runmode/runmode.js">lib/runmode.js</a></code> takes the following arguments:</p>
          
              <dl>
                <dt><code>text (string)</code></dt>
                <dd>The document to run through the highlighter.</dd>
                <dt><code>mode (<a href="../doc/manual.html#option_mode">mode spec</a>)</code></dt>
                <dd>The mode to use (must be loaded as normal).</dd>
                <dt><code>output (function or DOM node)</code></dt>
                <dd>If this is a function, it will be called for each token with
                two arguments, the token's text and the token's style class (may
                be <code>null</code> for unstyled tokens). If it is a DOM node,
                the tokens will be converted to <code>span</code> elements as in
                an editor, and inserted into the node
                (through <code>innerHTML</code>).</dd>
              </dl>
          
            </article>
          
        • search.html
          <!doctype html>
          
          <title>CodeMirror: Search/Replace Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../addon/search/matchesonscrollbar.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <script src="../addon/scroll/annotatescrollbar.js"></script>
          <script src="../addon/search/matchesonscrollbar.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                dt {font-family: monospace; color: #666;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Search/Replace</a>
            </ul>
          </div>
          
          <article>
          <h2>Search/Replace Demo</h2>
          <form><textarea id="code" name="code">
          <dl>
            <dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
            <dd>Whether, when indenting, the first N*<code>tabSize</code>
            spaces should be replaced by N tabs. Default is false.</dd>
          
            <dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
            <dd>Configures whether the editor should re-indent the current
            line when a character is typed that might change its proper
            indentation (only works if the mode supports indentation).
            Default is true.</dd>
          
            <dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
            <dd>A regular expression used to determine which characters
            should be replaced by a
            special <a href="#option_specialCharPlaceholder">placeholder</a>.
            Mostly useful for non-printing special characters. The default
            is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
            <dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
            <dd>A function that, given a special character identified by
            the <a href="#option_specialChars"><code>specialChars</code></a>
            option, produces a DOM node that is used to represent the
            character. By default, a red dot (<span style="color: red">•</span>)
            is shown, with a title tooltip to indicate the character code.</dd>
          
            <dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
            <dd>Determines whether horizontal cursor movement through
            right-to-left (Arabic, Hebrew) text is visual (pressing the left
            arrow moves the cursor left) or logical (pressing the left arrow
            moves to the next lower index in the string, which is visually
            right in right-to-left text). The default is <code>false</code>
            on Windows, and <code>true</code> on other platforms.</dd>
          </dl>
          </textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "text/html",
            lineNumbers: true
          });
          </script>
          
              <p>Demonstration of primitive search/replace functionality. The
              keybindings (which can be overridden by custom keymaps) are:</p>
              <dl>
                <dt>Ctrl-F / Cmd-F</dt><dd>Start searching</dd>
                <dt>Ctrl-G / Cmd-G</dt><dd>Find next</dd>
                <dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd>
                <dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd>
                <dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd>
              </dl>
              <p>Searching is enabled by
              including <a href="../addon/search/search.js">addon/search/search.js</a>
              and <a href="../addon/search/searchcursor.js">addon/search/searchcursor.js</a>.
              For good-looking input dialogs, you also want to include
              <a href="../addon/dialog/dialog.js">addon/dialog/dialog.js</a>
              and <a href="../addon/dialog/dialog.css">addon/dialog/dialog.css</a>.</p>
            </article>
          
        • simplemode.html
          <!doctype html>
          
          <title>CodeMirror: Simple Mode Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/simple.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
            .CodeMirror {border: 1px solid silver; margin-bottom: 1em; }
            dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }
            dd { margin-left: 1.5em; margin-bottom: 1em; }
            dt {margin-top: 1em;}
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Simple Mode</a>
            </ul>
          </div>
          
          <article>
          <h2>Simple Mode Demo</h2>
          
          <p>The <a href="../addon/mode/simple.js"><code>mode/simple</code></a>
          addon allows CodeMirror modes to be specified using a relatively simple
          declarative format. This format is not as powerful as writing code
          directly against the <a href="../doc/manual.html#modeapi">mode
          interface</a>, but is a lot easier to get started with, and
          sufficiently expressive for many simple language modes.</p>
          
          <p>This interface is still in flux. It is unlikely to be scrapped or
          overhauled completely, so do start writing code against it, but
          details might change as it stabilizes, and you might have to tweak
          your code when upgrading.</p>
          
          <p>Simple modes (loosely based on
          the <a href="https://github.com/mozilla/skywriter/wiki/Common-JavaScript-Syntax-Highlighting-Specification">Common
          JavaScript Syntax Highlighting Specification</a>, which never took
          off), are state machines, where each state has a number of rules that
          match tokens. A rule describes a type of token that may occur in the
          current state, and possibly a transition to another state caused by
          that token.</p>
          
          <p>The <code>CodeMirror.defineSimpleMode(name, states)</code> method
          takes a mode name and an object that describes the mode's states. The
          editor below shows an example of such a mode (and is itself
          highlighted by the mode shown in it).</p>
          
          <div id="code"></div>
          
          <p>Each state is an array of rules. A rule may have the following properties:</p>
          
          <dl>
            <dt><code><strong>regex</strong>: string | RegExp</code></dt>
            <dd>The regular expression that matches the token. May be a string
            or a regex object. When a regex, the <code>ignoreCase</code> flag
            will be taken into account when matching the token. This regex
            should only capture groups when the <code>token</code> property is
            an array.</dd>
            <dt><code><strong>token</strong></code>: string | null</dt>
            <dd>An optional token style. Multiple styles can be specified by
            separating them with dots or spaces. When the <code>regex</code> for
            this rule captures groups, it must capture <em>all</em> of the
            string (since JS provides no way to find out where a group matched),
            and this property must hold an array of token styles that has one
            style for each matched group.</dd>
            <dt><code><strong>sol</strong></code>: boolean</dt>
            <dd>When true, this token will only match at the start of the line.
            (The <code>^</code> regexp marker doesn't work as you'd expect in
            this context because of limitations in JavaScript's RegExp
            API.)</dd>
            <dt><code><strong>next</strong>: string</code></dt>
            <dd>When a <code>next</code> property is present, the mode will
            transfer to the state named by the property when the token is
            encountered.</dd>
            <dt><code><strong>push</strong>: string</code></dt>
            <dd>Like <code>next</code>, but instead replacing the current state
            by the new state, the current state is kept on a stack, and can be
            returned to with the <code>pop</code> directive.</dd>
            <dt><code><strong>pop</strong>: bool</code></dt>
            <dd>When true, and there is another state on the state stack, will
            cause the mode to pop that state off the stack and transition to
            it.</dd>
            <dt><code><strong>mode</strong>: {spec, end, persistent}</code></dt>
            <dd>Can be used to embed another mode inside a mode. When present,
            must hold an object with a <code>spec</code> property that describes
            the embedded mode, and an optional <code>end</code> end property
            that specifies the regexp that will end the extent of the mode. When
            a <code>persistent</code> property is set (and true), the nested
            mode's state will be preserved between occurrences of the mode.</dd>
            <dt><code><strong>indent</strong>: bool</code></dt>
            <dd>When true, this token changes the indentation to be one unit
            more than the current line's indentation.</dd>
            <dt><code><strong>dedent</strong>: bool</code></dt>
            <dd>When true, this token will pop one scope off the indentation
            stack.</dd>
            <dt><code><strong>dedentIfLineStart</strong>: bool</code></dt>
            <dd>If a token has its <code>dedent</code> property set, it will, by
            default, cause lines where it appears at the start to be dedented.
            Set this property to false to prevent that behavior.</dd>
          </dl>
          
          <p>The <code>meta</code> property of the states object is special, and
          will not be interpreted as a state. Instead, properties set on it will
          be set on the mode, which is useful for properties
          like <a href="../doc/manual.html#addon_comment"><code>lineComment</code></a>,
          which sets the comment style for a mode. The simple mode addon also
          recognizes a few such properties:</p>
          
          <dl>
            <dt><code><strong>dontIndentStates</strong>: array&lt;string&gt;</code></dt>
            <dd>An array of states in which the mode's auto-indentation should
            not take effect. Usually used for multi-line comment and string
            states.</dd>
          </dl>
          
          <script id="modecode">/* Example definition of a simple mode that understands a subset of
           * JavaScript:
           */
          
          CodeMirror.defineSimpleMode("simplemode", {
            // The start state contains the rules that are intially used
            start: [
              // The regex matches the token, the token property contains the type
              {regex: /"(?:[^\\]|\\.)*?"/, token: "string"},
              // You can match multiple tokens at once. Note that the captured
              // groups must span the whole string in this case
              {regex: /(function)(\s+)([a-z$][\w$]*)/,
               token: ["keyword", null, "variable-2"]},
              // Rules are matched in the order in which they appear, so there is
              // no ambiguity between this one and the one above
              {regex: /(?:function|var|return|if|for|while|else|do|this)\b/,
               token: "keyword"},
              {regex: /true|false|null|undefined/, token: "atom"},
              {regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
               token: "number"},
              {regex: /\/\/.*/, token: "comment"},
              {regex: /\/(?:[^\\]|\\.)*?\//, token: "variable-3"},
              // A next property will cause the mode to move to a different state
              {regex: /\/\*/, token: "comment", next: "comment"},
              {regex: /[-+\/*=<>!]+/, token: "operator"},
              // indent and dedent properties guide autoindentation
              {regex: /[\{\[\(]/, indent: true},
              {regex: /[\}\]\)]/, dedent: true},
              {regex: /[a-z$][\w$]*/, token: "variable"},
              // You can embed other modes with the mode property. This rule
              // causes all code between << and >> to be highlighted with the XML
              // mode.
              {regex: /<</, token: "meta", mode: {spec: "xml", end: />>/}}
            ],
            // The multi-line comment state.
            comment: [
              {regex: /.*?\*\//, token: "comment", next: "start"},
              {regex: /.*/, token: "comment"}
            ],
            // The meta property contains global information about the mode. It
            // can contain properties like lineComment, which are supported by
            // all modes, and also directives like dontIndentStates, which are
            // specific to simple modes.
            meta: {
              dontIndentStates: ["comment"],
              lineComment: "//"
            }
          });
          </script>
          
          <script>
          var sc = document.getElementById("modecode");
          var code = document.getElementById("code");
          var editor = CodeMirror(code, {
            value: (sc.textContent || sc.innerText || sc.innerHTML),
            mode: "simplemode"
          });
          </script>
          
          </article>
          
        • simplescrollbars.html
          <!doctype html>
          
          <title>CodeMirror: Simple Scrollbar Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/scroll/simplescrollbars.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/scroll/simplescrollbars.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Simple Scrollbar</a>
            </ul>
          </div>
          
          <article>
          <h2>Simple Scrollbar Demo</h2>
          <form><textarea id="code" name="code"># Custom Scrollbars
          
          This is a piece of text that creates scrollbars
          
          Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,
          aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio
          dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,
          integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.
          Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget
          pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed
          fusce vel.
          
          Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget
          vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id
          sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus
          quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in
          vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque
          donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit
          est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis
          explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae
          curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.
          
          Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus
          turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere
          volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed
          eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.
          Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra
          tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit
          parturient augue interdum, mattis sit tellus.
          
          Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia
          id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,
          sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus
          enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,
          ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit
          augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,
          curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,
          maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati
          lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.
          </textarea></form>
          
          <p>The <a href="../doc/manual.html#addon_simplescrollbars"><code>simplescrollbars</code></a> addon defines two
          styles of non-native scrollbars: <a href="javascript:editor.setOption('scrollbarStyle', 'simple')"><code>"simple"</code></a> and <a href="javascript:editor.setOption('scrollbarStyle', 'overlay')"><code>"overlay"</code></a> (click to try), which can be passed to
          the <a href="../doc/manual.html#option_scrollbarStyle"><code>scrollbarStyle</code></a> option. These implement
          the scrollbar using DOM elements, allowing more control over
          its <a href="../addon/scroll/simplescrollbars.css">appearance</a>.</p>
          
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                scrollbarStyle: "simple"
              });
            </script>
          </article>
          
        • spanaffectswrapping_shim.html
          <!doctype html>
          
          <title>CodeMirror: Automatically derive odd wrapping behavior for your browser</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Automatically derive odd wrapping behavior for your browser</a>
            </ul>
          </div>
          
          <article>
          <h2>Automatically derive odd wrapping behavior for your browser</h2>
          
          
              <p>This is a hack to automatically derive
              a <code>spanAffectsWrapping</code> regexp for a browser. See the
              comments above that variable
              in <a href="../lib/codemirror.js"><code>lib/codemirror.js</code></a>
              for some more details.</p>
          
              <div style="white-space: pre-wrap; width: 50px;" id="area"></div>
              <pre id="output"></pre>
          
              <script id="script">
                var a = document.getElementById("area"), bad = Object.create(null);
                var chars = "a~`!@#$%^&*()-_=+}{[]\\|'\"/?.>,<:;", l = chars.length;
                for (var x = 0; x < l; ++x) for (var y = 0; y < l; ++y) {
                  var s1 = "foooo" + chars.charAt(x), s2 = chars.charAt(y) + "br";
                  a.appendChild(document.createTextNode(s1 + s2));
                  var h1 = a.offsetHeight;
                  a.innerHTML = "";
                  a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s1));
                  a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s2));
                  if (a.offsetHeight != h1)
                    bad[chars.charAt(x)] = (bad[chars.charAt(x)] || "") + chars.charAt(y);
                  a.innerHTML = "";
                }
          
                var re = "";
                function toREElt(str) {
                  if (str.length > 1) {
                    var invert = false;
                    if (str.length > chars.length * .6) {
                      invert = true;
                      var newStr = "";
                      for (var i = 0; i < l; ++i) if (str.indexOf(chars.charAt(i)) == -1) newStr += chars.charAt(i);
                      str = newStr;
                    }
                    str = str.replace(/[\-\.\]\"\'\\\/\^a]/g, function(orig) { return orig == "a" ? "\\w" : "\\" + orig; });
                    return "[" + (invert ? "^" : "") + str + "]";
                  } else if (str == "a") {
                    return "\\w";
                  } else if (/[?$*()+{}[\]\.|/\'\"]/.test(str)) {
                    return "\\" + str;
                  } else {
                    return str;
                  }
                }
          
                var newRE = "";
                for (;;) {
                  var left = null;
                  for (var left in bad) break;
                  if (left == null) break;
                  var right = bad[left];
                  delete bad[left];
                  for (var other in bad) if (bad[other] == right) {
                    left += other;
                    delete bad[other];
                  }
                  newRE += (newRE ? "|" : "") + toREElt(left) + toREElt(right);
                }
          
                document.getElementById("output").appendChild(document.createTextNode("Your regexp is: " + (newRE || "^$")));
              </script>
            </article>
          
        • sublime.html
          <!doctype html>
          
          <title>CodeMirror: Sublime Text bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/fold/foldgutter.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../theme/monokai.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/edit/closebrackets.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../addon/wrap/hardwrap.js"></script>
          <script src="../addon/fold/foldcode.js"></script>
          <script src="../addon/fold/brace-fold.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../keymap/sublime.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee; line-height: 1.3; height: 500px}
            .CodeMirror-linenumbers { padding: 0 8px; }
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Sublime bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Sublime Text bindings demo</h2>
          
          <p>The <code>sublime</code> keymap defines many Sublime Text-specific
          bindings for CodeMirror. See the code below for an overview.</p>
          
          <p>Enable the keymap by
          loading <a href="../keymap/sublime.js"><code>keymap/sublime.js</code></a>
          and setting
          the <a href="../doc/manual.html#option_keyMap"><code>keyMap</code></a>
          option to <code>"sublime"</code>.</p>
          
          <p>(A lot of the search functionality is still missing.)
          
          <script>
            var value = "// The bindings defined specifically in the Sublime Text mode\nvar bindings = {\n";
            var map = CodeMirror.keyMap.sublime;
            for (var key in map) {
              var val = map[key];
              if (key != "fallthrough" && val != "..." && (!/find/.test(val) || /findUnder/.test(val)))
                value += "  \"" + key + "\": \"" + val + "\",\n";
            }
            value += "}\n\n// The implementation of joinLines\n";
            value += CodeMirror.commands.joinLines.toString().replace(/^function\s*\(/, "function joinLines(").replace(/\n  /g, "\n") + "\n";
            var editor = CodeMirror(document.body.getElementsByTagName("article")[0], {
              value: value,
              lineNumbers: true,
              mode: "javascript",
              keyMap: "sublime",
              autoCloseBrackets: true,
              matchBrackets: true,
              showCursorWhenSelecting: true,
              theme: "monokai"
            });
          </script>
          
          </article>
          
        • tern.html
          <!doctype html>
          
          <title>CodeMirror: Tern Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <link rel="stylesheet" href="../addon/tern/tern.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/tern/tern.js"></script>
          <script src="http://marijnhaverbeke.nl/acorn/acorn.js"></script>
          <script src="http://marijnhaverbeke.nl/acorn/acorn_loose.js"></script>
          <script src="http://marijnhaverbeke.nl/acorn/util/walk.js"></script>
          <script src="http://ternjs.net/doc/demo/polyfill.js"></script>
          <script src="http://ternjs.net/lib/signal.js"></script>
          <script src="http://ternjs.net/lib/tern.js"></script>
          <script src="http://ternjs.net/lib/def.js"></script>
          <script src="http://ternjs.net/lib/comment.js"></script>
          <script src="http://ternjs.net/lib/infer.js"></script>
          <script src="http://ternjs.net/plugin/doc_comment.js"></script>
          <style>
                .CodeMirror {border: 1px solid #ddd;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Tern</a>
            </ul>
          </div>
          
          <article>
          <h2>Tern Demo</h2>
          <form><textarea id="code" name="code">// Use ctrl-space to complete something
          // Put the cursor in or after an expression, press ctrl-o to
          // find its type
          
          var foo = ["array", "of", "strings"];
          var bar = foo.slice(0, 2).join("").split("a")[0];
          
          // Works for locally defined types too.
          
          function CTor() { this.size = 10; }
          CTor.prototype.hallo = "hallo";
          
          var baz = new CTor;
          baz.
          
          // You can press ctrl-q when the cursor is on a variable name to
          // rename it. Try it with CTor...
          
          // When the cursor is in an argument list, the arguments are
          // shown below the editor.
          
          [1].reduce(  );
          
          // And a little more advanced code...
          
          (function(exports) {
            exports.randomElt = function(arr) {
              return arr[Math.floor(arr.length * Math.random())];
            };
            exports.strList = "foo".split("");
            exports.intList = exports.strList.map(function(s) { return s.charCodeAt(0); });
          })(window.myMod = {});
          
          var randomStr = myMod.randomElt(myMod.strList);
          var randomInt = myMod.randomElt(myMod.intList);
          </textarea></p>
          
          <p>Demonstrates integration of <a href="http://ternjs.net/">Tern</a>
          and CodeMirror. The following keys are bound:</p>
          
          <dl>
            <dt>Ctrl-Space</dt><dd>Autocomplete</dd>
            <dt>Ctrl-O</dt><dd>Find docs for the expression at the cursor</dd>
            <dt>Ctrl-I</dt><dd>Find type at cursor</dd>
            <dt>Alt-.</dt><dd>Jump to definition (Alt-, to jump back)</dd>
            <dt>Ctrl-Q</dt><dd>Rename variable</dd>
            <dt>Ctrl-.</dt><dd>Select all occurrences of a variable</dd>
          </dl>
          
          <p>Documentation is sparse for now. See the top of
          the <a href="../addon/tern/tern.js">script</a> for a rough API
          overview.</p>
          
          <script>
            function getURL(url, c) {
              var xhr = new XMLHttpRequest();
              xhr.open("get", url, true);
              xhr.send();
              xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) return;
                if (xhr.status < 400) return c(null, xhr.responseText);
                var e = new Error(xhr.responseText || "No response");
                e.status = xhr.status;
                c(e);
              };
            }
          
            var server;
            getURL("http://ternjs.net/defs/ecma5.json", function(err, code) {
              if (err) throw new Error("Request for ecma5.json: " + err);
              server = new CodeMirror.TernServer({defs: [JSON.parse(code)]});
              editor.setOption("extraKeys", {
                "Ctrl-Space": function(cm) { server.complete(cm); },
                "Ctrl-I": function(cm) { server.showType(cm); },
                "Ctrl-O": function(cm) { server.showDocs(cm); },
                "Alt-.": function(cm) { server.jumpToDef(cm); },
                "Alt-,": function(cm) { server.jumpBack(cm); },
                "Ctrl-Q": function(cm) { server.rename(cm); },
                "Ctrl-.": function(cm) { server.selectName(cm); }
              })
              editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); });
            });
          
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              mode: "javascript"
            });
          </script>
          
            </article>
          
        • theme.html
          <!doctype html>
          
          <title>CodeMirror: Theme Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../theme/3024-day.css">
          <link rel="stylesheet" href="../theme/3024-night.css">
          <link rel="stylesheet" href="../theme/ambiance.css">
          <link rel="stylesheet" href="../theme/base16-dark.css">
          <link rel="stylesheet" href="../theme/base16-light.css">
          <link rel="stylesheet" href="../theme/blackboard.css">
          <link rel="stylesheet" href="../theme/cobalt.css">
          <link rel="stylesheet" href="../theme/colorforth.css">
          <link rel="stylesheet" href="../theme/eclipse.css">
          <link rel="stylesheet" href="../theme/elegant.css">
          <link rel="stylesheet" href="../theme/erlang-dark.css">
          <link rel="stylesheet" href="../theme/lesser-dark.css">
          <link rel="stylesheet" href="../theme/mbo.css">
          <link rel="stylesheet" href="../theme/mdn-like.css">
          <link rel="stylesheet" href="../theme/midnight.css">
          <link rel="stylesheet" href="../theme/monokai.css">
          <link rel="stylesheet" href="../theme/neat.css">
          <link rel="stylesheet" href="../theme/neo.css">
          <link rel="stylesheet" href="../theme/night.css">
          <link rel="stylesheet" href="../theme/paraiso-dark.css">
          <link rel="stylesheet" href="../theme/paraiso-light.css">
          <link rel="stylesheet" href="../theme/pastel-on-dark.css">
          <link rel="stylesheet" href="../theme/rubyblue.css">
          <link rel="stylesheet" href="../theme/solarized.css">
          <link rel="stylesheet" href="../theme/the-matrix.css">
          <link rel="stylesheet" href="../theme/tomorrow-night-bright.css">
          <link rel="stylesheet" href="../theme/tomorrow-night-eighties.css">
          <link rel="stylesheet" href="../theme/twilight.css">
          <link rel="stylesheet" href="../theme/vibrant-ink.css">
          <link rel="stylesheet" href="../theme/xq-dark.css">
          <link rel="stylesheet" href="../theme/xq-light.css">
          <link rel="stylesheet" href="../theme/zenburn.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../addon/selection/active-line.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black; font-size:13px}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Theme</a>
            </ul>
          </div>
          
          <article>
          <h2>Theme Demo</h2>
          <form><textarea id="code" name="code">
          function findSequence(goal) {
            function find(start, history) {
              if (start == goal)
                return history;
              else if (start > goal)
                return null;
              else
                return find(start + 5, "(" + history + " + 5)") ||
                       find(start * 3, "(" + history + " * 3)");
            }
            return find(1, "1");
          }</textarea></form>
          
          <p>Select a theme: <select onchange="selectTheme()" id=select>
              <option selected>default</option>
              <option>3024-day</option>
              <option>3024-night</option>
              <option>ambiance</option>
              <option>base16-dark</option>
              <option>base16-light</option>
              <option>blackboard</option>
              <option>cobalt</option>
              <option>colorforth</option>
              <option>eclipse</option>
              <option>elegant</option>
              <option>erlang-dark</option>
              <option>lesser-dark</option>
              <option>mbo</option>
              <option>mdn-like</option>
              <option>midnight</option>
              <option>monokai</option>
              <option>neat</option>
              <option>neo</option>
              <option>night</option>
              <option>paraiso-dark</option>
              <option>paraiso-light</option>
              <option>pastel-on-dark</option>
              <option>rubyblue</option>
              <option>solarized dark</option>
              <option>solarized light</option>
              <option>the-matrix</option>
              <option>tomorrow-night-bright</option>
              <option>tomorrow-night-eighties</option>
              <option>twilight</option>
              <option>vibrant-ink</option>
              <option>xq-dark</option>
              <option>xq-light</option>
              <option>zenburn</option>
          </select>
          </p>
          
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              styleActiveLine: true,
              matchBrackets: true
            });
            var input = document.getElementById("select");
            function selectTheme() {
              var theme = input.options[input.selectedIndex].innerHTML;
              editor.setOption("theme", theme);
            }
            var choice = document.location.search &&
                         decodeURIComponent(document.location.search.slice(1));
            if (choice) {
              input.value = choice;
              editor.setOption("theme", choice);
            }
          </script>
            </article>
          
        • trailingspace.html
          <!doctype html>
          
          <title>CodeMirror: Trailing Whitespace Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/trailingspace.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .cm-trailingspace {
                  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);
                  background-position: bottom left;
                  background-repeat: repeat-x;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Trailing Whitespace</a>
            </ul>
          </div>
          
          <article>
          <h2>Trailing Whitespace Demo</h2>
          <form><textarea id="code" name="code">This text  
           has some	 
          trailing whitespace!</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            showTrailingSpace: true
          });
          </script>
          
          <p>Uses
          the <a href="../doc/manual.html#addon_trailingspace">trailingspace</a>
          addon to highlight trailing whitespace.</p>
          
            </article>
          
        • variableheight.html
          <!doctype html>
          
          <title>CodeMirror: Variable Height Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid silver; border-width: 1px 2px; }
                .cm-header { font-family: arial; }
                .cm-header-1 { font-size: 150%; }
                .cm-header-2 { font-size: 130%; }
                .cm-header-3 { font-size: 120%; }
                .cm-header-4 { font-size: 110%; }
                .cm-header-5 { font-size: 100%; }
                .cm-header-6 { font-size: 90%; }
                .cm-strong { font-size: 140%; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Variable Height</a>
            </ul>
          </div>
          
          <article>
          <h2>Variable Height Demo</h2>
          <form><textarea id="code" name="code"># A First Level Header
          
          **Bold** text in a normal-size paragraph.
          
          And a very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long, wrapped line with a piece of **big** text inside of it.
          
          ## A Second Level Header
          
          Now is the time for all good men to come to
          the aid of their country. This is just a
          regular paragraph.
          
          The quick brown fox jumped over the lazy
          dog's back.
          
          ### Header 3
          
          > This is a blockquote.
          > 
          > This is the second paragraph in the blockquote.
          >
          > ## This is an H2 in a blockquote       
          </textarea></form>
              <script id="script">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  lineWrapping: true,
                  mode: "markdown"
                });
              </script>
            </article>
          
        • vim.html
          <!doctype html>
          
          <title>CodeMirror: Vim bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../keymap/vim.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Vim bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Vim bindings demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
            static char buf[BUFSIZ];
            static char *bufp = buf;
            static int n = 0;
            if (n == 0) {  /* buffer is empty */
              n = read(0, buf, sizeof buf);
              bufp = buf;
            }
            return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          <div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div>
          
          <p>The vim keybindings are enabled by
          including <a href="../keymap/vim.js">keymap/vim.js</a> and setting
          the <code>vimMode</code> option to <code>true</code>. This will also
          automatically change the <code>keyMap</code> option to <code>"vim"</code>.</p>
          
          <p><strong>Features</strong></p>
          
          <ul>
            <li>All common motions and operators, including text objects</li>
            <li>Operator motion orthogonality</li>
            <li>Visual mode - characterwise, linewise, partial support for blockwise</li>
            <li>Full macro support (q, @)</li>
            <li>Incremental highlighted search (/, ?, #, *, g#, g*)</li>
            <li>Search/replace with confirm (:substitute, :%s)</li>
            <li>Search history</li>
            <li>Jump lists (Ctrl-o, Ctrl-i)</li>
            <li>Key/command mapping with API (:map, :nmap, :vmap)</li>
            <li>Sort (:sort)</li>
            <li>Marks (`, ')</li>
            <li>:global</li>
            <li>Insert mode behaves identical to base CodeMirror</li>
            <li>Cross-buffer yank/paste</li>
          </ul>
          
          <p>Note that while the vim mode tries to emulate the most useful features of
          vim as faithfully as possible, it does not strive to become a complete vim
          implementation</p>
          
              <script>
                CodeMirror.commands.save = function(){ alert("Saving"); };
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  mode: "text/x-csrc",
                  keyMap: "vim",
                  matchBrackets: true,
                  showCursorWhenSelecting: true
                });
                var commandDisplay = document.getElementById('command-display');
                var keys = '';
                CodeMirror.on(editor, 'vim-keypress', function(key) {
                  keys = keys + key;
                  commandDisplay.innerHTML = keys;
                });
                CodeMirror.on(editor, 'vim-command-done', function(e) {
                  keys = '';
                  commandDisplay.innerHTML = keys;
                });
              </script>
          
            </article>
          
        • visibletabs.html
          <!doctype html>
          
          <title>CodeMirror: Visible tabs demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
                .cm-tab {
                   background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
                   background-position: right;
                   background-repeat: no-repeat;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Visible tabs</a>
            </ul>
          </div>
          
          <article>
          <h2>Visible tabs demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
          	static char buf[BUFSIZ];
          	static char *bufp = buf;
          	static int n = 0;
          	if (n == 0) {  /* buffer is empty */
          		n = read(0, buf, sizeof buf);
          		bufp = buf;
          	}
          	return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          
          <p>Tabs inside the editor are spans with the
          class <code>cm-tab</code>, and can be styled.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  tabSize: 4,
                  indentUnit: 4,
                  indentWithTabs: true,
                  mode: "text/x-csrc"
                });
              </script>
          
            </article>
          
        • widget.html
          <!doctype html>
          
          <title>CodeMirror: Inline Widget Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .lint-error {font-family: arial; font-size: 70%; background: #ffa; color: #a00; padding: 2px 5px 3px; }
                .lint-error-icon {color: white; background-color: red; font-weight: bold; border-radius: 50%; padding: 0 3px; margin-right: 7px;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Inline Widget</a>
            </ul>
          </div>
          
          <article>
          <h2>Inline Widget Demo</h2>
          
          
              <div id=code></div>
              <script id="script">var widgets = []
          function updateHints() {
            editor.operation(function(){
              for (var i = 0; i < widgets.length; ++i)
                editor.removeLineWidget(widgets[i]);
              widgets.length = 0;
          
              JSHINT(editor.getValue());
              for (var i = 0; i < JSHINT.errors.length; ++i) {
                var err = JSHINT.errors[i];
                if (!err) continue;
                var msg = document.createElement("div");
                var icon = msg.appendChild(document.createElement("span"));
                icon.innerHTML = "!!";
                icon.className = "lint-error-icon";
                msg.appendChild(document.createTextNode(err.reason));
                msg.className = "lint-error";
                widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
              }
            });
            var info = editor.getScrollInfo();
            var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
            if (info.top + info.clientHeight < after)
              editor.scrollTo(null, after - info.clientHeight + 3);
          }
          
          window.onload = function() {
            var sc = document.getElementById("script");
            var content = sc.textContent || sc.innerText || sc.innerHTML;
          
            window.editor = CodeMirror(document.getElementById("code"), {
              lineNumbers: true,
              mode: "javascript",
              value: content
            });
          
            var waiting;
            editor.on("change", function() {
              clearTimeout(waiting);
              waiting = setTimeout(updateHints, 500);
            });
          
            setTimeout(updateHints, 100);
          };
          
          "long line to create a horizontal scrollbar, in order to test whether the (non-inline) widgets stay in place when scrolling to the right";
          </script>
          <p>This demo runs <a href="http://jshint.com">JSHint</a> over the code
          in the editor (which is the script used on this page), and
          inserts <a href="../doc/manual.html#addLineWidget">line widgets</a> to
          display the warnings that JSHint comes up with.</p>
            </article>
          
        • xmlcomplete.html
          <!doctype html>
          
          <title>CodeMirror: XML Autocomplete Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/xml-hint.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror { border: 1px solid #eee; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">XML Autocomplete</a>
            </ul>
          </div>
          
          <article>
          <h2>XML Autocomplete Demo</h2>
          <form><textarea id="code" name="code"><!-- write some xml below -->
          </textarea></form>
          
              <p>Press <strong>ctrl-space</strong>, or type a '<' character to
              activate autocompletion. This demo defines a simple schema that
              guides completion. The schema can be customized—see
              the <a href="../doc/manual.html#addon_xml-hint">manual</a>.</p>
          
              <p>Development of the <code>xml-hint</code> addon was kindly
              sponsored
              by <a href="http://www.xperiment.mobi">www.xperiment.mobi</a>.</p>
          
              <script>
                var dummy = {
                  attrs: {
                    color: ["red", "green", "blue", "purple", "white", "black", "yellow"],
                    size: ["large", "medium", "small"],
                    description: null
                  },
                  children: []
                };
          
                var tags = {
                  "!top": ["top"],
                  "!attrs": {
                    id: null,
                    class: ["A", "B", "C"]
                  },
                  top: {
                    attrs: {
                      lang: ["en", "de", "fr", "nl"],
                      freeform: null
                    },
                    children: ["animal", "plant"]
                  },
                  animal: {
                    attrs: {
                      name: null,
                      isduck: ["yes", "no"]
                    },
                    children: ["wings", "feet", "body", "head", "tail"]
                  },
                  plant: {
                    attrs: {name: null},
                    children: ["leaves", "stem", "flowers"]
                  },
                  wings: dummy, feet: dummy, body: dummy, head: dummy, tail: dummy,
                  leaves: dummy, stem: dummy, flowers: dummy
                };
          
                function completeAfter(cm, pred) {
                  var cur = cm.getCursor();
                  if (!pred || pred()) setTimeout(function() {
                    if (!cm.state.completionActive)
                      cm.showHint({completeSingle: false});
                  }, 100);
                  return CodeMirror.Pass;
                }
          
                function completeIfAfterLt(cm) {
                  return completeAfter(cm, function() {
                    var cur = cm.getCursor();
                    return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) == "<";
                  });
                }
          
                function completeIfInTag(cm) {
                  return completeAfter(cm, function() {
                    var tok = cm.getTokenAt(cm.getCursor());
                    if (tok.type == "string" && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1)) return false;
                    var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
                    return inner.tagName;
                  });
                }
          
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: "xml",
                  lineNumbers: true,
                  extraKeys: {
                    "'<'": completeAfter,
                    "'/'": completeIfAfterLt,
                    "' '": completeIfInTag,
                    "'='": completeIfInTag,
                    "Ctrl-Space": "autocomplete"
                  },
                  hintOptions: {schemaInfo: tags}
                });
              </script>
            </article>
          
      • doc
        • activebookmark.js
          // Kludge in HTML5 tag recognition in IE8
          document.createElement("section");
          document.createElement("article");
          
          (function() {
            if (!window.addEventListener) return;
            var pending = false, prevVal = null;
          
            function updateSoon() {
              if (!pending) {
                pending = true;
                setTimeout(update, 250);
              }
            }
          
            function update() {
              pending = false;
              var marks = document.getElementById("nav").getElementsByTagName("a"), found;
              for (var i = 0; i < marks.length; ++i) {
                var mark = marks[i], m;
                if (mark.getAttribute("data-default")) {
                  if (found == null) found = i;
                } else if (m = mark.href.match(/#(.*)/)) {
                  var ref = document.getElementById(m[1]);
                  if (ref && ref.getBoundingClientRect().top < 50)
                    found = i;
                }
              }
              if (found != null && found != prevVal) {
                prevVal = found;
                var lis = document.getElementById("nav").getElementsByTagName("li");
                for (var i = 0; i < lis.length; ++i) lis[i].className = "";
                for (var i = 0; i < marks.length; ++i) {
                  if (found == i) {
                    marks[i].className = "active";
                    for (var n = marks[i]; n; n = n.parentNode)
                      if (n.nodeName == "LI") n.className = "active";
                  } else {
                    marks[i].className = "";
                  }
                }
              }
            }
          
            window.addEventListener("scroll", updateSoon);
            window.addEventListener("load", updateSoon);
            window.addEventListener("hashchange", function() {
              setTimeout(function() {
                var hash = document.location.hash, found = null, m;
                var marks = document.getElementById("nav").getElementsByTagName("a");
                for (var i = 0; i < marks.length; i++)
                  if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; }
                if (found != null) for (var i = 0; i < marks.length; i++)
                  marks[i].className = i == found ? "active" : "";
              }, 300);
            });
          })();
          
        • compress.html
          <!doctype html>
          
          <title>CodeMirror: Compression Helper</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <link rel=stylesheet href="../lib/codemirror.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Compression helper</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Script compression helper</h2>
          
              <p>To optimize loading CodeMirror, especially when including a
              bunch of different modes, it is recommended that you combine and
              minify (and preferably also gzip) the scripts. This page makes
              those first two steps very easy. Simply select the version and
              scripts you need in the form below, and
              click <strong>Compress</strong> to download the minified script
              file.</p>
          
              <form id="form" action="http://marijnhaverbeke.nl/uglifyjs" method="post" onsubmit="generateHeader();">
                <input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>
                <p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px;">
                  <option value="http://codemirror.net/">HEAD</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.0.0;f=">5.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.13.0;f=">4.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.12.0;f=">4.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.11.0;f=">4.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.10.0;f=">4.10</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.9.0;f=">4.9</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.8.0;f=">4.8</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.7.0;f=">4.7</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.6.0;f=">4.6</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.5.0;f=">4.5</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.4.0;f=">4.4</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.3.0;f=">4.3</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.1;f=">4.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.0;f=">4.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.1.0;f=">4.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.0.3;f=">4.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.23.0;f=">3.23</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.22.0;f=">3.22</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.21.0;f=">3.21</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.20.0;f=">3.20</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.19.0;f=">3.19</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.18.0;f=">3.18</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.16.0;f=">3.16</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.15.0;f=">3.15</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.14.0;f=">3.14</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.13.0;f=">3.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.12;f=">3.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.11;f=">3.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.1;f=">3.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.02;f=">3.02</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.01;f=">3.01</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.0;f=">3.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.38;f=">2.38</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.37;f=">2.37</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.36;f=">2.36</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.35;f=">2.35</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.34;f=">2.34</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.33;f=">2.33</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.32;f=">2.32</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.31;f=">2.31</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.3;f=">2.3</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.25;f=">2.25</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.24;f=">2.24</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.23;f=">2.23</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.22;f=">2.22</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.21;f=">2.21</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.2;f=">2.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.18;f=">2.18</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.16;f=">2.16</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.15;f=">2.15</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.13;f=">2.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.12;f=">2.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.11;f=">2.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.1;f=">2.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.02;f=">2.02</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.01;f=">2.01</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.0;f=">2.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta2;f=">beta2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta1;f=">beta1</option>
                </select></p>
          
                <select multiple="multiple" size="20" name="code_url" style="width: 40em;" class="field" id="files">
                  <optgroup label="CodeMirror Library">
                    <option value="http://codemirror.net/lib/codemirror.js" selected>codemirror.js</option>
                  </optgroup>
                  <optgroup label="Modes">
                    <option value="http://codemirror.net/mode/apl/apl.js">apl.js</option>
                    <option value="http://codemirror.net/mode/clike/clike.js">clike.js</option>
                    <option value="http://codemirror.net/mode/clojure/clojure.js">clojure.js</option>
                    <option value="http://codemirror.net/mode/cobol/cobol.js">cobol.js</option>
                    <option value="http://codemirror.net/mode/coffeescript/coffeescript.js">coffeescript.js</option>
                    <option value="http://codemirror.net/mode/commonlisp/commonlisp.js">commonlisp.js</option>
                    <option value="http://codemirror.net/mode/css/css.js">css.js</option>
                    <option value="http://codemirror.net/mode/cypher/cypher.js">cypher.js</option>
                    <option value="http://codemirror.net/mode/d/d.js">d.js</option>
                    <option value="http://codemirror.net/mode/dart/dart.js">dart.js</option>
                    <option value="http://codemirror.net/mode/diff/diff.js">diff.js</option>
                    <option value="http://codemirror.net/mode/django/django.js">django.js</option>
                    <option value="http://codemirror.net/mode/dockerfile/dockerfile.js">dockerfile.js</option>
                    <option value="http://codemirror.net/mode/dtd/dtd.js">dtd.js</option>
                    <option value="http://codemirror.net/mode/dylan/dylan.js">dylan.js</option>
                    <option value="http://codemirror.net/mode/ebnf/ebnf.js">ebnf.js</option>
                    <option value="http://codemirror.net/mode/ecl/ecl.js">ecl.js</option>
                    <option value="http://codemirror.net/mode/eiffel/eiffel.js">eiffel.js</option>
                    <option value="http://codemirror.net/mode/erlang/erlang.js">erlang.js</option>
                    <option value="http://codemirror.net/mode/forth/forth.js">forth.js</option>
                    <option value="http://codemirror.net/mode/fortran/fortran.js">fortran.js</option>
                    <option value="http://codemirror.net/mode/gfm/gfm.js">gfm.js</option>
                    <option value="http://codemirror.net/mode/gas/gas.js">gas.js</option>
                    <option value="http://codemirror.net/mode/gherkin/gherkin.js">gherkin.js</option>
                    <option value="http://codemirror.net/mode/go/go.js">go.js</option>
                    <option value="http://codemirror.net/mode/groovy/groovy.js">groovy.js</option>
                    <option value="http://codemirror.net/mode/haml/haml.js">haml.js</option>
                    <option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
                    <option value="http://codemirror.net/mode/haxe/haxe.js">haxe.js</option>
                    <option value="http://codemirror.net/mode/htmlembedded/htmlembedded.js">htmlembedded.js</option>
                    <option value="http://codemirror.net/mode/htmlmixed/htmlmixed.js">htmlmixed.js</option>
                    <option value="http://codemirror.net/mode/http/http.js">http.js</option>
                    <option value="http://codemirror.net/mode/idl/idl.js">idl.js</option>
                    <option value="http://codemirror.net/mode/jade/jade.js">jade.js</option>
                    <option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>
                    <option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>
                    <option value="http://codemirror.net/mode/julia/julia.js">julia.js</option>
                    <option value="http://codemirror.net/mode/kotlin/kotlin.js">kotlin.js</option>
                    <option value="http://codemirror.net/mode/livescript/livescript.js">livescript.js</option>
                    <option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
                    <option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>
                    <option value="http://codemirror.net/mode/mirc/mirc.js">mirc.js</option>
                    <option value="http://codemirror.net/mode/mllike/mllike.js">mllike.js</option>
                    <option value="http://codemirror.net/mode/modelica/modelica.js">modelica.js</option>
                    <option value="http://codemirror.net/mode/nginx/nginx.js">nginx.js</option>
                    <option value="http://codemirror.net/mode/ntriples/ntriples.js">ntriples.js</option>
                    <option value="http://codemirror.net/mode/octave/octave.js">octave.js</option>
                    <option value="http://codemirror.net/mode/pascal/pascal.js">pascal.js</option>
                    <option value="http://codemirror.net/mode/pegjs/pegjs.js">pegjs.js</option>
                    <option value="http://codemirror.net/mode/perl/perl.js">perl.js</option>
                    <option value="http://codemirror.net/mode/php/php.js">php.js</option>
                    <option value="http://codemirror.net/mode/pig/pig.js">pig.js</option>
                    <option value="http://codemirror.net/mode/properties/properties.js">properties.js</option>
                    <option value="http://codemirror.net/mode/python/python.js">python.js</option>
                    <option value="http://codemirror.net/mode/puppet/puppet.js">puppet.js</option>
                    <option value="http://codemirror.net/mode/q/q.js">q.js</option>
                    <option value="http://codemirror.net/mode/r/r.js">r.js</option>
                    <option value="http://codemirror.net/mode/rpm/rpm.js">rpm.js</option>
                    <option value="http://codemirror.net/mode/rst/rst.js">rst.js</option>
                    <option value="http://codemirror.net/mode/ruby/ruby.js">ruby.js</option>
                    <option value="http://codemirror.net/mode/rust/rust.js">rust.js</option>
                    <option value="http://codemirror.net/mode/sass/sass.js">sass.js</option>
                    <option value="http://codemirror.net/mode/scala/scala.js">scala.js</option>
                    <option value="http://codemirror.net/mode/scheme/scheme.js">scheme.js</option>
                    <option value="http://codemirror.net/mode/shell/shell.js">shell.js</option>
                    <option value="http://codemirror.net/mode/sieve/sieve.js">sieve.js</option>
                    <option value="http://codemirror.net/mode/slim/slim.js">slim.js</option>
                    <option value="http://codemirror.net/mode/smalltalk/smalltalk.js">smalltalk.js</option>
                    <option value="http://codemirror.net/mode/smarty/smarty.js">smarty.js</option>
                    <option value="http://codemirror.net/mode/smartymixed/smartymixed.js">smartymixed.js</option>
                    <option value="http://codemirror.net/mode/solr/solr.js">solr.js</option>
                    <option value="http://codemirror.net/mode/soy/soy.js">soy.js</option>
                    <option value="http://codemirror.net/mode/sparql/sparql.js">sparql.js</option>
                    <option value="http://codemirror.net/mode/spreadsheet/spreadsheet.js">spreadsheet.js</option>
                    <option value="http://codemirror.net/mode/stylus/stylus.js">stylus.js</option>
                    <option value="http://codemirror.net/mode/sql/sql.js">sql.js</option>
                    <option value="http://codemirror.net/mode/stex/stex.js">stex.js</option>
                    <option value="http://codemirror.net/mode/tcl/tcl.js">tcl.js</option>
                    <option value="http://codemirror.net/mode/textile/textile.js">textile.js</option>
                    <option value="http://codemirror.net/mode/tiddlywiki/tiddlywiki.js">tiddlywiki.js</option>
                    <option value="http://codemirror.net/mode/tiki/tiki.js">tiki.js</option>
                    <option value="http://codemirror.net/mode/toml/toml.js">toml.js</option>
                    <option value="http://codemirror.net/mode/tornado/tornado.js">tornado.js</option>
                    <option value="http://codemirror.net/mode/turtle/turtle.js">turtle.js</option>
                    <option value="http://codemirror.net/mode/vb/vb.js">vb.js</option>
                    <option value="http://codemirror.net/mode/vbscript/vbscript.js">vbscript.js</option>
                    <option value="http://codemirror.net/mode/velocity/velocity.js">velocity.js</option>
                    <option value="http://codemirror.net/mode/verilog/verilog.js">verilog.js</option>
                    <option value="http://codemirror.net/mode/xml/xml.js">xml.js</option>
                    <option value="http://codemirror.net/mode/xquery/xquery.js">xquery.js</option>
                    <option value="http://codemirror.net/mode/yaml/yaml.js">yaml.js</option>
                    <option value="http://codemirror.net/mode/z80/z80.js">z80.js</option>
                  </optgroup>
                  <optgroup label="Add-ons">
                    <option value="http://codemirror.net/addon/selection/active-line.js">active-line.js</option>
                    <option value="http://codemirror.net/addon/hint/anyword-hint.js">anyword-hint.js</option>
                    <option value="http://codemirror.net/addon/fold/brace-fold.js">brace-fold.js</option>
                    <option value="http://codemirror.net/addon/edit/closebrackets.js">closebrackets.js</option>
                    <option value="http://codemirror.net/addon/edit/closetag.js">closetag.js</option>
                    <option value="http://codemirror.net/addon/runmode/colorize.js">colorize.js</option>
                    <option value="http://codemirror.net/addon/comment/comment.js">comment.js</option>
                    <option value="http://codemirror.net/addon/fold/comment-fold.js">comment-fold.js</option>
                    <option value="http://codemirror.net/addon/comment/continuecomment.js">continuecomment.js</option>
                    <option value="http://codemirror.net/addon/edit/continuelist.js">continuelist.js</option>
                    <option value="http://codemirror.net/addon/hint/css-hint.js">css-hint.js</option>
                    <option value="http://codemirror.net/addon/dialog/dialog.js">dialog.js</option>
                    <option value="http://codemirror.net/addon/fold/foldcode.js">foldcode.js</option>
                    <option value="http://codemirror.net/addon/fold/foldgutter.js">foldgutter.js</option>
                    <option value="http://codemirror.net/addon/display/fullscreen.js">fullscreen.js</option>
                    <option value="http://codemirror.net/addon/wrap/hardwrap.js">hardwrap.js</option>
                    <option value="http://codemirror.net/addon/hint/html-hint.js">html-hint.js</option>
                    <option value="http://codemirror.net/addon/fold/indent-fold.js">indent-fold.js</option>
                    <option value="http://codemirror.net/addon/hint/javascript-hint.js">javascript-hint.js</option>
                    <option value="http://codemirror.net/addon/lint/javascript-lint.js">javascript-lint.js</option>
                    <option value="http://codemirror.net/addon/lint/json-lint.js">json-lint.js</option>
                    <option value="http://codemirror.net/addon/lint/lint.js">lint.js</option>
                    <option value="http://codemirror.net/addon/mode/loadmode.js">loadmode.js</option>
                    <option value="http://codemirror.net/addon/fold/markdown-fold.js">markdown-fold.js</option>
                    <option value="http://codemirror.net/addon/selection/mark-selection.js">mark-selection.js</option>
                    <option value="http://codemirror.net/addon/search/match-highlighter.js">match-highlighter.js</option>
                    <option value="http://codemirror.net/addon/edit/matchbrackets.js">matchbrackets.js</option>
                    <option value="http://codemirror.net/addon/edit/matchtags.js">matchtags.js</option>
                    <option value="http://codemirror.net/addon/merge/merge.js">merge.js</option>
                    <option value="http://codemirror.net/addon/mode/multiplex.js">multiplex.js</option>
                    <option value="http://codemirror.net/addon/mode/overlay.js">overlay.js</option>
                    <option value="http://codemirror.net/addon/display/placeholder.js">placeholder.js</option>
                    <option value="http://codemirror.net/addon/display/rulers.js">rulers.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode.js">runmode.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode.node.js">runmode.node.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode-standalone.js">runmode-standalone.js</option>
                    <option value="http://codemirror.net/addon/search/search.js">search.js</option>
                    <option value="http://codemirror.net/addon/search/searchcursor.js">searchcursor.js</option>
                    <option value="http://codemirror.net/addon/hint/show-hint.js">show-hint.js</option>
                    <option value="http://codemirror.net/addon/mode/simple.js">simple.js</option>
                    <option value="http://codemirror.net/addon/scroll/simplescrollbars.js">simplescrollbars.js</option>
                    <option value="http://codemirror.net/addon/hint/sql-hint.js">sql-hint.js</option>
                    <option value="http://codemirror.net/addon/edit/trailingspace.js">trailingspace.js</option>
                    <option value="http://codemirror.net/addon/tern/tern.js">tern.js</option>
                    <option value="http://codemirror.net/addon/fold/xml-fold.js">xml-fold.js</option>
                    <option value="http://codemirror.net/addon/hint/xml-hint.js">xml-hint.js</option>
                    <option value="http://codemirror.net/addon/hint/yaml-lint.js">yaml-lint.js</option>
                  </optgroup>
                  <optgroup label="Keymaps">
                    <option value="http://codemirror.net/keymap/emacs.js">emacs.js</option>
                    <option value="http://codemirror.net/keymap/sublime.js">sublime.js</option>
                    <option value="http://codemirror.net/keymap/vim.js">vim.js</option>
                  </optgroup>
                </select>
          
                <p>
                  <button type="submit">Compress</button> with <a href="http://github.com/mishoo/UglifyJS/">UglifyJS</a>
                </p>
                <input type="hidden" id="header" name="header">
                <p>Custom code to add to the compressed file:<textarea name="js_code" style="width: 100%; height: 15em;" class="field" id="js_code"></textarea></p>
              </form>
          
              <script type="text/javascript">
                CodeMirror.fromTextArea(document.getElementById("js_code")).getWrapperElement().className += " field";
          
                function setVersion(ver) {
                  var urlprefix = ver.options[ver.selectedIndex].value;
                  var select = document.getElementById("files"), m;
                  for (var optgr = select.firstChild; optgr; optgr = optgr.nextSibling)
                    for (var opt = optgr.firstChild; opt; opt = opt.nextSibling) {
                      if (opt.nodeName != "OPTION")
                        continue;
                      else if (m = opt.value.match(/^http:\/\/codemirror.net\/(.*)$/))
                        opt.value = urlprefix + m[1];
                      else if (m = opt.value.match(/http:\/\/marijnhaverbeke.nl\/git\/codemirror\?a=blob_plain;hb=[^;]+;f=(.*)$/))
                        opt.value = urlprefix + m[1];
                    }
                 }
                 
                 function generateHeader() {
                   var versionNode = document.getElementById("version");
                   var version = versionNode.options[versionNode.selectedIndex].label
                   var filesNode = document.getElementById("files");
                   var optGroupHeaderIncluded;
          
                   // Generate the comment
                   var str = "/* CodeMirror - Minified & Bundled\n";
                   str += "   Generated on " + new Date().toLocaleDateString() + " with http://codemirror.net/doc/compress.html\n";
                   str += "   Version: " + version + "\n\n";
          
                   for (var group = filesNode.firstChild; group; group = group.nextSibling) {
                     optGroupHeaderIncluded = false;
                     for (var option = group.firstChild; option; option = option.nextSibling) {
                       if (option.nodeName !== "OPTION") {
                         continue;
                       } else if (option.selected) {
                         if (!optGroupHeaderIncluded) {
                           str += "   " + group.label + ":\n";
                           optGroupHeaderIncluded = true;
                         }
                         str += "   - " + option.label + "\n";
                       }
                     }
                   }
                   str += " */\n\n";
          
                   document.getElementById("header").value = str;
                 }
              </script>
          
          </article>
          
        • docs.css
          @font-face {
            font-family: 'Source Sans Pro';
            font-style: normal;
            font-weight: 400;
            src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(//themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
          }
          
          body, html { margin: 0; padding: 0; height: 100%; }
          section, article { display: block; padding: 0; }
          
          body {
            background: #f8f8f8;
            font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
            line-height: 1.5;
          }
          
          p { margin-top: 0; }
          
          h2, h3, h1 {
            font-weight: normal;
            margin-bottom: .7em;
          }
          h1 { font-size: 140%; }
          h2 { font-size: 120%; }
          h3 { font-size: 110%; }
          article > h2:first-child, section:first-child > h2 { margin-top: 0; }
          
          #nav h1 {
            margin-right: 12px;
            margin-top: 0;
            margin-bottom: 2px;
            color: #d30707;
            letter-spacing: .5px;
          }
          
          a, a:visited, a:link, .quasilink {
            color: #A21313;
            text-decoration: none;
          }
          
          em {
            padding-right: 2px;
          }
          
          .quasilink {
            cursor: pointer;
          }
          
          article {
            max-width: 700px;
            margin: 0 0 0 160px;
            border-left: 2px solid #E30808;
            border-right: 1px solid #ddd;
            padding: 30px 50px 100px 50px;
            background: white;
            z-index: 2;
            position: relative;
            min-height: 100%;
            box-sizing: border-box;
            -moz-box-sizing: border-box;
          }
          
          #nav {
            position: fixed;
            padding-top: 30px;
            max-height: 100%;
            box-sizing: -moz-border-box;
            box-sizing: border-box;
            overflow-y: auto;
            left: 0; right: none;
            width: 160px;
            text-align: right;
            z-index: 1;
          }
          
          @media screen and (min-width: 1000px) {
            article {
              margin: 0 auto;
            }
            #nav {
              right: 50%;
              width: auto;
              border-right: 349px solid transparent;
            }
          }
          
          #nav ul {
            display: block;
            margin: 0; padding: 0;
            margin-bottom: 32px;
          }
          
          #nav li {
            display: block;
            margin-bottom: 4px;
          }
          
          #nav li ul {
            font-size: 80%;
            margin-bottom: 0;
            display: none;
          }
          
          #nav li.active ul {
            display: block;
          }
          
          #nav li li a {
            padding-right: 20px;
            display: inline-block;
          }
          
          #nav ul a {
            color: black;
            padding: 0 7px 1px 11px;
          }
          
          #nav ul a.active, #nav ul a:hover {
            border-bottom: 1px solid #E30808;
            margin-bottom: -1px;
            color: #E30808;
          }
          
          #logo {
            border: 0;
            margin-right: 12px;
            margin-bottom: 25px;
          }
          
          section {
            border-top: 1px solid #E30808;
            margin: 1.5em 0;
          }
          
          section.first {
            border: none;
            margin-top: 0;
          }
          
          #demo {
            position: relative;
          }
          
          #demolist {
            position: absolute;
            right: 5px;
            top: 5px;
            z-index: 25;
          }
          
          .yinyang {
            position: absolute;
            top: -10px;
            left: 0; right: 0;
            margin: auto;
            display: block;
            height: 120px;
          }
          
          .actions {
            margin: 1em 0 0;
            min-height: 100px;
            position: relative;
          }
          
          .actionspicture {
            pointer-events: none;
            position: absolute;
            height: 100px;
            top: 0; left: 0; right: 0;
          }
          
          .actionlink {
            pointer-events: auto;
            font-family: arial;
            font-size: 80%;
            font-weight: bold;
            position: absolute;
            top: 0; bottom: 0;
            line-height: 1;
            height: 1em;
            margin: auto;
          }
          
          .actionlink.download {
            color: white;
            right: 50%;
            margin-right: 13px;
            text-shadow: -1px 1px 3px #b00, -1px -1px 3px #b00, 1px 0px 3px #b00;
          }
          
          .actionlink.fund {
            color: #b00;
            left: 50%;
            margin-left: 15px;
          }
          
          .actionlink:hover {
            text-decoration: underline;
          }
          
          .actionlink a {
            color: inherit;
          }
          
          .actionsleft {
            float: left;
          }
          
          .actionsright {
            float: right;
            text-align: right;
          }
          
          @media screen and (max-width: 800px) {
            .actions {
              padding-top: 120px;
            }
            .actionsleft, .actionsright {
              float: none;
              text-align: left;
              margin-bottom: 1em;
            }
          }
          
          th {
            text-decoration: underline;
            font-weight: normal;
            text-align: left;
          }
          
          #features ul {
            list-style: none;
            margin: 0 0 1em;
            padding: 0 0 0 1.2em;
          }
          
          #features li:before {
            content: "-";
            width: 1em;
            display: inline-block;
            padding: 0;
            margin: 0;
            margin-left: -1em;
          }
          
          .rel {
            margin-bottom: 0;
          }
          .rel-note {
            margin-top: 0;
            color: #555;
          }
          
          pre {
            padding-left: 15px;
            border-left: 2px solid #ddd;
          }
          
          code {
            padding: 0 2px;
          }
          
          strong {
            text-decoration: underline;
            font-weight: normal;
          }
          
          .field {
            border: 1px solid #A21313;
          }
          
        • internals.html
          <!doctype html>
          
          <title>CodeMirror: Internals</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <style>dl dl {margin: 0;} .update {color: #d40 !important}</style>
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a href="#top">Introduction</a></li>
              <li><a href="#approach">General Approach</a></li>
              <li><a href="#input">Input</a></li>
              <li><a href="#selection">Selection</a></li>
              <li><a href="#update">Intelligent Updating</a></li>
              <li><a href="#parse">Parsing</a></li>
              <li><a href="#summary">What Gives?</a></li>
              <li><a href="#btree">Content Representation</a></li>
              <li><a href="#keymap">Key Maps</a></li>
            </ul>
          </div>
          
          <article>
          
          <h2 id=top>(Re-) Implementing A Syntax-Highlighting Editor in JavaScript</h2>
          
          <p style="font-size: 85%" id="intro">
            <strong>Topic:</strong> JavaScript, code editor implementation<br>
            <strong>Author:</strong> Marijn Haverbeke<br>
            <strong>Date:</strong> March 2nd 2011 (updated November 13th 2011)
          </p>
          
          <p style="padding: 0 3em 0 2em"><strong>Caution</strong>: this text was written briefly after
          version 2 was initially written. It no longer (even including the
          update at the bottom) fully represents the current implementation. I'm
          leaving it here as a historic document. For more up-to-date
          information, look at the entries
          tagged <a href="http://marijnhaverbeke.nl/blog/#cm-internals">cm-internals</a>
          on my blog.</p>
          
          <p>This is a followup to
          my <a href="http://codemirror.net/story.html">Brutal Odyssey to the
          Dark Side of the DOM Tree</a> story. That one describes the
          mind-bending process of implementing (what would become) CodeMirror 1.
          This one describes the internals of CodeMirror 2, a complete rewrite
          and rethink of the old code base. I wanted to give this piece another
          Hunter Thompson copycat subtitle, but somehow that would be out of
          place—the process this time around was one of straightforward
          engineering, requiring no serious mind-bending whatsoever.</p>
          
          <p>So, what is wrong with CodeMirror 1? I'd estimate, by mailing list
          activity and general search-engine presence, that it has been
          integrated into about a thousand systems by now. The most prominent
          one, since a few weeks,
          being <a href="http://googlecode.blogspot.com/2011/01/make-quick-fixes-quicker-on-google.html">Google
          code's project hosting</a>. It works, and it's being used widely.</p>
          
          <p>Still, I did not start replacing it because I was bored. CodeMirror
          1 was heavily reliant on <code>designMode</code>
          or <code>contentEditable</code> (depending on the browser). Neither of
          these are well specified (HTML5 tries
          to <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">specify</a>
          their basics), and, more importantly, they tend to be one of the more
          obscure and buggy areas of browser functionality—CodeMirror, by using
          this functionality in a non-typical way, was constantly running up
          against browser bugs. WebKit wouldn't show an empty line at the end of
          the document, and in some releases would suddenly get unbearably slow.
          Firefox would show the cursor in the wrong place. Internet Explorer
          would insist on linkifying everything that looked like a URL or email
          address, a behaviour that can't be turned off. Some bugs I managed to
          work around (which was often a frustrating, painful process), others,
          such as the Firefox cursor placement, I gave up on, and had to tell
          user after user that they were known problems, but not something I
          could help.</p>
          
          <p>Also, there is the fact that <code>designMode</code> (which seemed
          to be less buggy than <code>contentEditable</code> in Webkit and
          Firefox, and was thus used by CodeMirror 1 in those browsers) requires
          a frame. Frames are another tricky area. It takes some effort to
          prevent getting tripped up by domain restrictions, they don't
          initialize synchronously, behave strangely in response to the back
          button, and, on several browsers, can't be moved around the DOM
          without having them re-initialize. They did provide a very nice way to
          namespace the library, though—CodeMirror 1 could freely pollute the
          namespace inside the frame.</p>
          
          <p>Finally, working with an editable document means working with
          selection in arbitrary DOM structures. Internet Explorer (8 and
          before) has an utterly different (and awkward) selection API than all
          of the other browsers, and even among the different implementations of
          <code>document.selection</code>, details about how exactly a selection
          is represented vary quite a bit. Add to that the fact that Opera's
          selection support tended to be very buggy until recently, and you can
          imagine why CodeMirror 1 contains 700 lines of selection-handling
          code.</p>
          
          <p>And that brings us to the main issue with the CodeMirror 1
          code base: The proportion of browser-bug-workarounds to real
          application code was getting dangerously high. By building on top of a
          few dodgy features, I put the system in a vulnerable position—any
          incompatibility and bugginess in these features, I had to paper over
          with my own code. Not only did I have to do some serious stunt-work to
          get it to work on older browsers (as detailed in the
          previous <a href="http://codemirror.net/story.html">story</a>), things
          also kept breaking in newly released versions, requiring me to come up
          with <em>new</em> scary hacks in order to keep up. This was starting
          to lose its appeal.</p>
          
          <section id=approach>
            <h2>General Approach</h2>
          
          <p>What CodeMirror 2 does is try to sidestep most of the hairy hacks
          that came up in version 1. I owe a lot to the
          <a href="http://ace.ajax.org">ACE</a> editor for inspiration on how to
          approach this.</p>
          
          <p>I absolutely did not want to be completely reliant on key events to
          generate my input. Every JavaScript programmer knows that key event
          information is horrible and incomplete. Some people (most awesomely
          Mihai Bazon with <a href="http://ymacs.org">Ymacs</a>) have been able
          to build more or less functioning editors by directly reading key
          events, but it takes a lot of work (the kind of never-ending, fragile
          work I described earlier), and will never be able to properly support
          things like multi-keystoke international character
          input. <a href="#keymap" class="update">[see below for caveat]</a></p>
          
          <p>So what I do is focus a hidden textarea, and let the browser
          believe that the user is typing into that. What we show to the user is
          a DOM structure we built to represent his document. If this is updated
          quickly enough, and shows some kind of believable cursor, it feels
          like a real text-input control.</p>
          
          <p>Another big win is that this DOM representation does not have to
          span the whole document. Some CodeMirror 1 users insisted that they
          needed to put a 30 thousand line XML document into CodeMirror. Putting
          all that into the DOM takes a while, especially since, for some
          reason, an editable DOM tree is slower than a normal one on most
          browsers. If we have full control over what we show, we must only
          ensure that the visible part of the document has been added, and can
          do the rest only when needed. (Fortunately, the <code>onscroll</code>
          event works almost the same on all browsers, and lends itself well to
          displaying things only as they are scrolled into view.)</p>
          </section>
          <section id="input">
            <h2>Input</h2>
          
          <p>ACE uses its hidden textarea only as a text input shim, and does
          all cursor movement and things like text deletion itself by directly
          handling key events. CodeMirror's way is to let the browser do its
          thing as much as possible, and not, for example, define its own set of
          key bindings. One way to do this would have been to have the whole
          document inside the hidden textarea, and after each key event update
          the display DOM to reflect what's in that textarea.</p>
          
          <p>That'd be simple, but it is not realistic. For even medium-sized
          document the editor would be constantly munging huge strings, and get
          terribly slow. What CodeMirror 2 does is put the current selection,
          along with an extra line on the top and on the bottom, into the
          textarea.</p>
          
          <p>This means that the arrow keys (and their ctrl-variations), home,
          end, etcetera, do not have to be handled specially. We just read the
          cursor position in the textarea, and update our cursor to match it.
          Also, copy and paste work pretty much for free, and people get their
          native key bindings, without any special work on my part. For example,
          I have emacs key bindings configured for Chrome and Firefox. There is
          no way for a script to detect this. <a class="update"
          href="#keymap">[no longer the case]</a></p>
          
          <p>Of course, since only a small part of the document sits in the
          textarea, keys like page up and ctrl-end won't do the right thing.
          CodeMirror is catching those events and handling them itself.</p>
          </section>
          <section id="selection">
            <h2>Selection</h2>
          
          <p>Getting and setting the selection range of a textarea in modern
          browsers is trivial—you just use the <code>selectionStart</code>
          and <code>selectionEnd</code> properties. On IE you have to do some
          insane stuff with temporary ranges and compensating for the fact that
          moving the selection by a 'character' will treat \r\n as a single
          character, but even there it is possible to build functions that
          reliably set and get the selection range.</p>
          
          <p>But consider this typical case: When I'm somewhere in my document,
          press shift, and press the up arrow, something gets selected. Then, if
          I, still holding shift, press the up arrow again, the top of my
          selection is adjusted. The selection remembers where its <em>head</em>
          and its <em>anchor</em> are, and moves the head when we shift-move.
          This is a generally accepted property of selections, and done right by
          every editing component built in the past twenty years.</p>
          
          <p>But not something that the browser selection APIs expose.</p>
          
          <p>Great. So when someone creates an 'upside-down' selection, the next
          time CodeMirror has to update the textarea, it'll re-create the
          selection as an 'upside-up' selection, with the anchor at the top, and
          the next cursor motion will behave in an unexpected way—our second
          up-arrow press in the example above will not do anything, since it is
          interpreted in exactly the same way as the first.</p>
          
          <p>No problem. We'll just, ehm, detect that the selection is
          upside-down (you can tell by the way it was created), and then, when
          an upside-down selection is present, and a cursor-moving key is
          pressed in combination with shift, we quickly collapse the selection
          in the textarea to its start, allow the key to take effect, and then
          combine its new head with its old anchor to get the <em>real</em>
          selection.</p>
          
          <p>In short, scary hacks could not be avoided entirely in CodeMirror
          2.</p>
          
          <p>And, the observant reader might ask, how do you even know that a
          key combo is a cursor-moving combo, if you claim you support any
          native key bindings? Well, we don't, but we can learn. The editor
          keeps a set known cursor-movement combos (initialized to the
          predictable defaults), and updates this set when it observes that
          pressing a certain key had (only) the effect of moving the cursor.
          This, of course, doesn't work if the first time the key is used was
          for extending an inverted selection, but it works most of the
          time.</p>
          </section>
          <section id="update">
            <h2>Intelligent Updating</h2>
          
          <p>One thing that always comes up when you have a complicated internal
          state that's reflected in some user-visible external representation
          (in this case, the displayed code and the textarea's content) is
          keeping the two in sync. The naive way is to just update the display
          every time you change your state, but this is not only error prone
          (you'll forget), it also easily leads to duplicate work on big,
          composite operations. Then you start passing around flags indicating
          whether the display should be updated in an attempt to be efficient
          again and, well, at that point you might as well give up completely.</p>
          
          <p>I did go down that road, but then switched to a much simpler model:
          simply keep track of all the things that have been changed during an
          action, and then, only at the end, use this information to update the
          user-visible display.</p>
          
          <p>CodeMirror uses a concept of <em>operations</em>, which start by
          calling a specific set-up function that clears the state and end by
          calling another function that reads this state and does the required
          updating. Most event handlers, and all the user-visible methods that
          change state are wrapped like this. There's a method
          called <code>operation</code> that accepts a function, and returns
          another function that wraps the given function as an operation.</p>
          
          <p>It's trivial to extend this (as CodeMirror does) to detect nesting,
          and, when an operation is started inside an operation, simply
          increment the nesting count, and only do the updating when this count
          reaches zero again.</p>
          
          <p>If we have a set of changed ranges and know the currently shown
          range, we can (with some awkward code to deal with the fact that
          changes can add and remove lines, so we're dealing with a changing
          coordinate system) construct a map of the ranges that were left
          intact. We can then compare this map with the part of the document
          that's currently visible (based on scroll offset and editor height) to
          determine whether something needs to be updated.</p>
          
          <p>CodeMirror uses two update algorithms—a full refresh, where it just
          discards the whole part of the DOM that contains the edited text and
          rebuilds it, and a patch algorithm, where it uses the information
          about changed and intact ranges to update only the out-of-date parts
          of the DOM. When more than 30 percent (which is the current heuristic,
          might change) of the lines need to be updated, the full refresh is
          chosen (since it's faster to do than painstakingly finding and
          updating all the changed lines), in the other case it does the
          patching (so that, if you scroll a line or select another character,
          the whole screen doesn't have to be
          re-rendered). <span class="update">[the full-refresh
          algorithm was dropped, it wasn't really faster than the patching
          one]</span></p>
          
          <p>All updating uses <code>innerHTML</code> rather than direct DOM
          manipulation, since that still seems to be by far the fastest way to
          build documents. There's a per-line function that combines the
          highlighting, <a href="manual.html#markText">marking</a>, and
          selection info for that line into a snippet of HTML. The patch updater
          uses this to reset individual lines, the refresh updater builds an
          HTML chunk for the whole visible document at once, and then uses a
          single <code>innerHTML</code> update to do the refresh.</p>
          </section>
          <section id="parse">
            <h2>Parsers can be Simple</h2>
          
          <p>When I wrote CodeMirror 1, I
          thought <a href="http://codemirror.net/story.html#parser">interruptable
          parsers</a> were a hugely scary and complicated thing, and I used a
          bunch of heavyweight abstractions to keep this supposed complexity
          under control: parsers
          were <a href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">iterators</a>
          that consumed input from another iterator, and used funny
          closure-resetting tricks to copy and resume themselves.</p>
          
          <p>This made for a rather nice system, in that parsers formed strictly
          separate modules, and could be composed in predictable ways.
          Unfortunately, it was quite slow (stacking three or four iterators on
          top of each other), and extremely intimidating to people not used to a
          functional programming style.</p>
          
          <p>With a few small changes, however, we can keep all those
          advantages, but simplify the API and make the whole thing less
          indirect and inefficient. CodeMirror
          2's <a href="manual.html#modeapi">mode API</a> uses explicit state
          objects, and makes the parser/tokenizer a function that simply takes a
          state and a character stream abstraction, advances the stream one
          token, and returns the way the token should be styled. This state may
          be copied, optionally in a mode-defined way, in order to be able to
          continue a parse at a given point. Even someone who's never touched a
          lambda in his life can understand this approach. Additionally, far
          fewer objects are allocated in the course of parsing now.</p>
          
          <p>The biggest speedup comes from the fact that the parsing no longer
          has to touch the DOM though. In CodeMirror 1, on an older browser, you
          could <em>see</em> the parser work its way through the document,
          managing some twenty lines in each 50-millisecond time slice it got. It
          was reading its input from the DOM, and updating the DOM as it went
          along, which any experienced JavaScript programmer will immediately
          spot as a recipe for slowness. In CodeMirror 2, the parser usually
          finishes the whole document in a single 100-millisecond time slice—it
          manages some 1500 lines during that time on Chrome. All it has to do
          is munge strings, so there is no real reason for it to be slow
          anymore.</p>
          </section>
          <section id="summary">
            <h2>What Gives?</h2>
          
          <p>Given all this, what can you expect from CodeMirror 2?</p>
          
          <ul>
          
          <li><strong>Small.</strong> the base library is
          some <span class="update">45k</span> when minified
          now, <span class="update">17k</span> when gzipped. It's smaller than
          its own logo.</li>
          
          <li><strong>Lightweight.</strong> CodeMirror 2 initializes very
          quickly, and does almost no work when it is not focused. This means
          you can treat it almost like a textarea, have multiple instances on a
          page without trouble.</li>
          
          <li><strong>Huge document support.</strong> Since highlighting is
          really fast, and no DOM structure is being built for non-visible
          content, you don't have to worry about locking up your browser when a
          user enters a megabyte-sized document.</li>
          
          <li><strong>Extended API.</strong> Some things kept coming up in the
          mailing list, such as marking pieces of text or lines, which were
          extremely hard to do with CodeMirror 1. The new version has proper
          support for these built in.</li>
          
          <li><strong>Tab support.</strong> Tabs inside editable documents were,
          for some reason, a no-go. At least six different people announced they
          were going to add tab support to CodeMirror 1, none survived (I mean,
          none delivered a working version). CodeMirror 2 no longer removes tabs
          from your document.</li>
          
          <li><strong>Sane styling.</strong> <code>iframe</code> nodes aren't
          really known for respecting document flow. Now that an editor instance
          is a plain <code>div</code> element, it is much easier to size it to
          fit the surrounding elements. You don't even have to make it scroll if
          you do not <a href="../demo/resize.html">want to</a>.</li>
          
          </ul>
          
          <p>On the downside, a CodeMirror 2 instance is <em>not</em> a native
          editable component. Though it does its best to emulate such a
          component as much as possible, there is functionality that browsers
          just do not allow us to hook into. Doing select-all from the context
          menu, for example, is not currently detected by CodeMirror.</p>
          
          <p id="changes" style="margin-top: 2em;"><span style="font-weight:
          bold">[Updates from November 13th 2011]</span> Recently, I've made
          some changes to the codebase that cause some of the text above to no
          longer be current. I've left the text intact, but added markers at the
          passages that are now inaccurate. The new situation is described
          below.</p>
          </section>
          <section id="btree">
            <h2>Content Representation</h2>
          
          <p>The original implementation of CodeMirror 2 represented the
          document as a flat array of line objects. This worked well—splicing
          arrays will require the part of the array after the splice to be
          moved, but this is basically just a simple <code>memmove</code> of a
          bunch of pointers, so it is cheap even for huge documents.</p>
          
          <p>However, I recently added line wrapping and code folding (line
          collapsing, basically). Once lines start taking up a non-constant
          amount of vertical space, looking up a line by vertical position
          (which is needed when someone clicks the document, and to determine
          the visible part of the document during scrolling) can only be done
          with a linear scan through the whole array, summing up line heights as
          you go. Seeing how I've been going out of my way to make big documents
          fast, this is not acceptable.</p>
          
          <p>The new representation is based on a B-tree. The leaves of the tree
          contain arrays of line objects, with a fixed minimum and maximum size,
          and the non-leaf nodes simply hold arrays of child nodes. Each node
          stores both the amount of lines that live below them and the vertical
          space taken up by these lines. This allows the tree to be indexed both
          by line number and by vertical position, and all access has
          logarithmic complexity in relation to the document size.</p>
          
          <p>I gave line objects and tree nodes parent pointers, to the node
          above them. When a line has to update its height, it can simply walk
          these pointers to the top of the tree, adding or subtracting the
          difference in height from each node it encounters. The parent pointers
          also make it cheaper (in complexity terms, the difference is probably
          tiny in normal-sized documents) to find the current line number when
          given a line object. In the old approach, the whole document array had
          to be searched. Now, we can just walk up the tree and count the sizes
          of the nodes coming before us at each level.</p>
          
          <p>I chose B-trees, not regular binary trees, mostly because they
          allow for very fast bulk insertions and deletions. When there is a big
          change to a document, it typically involves adding, deleting, or
          replacing a chunk of subsequent lines. In a regular balanced tree, all
          these inserts or deletes would have to be done separately, which could
          be really expensive. In a B-tree, to insert a chunk, you just walk
          down the tree once to find where it should go, insert them all in one
          shot, and then break up the node if needed. This breaking up might
          involve breaking up nodes further up, but only requires a single pass
          back up the tree. For deletion, I'm somewhat lax in keeping things
          balanced—I just collapse nodes into a leaf when their child count goes
          below a given number. This means that there are some weird editing
          patterns that may result in a seriously unbalanced tree, but even such
          an unbalanced tree will perform well, unless you spend a day making
          strangely repeating edits to a really big document.</p>
          </section>
          <section id="keymap">
            <h2>Keymaps</h2>
          
          <p><a href="#approach">Above</a>, I claimed that directly catching key
          events for things like cursor movement is impractical because it
          requires some browser-specific kludges. I then proceeded to explain
          some awful <a href="#selection">hacks</a> that were needed to make it
          possible for the selection changes to be detected through the
          textarea. In fact, the second hack is about as bad as the first.</p>
          
          <p>On top of that, in the presence of user-configurable tab sizes and
          collapsed and wrapped lines, lining up cursor movement in the textarea
          with what's visible on the screen becomes a nightmare. Thus, I've
          decided to move to a model where the textarea's selection is no longer
          depended on.</p>
          
          <p>So I moved to a model where all cursor movement is handled by my
          own code. This adds support for a goal column, proper interaction of
          cursor movement with collapsed lines, and makes it possible for
          vertical movement to move through wrapped lines properly, instead of
          just treating them like non-wrapped lines.</p>
          
          <p>The key event handlers now translate the key event into a string,
          something like <code>Ctrl-Home</code> or <code>Shift-Cmd-R</code>, and
          use that string to look up an action to perform. To make keybinding
          customizable, this lookup goes through
          a <a href="manual.html#option_keyMap">table</a>, using a scheme that
          allows such tables to be chained together (for example, the default
          Mac bindings fall through to a table named 'emacsy', which defines
          basic Emacs-style bindings like <code>Ctrl-F</code>, and which is also
          used by the custom Emacs bindings).</p>
          
          <p>A new
          option <a href="manual.html#option_extraKeys"><code>extraKeys</code></a>
          allows ad-hoc keybindings to be defined in a much nicer way than what
          was possible with the
          old <a href="manual.html#option_onKeyEvent"><code>onKeyEvent</code></a>
          callback. You simply provide an object mapping key identifiers to
          functions, instead of painstakingly looking at raw key events.</p>
          
          <p>Built-in commands map to strings, rather than functions, for
          example <code>"goLineUp"</code> is the default action bound to the up
          arrow key. This allows new keymaps to refer to them without
          duplicating any code. New commands can be defined by assigning to
          the <code>CodeMirror.commands</code> object, which maps such commands
          to functions.</p>
          
          <p>The hidden textarea now only holds the current selection, with no
          extra characters around it. This has a nice advantage: polling for
          input becomes much, much faster. If there's a big selection, this text
          does not have to be read from the textarea every time—when we poll,
          just noticing that something is still selected is enough to tell us
          that no new text was typed.</p>
          
          <p>The reason that cheap polling is important is that many browsers do
          not fire useful events on IME (input method engine) input, which is
          the thing where people inputting a language like Japanese or Chinese
          use multiple keystrokes to create a character or sequence of
          characters. Most modern browsers fire <code>input</code> when the
          composing is finished, but many don't fire anything when the character
          is updated <em>during</em> composition. So we poll, whenever the
          editor is focused, to provide immediate updates of the display.</p>
          
          </article>
          
        • logo.png
          �PNG
          
          
          IHDRqi
          ��&bKGD�������	pHYs�����tIME�
          1;�� IDATx���w|TE�ǿsw7��)Ri�!A��k@EA��QPAQ@���6P���ދ���G!��i�JKO6�����l�&$!e�����'ٙ�;�����9gNRJ�B��͛��#���L�)$�R�)%� =AXA�H)���l6������AlԨ����{���GQD����Jy�X�_�(�M&S�? �b������ ���.�6�7�{��Q��V�r��YΝ;ǹ3g�p����7��%!��bǮ���HF��{��M�ׯ_��s���ӧO��/��랟� ����"�d����Qqqq������W_/�Ҵ�vV�������K������$Q
          ƚ��Ew�s+�]�7%%��f�<<<x�Kg�.�Ϫ5�	���F�ܤ��,4�
          ?�ƀ@�u��'�,���4�kܸ1S�La��M��*X�Un
          
          ��g9�x���Bߟ~�#��6yTUe�����b&6�͹��*2�b���3+���f��Y�fֲ�(
          �=�K�/�F��ow[��?�i�8P�����	OW\�q��|��bQ��
          ���S��xyy���������s�F��7�ti_�Ν��aϪ.\�}�SQD��t��^�����IHH����]�<3h �ǏG��~Ϝ9��O>����;��KMˠ@,9p�|������&$$�)Xߥ[W���ѨQ�
          ��mQ[y}�y����f���2N�J��$��������AzZ^��ujѭ{���4i����W�����׽lX�@�H�
          �g&^N�!��<���_�6u�֥{�0�w�N���o�}fdd�X�G��_�RQ5�Cq�,��A4�
          �C��@����ԣ[�0���nٌs��F�}ӦML|k�c/fU����D��P���]���� z�	�O�><���e@TU%6&����B��|�Iy��_�V�u-���{�Qox�ܝ�|���ڣ;}���u�օ΀[I6��=?�)DEQ=z�3f4�VA
          |xW�h��o=
          ��#L�޽qww�4�Ubb"�Y߹kgHHH䠻D���0�R��Mۇ:t(�۷���� &\����E�gee9�x�w׉F�!�
          <�!��j�ѫ'C���LJi���HII��7���������O�r�Jn��B!]�X�lٲv��uG�t�>ǎ[��-Ѩ7�A���;<̄	�[���J��@||<͛7'������mQl��wl�4B�#�\	���ë��ۯ�ךU�Q�[4o�;�p��
          Ѩ7T�+����[���=�;����7��~��S'�KL '��K���c��B���ˎ�zv���f�Z���ﴵj�"--��_.pS���Qo����i4
          �dԨQxyyq���`I�hF
          �MR��f��?we��!�M�[7c��Z�j9��>[����GGG'�D��0�x����������x�����S�O����Y��)	\��vX�|����5kv���C]�F�z�����ڵCf�Z�Ν�kc�ۅKg�QoP����������w�������ȑ#$��)>Z-5tn��W���c����)J(��}�z�~U�z5���
          's���:#�U�|��_C)%���@!�^�S�L��X�re.��n7�/��Z�@�.YEy�%�`3�c��)]_�������3H���N��EI��|<����ݝ�>��_|�;����ؼ~�
          ���o~�7t^�v���Bppp������}�n���۶�m�{��3oRX,g1&�aÆ�.Ѩ7L^��ȂE�ѳ�m�ӧO������M�6͖a�)���O�@
          �@5;{jy�SP>���A��}��?��� |}رc�sӟW�\i/7�F�a"����5g6-Z��m3��{�eƌ̘1�˗/��Z[6oaՊ�:��n��R�ȶ>���*R2�E�]��_p��� _z���	�����UHMC	���?l�k+?�{O4�
          a���e����m;�sދ'N�HVV=�z0i�$�=Z�k��ʊ+�'N����&ժ��(~Xz�W��B�X ��8!�湁�"�`Җ�z�2������?���w~�������@�+g���G�+���Eaܸq��y{�;l\�����JHH��w�
          :���DL&���i?r���(����4r���\�*=�1YӼ�P7�ƞ&�iOI��E�A �w��I�u�o�Xz��]@(�F=;��H4��1�U��j�~��H'^~��Jǔ��ً
          ����c8{�,۶F�mk���ԪS�N�V�����?>�����w�4�>��[�U@J^�Y��O�.��\c0ژ���7����!���Ӈ츣�Z3��lh5D��`�����)�T��Qo<��}�ᇷ���(z��X�v
          ˖-�믿&�Z��aRRR�P+/�۵zTS4�ꯑ�'������s�PUH1x���4j������&M��~��(R*�''���F��r��i�����~(�YN4�
          u�/��ƍ���w����>|8QQQLz�m��u�J`�������u��\z"0�w祐N;Ȟ7k�������X� %�dFdXI�Z!��`#۷own~�iӦ[KrE��	@��R��P������������ "")%�ϟ'**�ϧ��]�j/�uS�v�%\"6-�)i��EVv6
          R�)����mDD��1��>�ͪ�G��"�@�h@�AӨ!;>����뛉E�D��p��3����X!^A�ڵ���Ɨp�ՋY�3RQKp���4��:ʷW/b��s,3�-�Wٝ�lԺ�c�v�^W��z���ğ8I5���E��/��.eew]Kc�}U�g,l&���L��޷]�p5h�_oRҮ+?Rl6�k�Ǩ���շ
          a~�<����%>+�u	�X�t�Ӊ��$�\�j���9fJ�93$�$<<\{t�V:�Fu�\�����n�r��?����L :D�<�V�e����
          $��ZPuRN^�&0�%�J�����ˬH�̽nܣ�a���c�/eRk��PҾCCC�@>�f��~�ݗ��k�Z(^^T�M�t�+�����i��h�'�K��{�u7��A_Qy�Jjr3��Ӕ��Bⳬ�������B����k����m�>
          ��������fW�
          @ff�X8��n�ҥK��/�ef./���N�P�r��݋����x�E�ɓ'��X�^�\��"����u(9΀<(�؟n���رc�eX�����~�B]��Y����Y�ŋ��?���c�2�"������ÃN�t��@����/x#��X,���N˯h۶��޽{3�ӧ�翇���}����N=__�`�v��ԩSy۴F��[�>�A|ܹ�S�G�����@<}�T��"��TF��BP�=�P��|�Ǜ���h�G���"'5�̏��I,�������-��z�U�l6gu[����*^��������9���hд	aϞ=XL��|�F3�L]8��89�h4ڶowW�x��YT5�D�wlܑ}��k#@p�KNi�!<=�Ta��8��%�:Wf.�
          4�T����������yK������#��.�tE���i���󝍡����2Ov��|L�ƍ��h����6��T�5l�0YI������.��ʏb�Ĝ*/���;���0:l6�;����6o�\x�kP�]ڲѸ{���)S����������è7����7n|W��z����\t+Y,�, �^�z~jb�^�X�q�~��I��+��-8+�L�R�ړ*>>����)XR�N����G�Ν��.]k+���(��n�*\Semll�Y�%5�f͚>nݻs��f�p>��;]�S��4
          AAA�ī�/S��������#�����K�V���r��hl�������w`ZJj��������Ӎz�OR���l�y��ŋ��\���1�ug����kX�����q���ۇ_�o�055���Obha(�o���ˋ#_(���^P�Ga����q@�����h4���KKIk���Zr�*|�
          �ڵ�}��V�FFF�b�}�N�m��*��R��*oegۼR�Gٯ�i��"��O@�܂jժ���ݕąү_?�U+Yt���L"�z��'O�.k�G�����2l(����Z����|<�C�E�h��ਐ4�YmQAlp�p^��LY��|6�QՖ��ɖ�7�@)%o��v�^^^�6n,��_:�IQڴ}���g�v�:����*4nܘ�1���Ԯ][uPR�o���r%��{b>s]�*w�z5AUK�Ξ=��-[���i�R�^=���7��������VP4�Wxoz��Yf��[�nt��Q���o�9���R��^!̆04��yn��F�,YRi<~�8���������7�6o�̄7��������j��v;q�8�:�^^^x{{���M�5\~��o�>^{�U599YQT�ɡ8��.���\��\/s?C"��B)))�O�>�M�ejj�M�oX�A���m[��Q[�T�=eggˤ��R�.>>^���K54�KCSC7)%��ܰ�&''W�(�d����>}�'�z�Xs���L&O�̏�v3d�P�R1);;�-���i���FUU�7�G��9��J��nݺ|:}��8q�hu�r��r�W���ݻn;��f�bޜ���e+�i�u��y-���M��RŽ�ng�ƍ̟7�sg��F��00r�F�*�]���=sV��C1.3����ڕi&�\���s��1�Y�լu'Nti����%�9s�p���^Z��q�ۯ�a��mD��W�^ԨQ�8�WUU�oW36�@�s��ѷ�(�n�3u�TV,˱rwwgɲ��L
          (�d�;�5k&'N\.,�Q�7ccc��ܹ�6����T��yC�%!�!�hӦ
          O>�d�e�ʥK���7;--�#�as��<����@��!�\JR��X�ϻo������ƾ>������̚5�?�������+��ؼ��ݻwg���z��^!Dw!eK�GQ4}UU�z0���mk�7^��.X����t�re9��ȉ��l� &$%�ZGYuڼy�X�ݒ|:��]�0`@�Dž���_���L>��=��IM�6�U�)��b�6mڴ�V�TU5��˥��W͋/JEQ�fSy2�}�0�+�?����̙���Z��/��w�sR8xy��{�Uh����c��/8t�P�q��UƔ�TB��M9�`y`���'OOUU�DzZ��Z@���k�S���O�G+d��V++V�`񢯸z�j�m���\�p�c��3,�w���o�#������sv�f���R��B�$$7��‹#���ںE�:yڳ$���Pn4���ly(���������ڵk7��L���_���JJH`՚5�\����1�*�������o[Z�R��ą�kZ{ݺu�]��sH"��r<�3���)%F��2P͙��e��7D,+Ƿl�2�Ν���Y��z����Y�3c�e��=’������B�'֩S��g��21Kb���r0q
          dػ� ,猱L׿8VH��\���q�x�R��?\.Ϝ9�;��Á�E�w@@�^K�G��h�">�v��2&&�!��y��Wi۾�Mg��+W������۟OLp&��*�2�Z����cې����P������>g�-�t&���QR�5V�u{i���SE��](��XV��,_��ϦM'#�p�OOO�?3�#F�������sϑ���W�[E�<y�ѣG���I�Ӳe�\�O�8A������EjW�v;i���A�ԫW?W���e�z��Hɥ{^��C�<-�j�XI4/��\�r����[�ti��Η_~���n���C�A�0d��T)<������?w^��FKC�����F�n�زe�7��d��t̚3���1��B�4���=Yʥ���~���C�Ke#��P��)��M�}{:兼���6�in0���>��P���48���ț��#G�$,,�y���{�.��K���s�=�����^��[�~�a�ԩ���s��l|4�#֬[C�N�y�O�n�N��������\��Rn��`w^J������^����Ò�)_�b��� _���C��������)�H��/?�籿8s��Μ�f����woO<==�W�F���z�MO���ҥk�b��O�ѴyS��X�#�b���T2�
          ��	�fa� �� ��3G��h��a[�
          ]�=t���幏�t:"�g�ȑT����Ǐg��[x0�5/����㣩:��FŚ�s*���	�X}n��_��L�%`UA����%sZ�:u*���(�£��c���?~|�����ѣG9p�{��aϏ�9~�x���v]w:}&'Wdd$�w�Ĭ6!!��f݁7�����f��ʭ^��^x�Xۛ3g�p�pAAAL��Y��
          K�i���c�޽�ݻ�ؘC�����"�U�<��`�h4�4`��r��:����*)))�^�
          )����ZԩS�ג������܎C��p:&,@ߚ,�37�h���k�~%�k8gIJb�ƍDD�i����
          
          aڴi��	��Dm�b���p(�������E�N��Z��=G�ϟ�oҤI����es��&��5=��S����V��5��c/�v����/i��R��*ň;*NIU
          ���#������ٳg�<W��?��ٳ]��f���+��r�yT�~}ޜ��ڕ�����ҫZ5��ZQ�N��#�<—��q��i�v;R��ZES�Iu��T��;z�E���6C	h:PT���&�9/DJ�	��z���ǩ&''������o���oڜ��}q���V[�$��������oO/V�[C�ڵ�\
          r�_UUY�ti>ȩ�{&���.��=��B���,���E���m
          Qm�~QQQ����ĉy�@�*UX�zÆ
          +����L�8!O?+�$5=��^{�H���s߾}�[��������-�/0��&k�,D�Ŝ�`9���r=�J�ђ%K�L��Z-�>�{キ������:yډ�{��#r�@���#*�@OEȑ#��؟9|	�& �R�x�X�';�tn<�*��3Y����	�IILz��
          099�M6�}�ҭk�i�JK���cْ��r�'*jgE�3y��i�0P��y�ʧ�?���#���[U�6�l�a��5Y�-Ud�[9ga7`d1"E�ŜPb��=���{��+V��F��úvֵ���E��=؏]���c�X�ּ�}����W_�t�.�Ě�,K֡8�)��Trr�3f4#F��g�����t�5����-�^k����^�+�Q��a��/t!����Qoh	��<m<<<���ohڴi�8������M�E�=�ڵ�u�Ą�ؾsg��۾��u0�e�&M�(���E���gQ�D�I�&�nZ�f:�z���*�q��*9_����'j�����Zg���(R�-���Qo�$��*C����i�p��9��.Y�u�s�0)�Q�F�Y��̃�h�"���Ϝ�Q|c>l~���̡��essIJ"�؛@,�^ll�%��Z���|J�Att�99�J���y�&~�L)�k|lF*/�_?����Q&O.�����L�<9#z�~���b���b��4�	n�@�6���"TO@�*�i�5?��AԨ7h�IWTT��,���b>P�uJï��9o����<?|D�@�2�T�I���{I��\JLLdƌ�5�V�I)s�+C�f����#���T�-�L#s�f)qTv�ŜMN����燏�ȑ#���	����N��x�0yJzz:s�εu��5s��URJH�7�4kڱ$Q�o�b[����E4Iz�,�i�J��ݨ7x�)���yiM����=�����p8���o�Z���a�M���˗�9s�d���y\��F���U>�.��(�Q��2Y�%YV��&��JN������w�F�2����k���#�X���+�}��'���4�����b�TI��R�����L3���܁5�
          �Q�}��x�u�T*����|w-�'EQX�fu�V��d��7��r�)��ʅ�i?(k��[`[`P�.���b>Q�k��D�0�
          n������Z7&ԪG�g�&��ʻ�N�[��r���#x��Oa~ܵ��cǪ6Gv5ଊ|�p�J��>�(����2Y�	W4�
          /��Ix��)�IDAT:�:#�j��PD�Ȳ�}�e�%]#�q-00�
          �6�pF�g�F����R:f���B�2��E��5h�������n�{��ŝ���i�)��v��&��ZY����H���`�����Ӌ��,Nem?���ǂEiҤI�r)%=�z$_�p���"��X6� ���겭�'UD�����%?�0�d2�`���`jV�D���Q��\���!τ�㻗����C���X�N�}9�v�څ3�ِr��������*b9ƶmJ�@>�*3�*�`�ް��P�E�]`i����<]��Z�������3x���ԑ�?��_
          b}��-FH�4+�lUh'�,�+�%ӄ��^�_o�X�r!�9��h%v
          0�d1��q�V��h��g��]䜍L�nݺ��‹��ӻ���ƍ�b�I��DUh�zIR\_-�g�R���;��z7����R���ǗϚ,�S�oQ���zC�E)x	
          
          ��Ayꩧ
          5z��̤{�n1���%8X�+���F���d�SJ)#""4G㎎�>�$T�^-���]���
          u�W���I�;�&��B[܊0؎���M��[<<<x�cZ�nM�֭�e!���Xۦu�d�q2�r�#�b�)δ���7k����u����d��-�sx8��o�S\>��,�
          
          IrK@,� MNj���8�@HH�����voٲ�Y����[E$K!����7EGG�*��]�%�����b�Ŝy+�����40��x�ڔ�w~~~ؕ���	����$W]��;\�8>m��4�S0Xm���[9������`��v�ـ����W
          ���͛��f��@���S����T���������
          9g�C2^e�qd~r�z[M���}C��B����C�e-��o1u��
          �c��3*�xUJU4w�lSWj�
          v�g��OW���#@,X_��Yӱ��	t��4� ��7��wp���%�U���ٕ���IEND�B`�
        • logo.svg
          <?xml version="1.0" encoding="UTF-8" standalone="no"?>
          <!-- Created with Inkscape (http://www.inkscape.org/) -->
          
          <svg
             xmlns:dc="http://purl.org/dc/elements/1.1/"
             xmlns:cc="http://creativecommons.org/ns#"
             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
             xmlns:svg="http://www.w3.org/2000/svg"
             xmlns="http://www.w3.org/2000/svg"
             xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
             xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
             id="svg2"
             version="1.1"
             inkscape:version="0.48.4 r9939"
             width="640"
             height="640"
             xml:space="preserve"
             sodipodi:docname="logo.svg"
             inkscape:export-filename="/home/marijn/src/js/codemirror/doc/logo.png"
             inkscape:export-xdpi="16.601332"
             inkscape:export-ydpi="16.601332"><metadata
               id="metadata8"><rdf:RDF><cc:Work
                   rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
                     rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
               id="defs6"><clipPath
                 clipPathUnits="userSpaceOnUse"
                 id="clipPath16"><path
                   d="M 0,512 512,512 512,0 0,0 0,512 z"
                   id="path18" /></clipPath><clipPath
                 clipPathUnits="userSpaceOnUse"
                 id="clipPath40"><path
                   d="m 435.607,369.899 31.242,0 0,-64.782 -31.242,0 0,64.782 z"
                   id="path42" /></clipPath><clipPath
                 clipPathUnits="userSpaceOnUse"
                 id="clipPath56"><path
                   d="m 421.796,349.477 39.074,0 0,-88.423 -39.074,0 0,88.423 z"
                   id="path58" /></clipPath></defs><sodipodi:namedview
               pagecolor="#ffffff"
               bordercolor="#666666"
               borderopacity="1"
               objecttolerance="10"
               gridtolerance="10"
               guidetolerance="10"
               inkscape:pageopacity="0"
               inkscape:pageshadow="2"
               inkscape:window-width="1600"
               inkscape:window-height="875"
               id="namedview4"
               showgrid="false"
               showguides="true"
               inkscape:guide-bbox="true"
               inkscape:zoom="0.52149125"
               inkscape:cx="303.572"
               inkscape:cy="574.48012"
               inkscape:window-x="0"
               inkscape:window-y="25"
               inkscape:window-maximized="0"
               inkscape:current-layer="g10" /><g
               id="g10"
               inkscape:groupmode="layer"
               inkscape:label="2014-10_codeMirror_logo_vectors"
               transform="matrix(1.25,0,0,-1.25,0,640)"><path
                 inkscape:connector-curvature="0"
                 id="path22"
                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 233.97976,469.37438 c 0,0 7.01353,-14.94848 -2.94916,-31.42373 -4.97925,-8.23417 -130.50847,-34.94915 -179.50847,-102.94915 -30,-47 -76,-183 71,-273 66,-34 94,-33 94,-33 0,0 -44,31 -16,52 28,21 69,31 80,60 13,-10 34,-31 54,-29 -2,13 -7,18 9,20 16,2 24,2 24,2 0,0 -15,12 -32,13 -17,1 -49,34 -48,48 21,12 48,32 64,26 16,-6 32,-16 35,-25 0,-6 -3,-16 10,-8 13,8 10,13 15,24 5,11 6,13 -5,22 -11,9 -37,30 -58,24 -21,-6 -65,-23 -87,-2 9,20 23,52 16,74 13,10 28,21 30,39 15,2 47,11 41,27 -6,16 -48.59322,87.16949 -113.59322,73.16949"
                 sodipodi:nodetypes="cscccsccscscscsssscccsc" /><path
                 inkscape:connector-curvature="0"
                 id="path26"
                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 441.52213,306.0015 c 11,29 29,78 12,80 -17,2 -36,-44 -41,-56 -5,-12 -25,-72 -14,-80 11,-8 43,56 43,56" /><path
                 inkscape:connector-curvature="0"
                 id="path30"
                 style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 348.52213,384.0015 c 3.13,4.919 5.82086,0.64508 -7.67914,-0.35492 -13.5,-1 -29.62196,-5.18461 -32.38899,-11.04836 -5.19174,-11.00208 -6.93187,-38.09672 -26.43187,-44.09672 -1,-7 0,-23 27.5,-26 27.5,-3 28.5,15 44.5,14.5 16,-0.5 14.5,5.5 9,10 -5.5,4.5 -24.5,35 -24.5,45 0,10 6.5,6.5 10,12"
                 sodipodi:nodetypes="csscssssc" /><path
                 inkscape:connector-curvature="0"
                 id="path34"
                 style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 103.02213,82.502 c 0,0 -8.5,22.5 16.5,34.5 25,12 47.5,2.5 52,-6 4.5,-8.5 -7.5,-42.5 -50.5,-43 -10.5,8.5 -18,14.5 -18,14.5" /><g
                 id="g38"
                 transform="translate(-21.47687,0)" /><g
                 id="g44"
                 transform="translate(-21.47687,0)"><g
                   style="opacity:0.69999701"
                   id="g46"
                   clip-path="url(#clipPath40)"><g
                     id="g48"
                     transform="translate(466.2583,369.8384)"><path
                       inkscape:connector-curvature="0"
                       id="path50"
                       style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"
                       d="M 0,0 C 0.423,-1.569 0.298,-3.199 0.255,-4.838 0.213,-6.452 0.062,-8.15 -0.349,-9.801 c 0.106,-0.377 -0.082,-0.814 -0.018,-1.201 -0.41,-0.515 -0.194,-0.903 -0.284,-1.354 0.661,-0.674 1.522,-1.313 1.152,-2.162 -0.259,-0.596 -0.874,-0.706 -1.464,-0.995 -0.389,-1.403 -0.709,-3.099 -1.028,-4.649 -0.097,-0.476 -0.044,-1.051 -0.187,-1.485 -0.334,-1.01 -0.691,-1.978 -0.971,-3.09 -0.237,-0.945 0.034,-2.689 -1.063,-2.811 -0.423,-1.049 -0.663,-1.841 -1.165,-2.83 -0.286,-0.163 -0.452,0.106 -0.692,0.009 -0.305,-0.348 -0.294,-0.823 -0.577,-1.114 -0.222,-0.229 -0.503,-0.163 -0.665,-0.385 -0.363,-0.5 -0.266,-1.24 -0.523,-1.902 -0.468,-0.4 -0.862,-0.905 -1.147,-1.478 -0.588,-1.179 -0.698,-2.681 -1.591,-3.593 -0.28,-0.286 -0.761,-0.365 -1.011,-0.647 -0.238,-0.269 -0.455,-0.665 -0.689,-0.98 -0.338,-0.452 -0.669,-1.045 -0.972,-1.583 -1.004,-1.787 -2.383,-3.71 -3.301,-5.664 -0.173,-0.369 -0.199,-0.805 -0.364,-1.165 -0.381,-0.827 -0.943,-1.579 -1.257,-2.333 -0.516,-1.239 -1.31,-3.339 -2.538,-4.42 -0.149,-0.131 -0.473,-0.254 -0.606,-0.414 -0.179,-0.215 -0.136,-0.568 -0.32,-0.808 -0.086,-0.113 -0.4,-0.164 -0.537,-0.302 -0.208,-0.211 -0.306,-0.481 -0.479,-0.639 -0.426,-0.388 -1.015,-0.555 -1.381,-0.959 -0.277,-0.306 -0.397,-0.743 -0.692,-1.127 -0.318,-0.413 -0.761,-0.784 -1.09,-1.202 -0.994,-1.264 -1.38,-2.8 -2.702,-3.396 -0.393,-0.178 -0.88,-0.12 -1.291,-0.241 -0.374,0.344 -0.078,0.818 -0.163,1.164 -0.055,0.222 -0.285,0.382 -0.346,0.583 -0.143,0.474 -0.347,1.336 -0.34,1.878 0.007,0.538 0.305,0.971 0.375,1.612 0.061,0.549 -0.137,1.246 -0.177,1.856 -0.021,0.306 0.064,0.624 0.059,0.956 -0.008,0.533 -0.066,0.801 0.008,1.442 0.086,0.743 -0.074,1.462 -0.171,2.152 0.342,1.705 0.531,3.008 1.09,4.919 0.258,0.881 0.721,2.367 1.18,3.346 0.886,1.895 1.64,3.964 2.6,5.945 0.319,0.656 0.825,1.196 1.139,1.852 0.182,0.381 0.211,0.828 0.395,1.215 1.617,3.398 3.877,6.233 5.565,9.731 1.399,2.859 2.88,5.418 4.745,8.545 0.842,1.415 1.568,2.917 2.434,4.086 0.66,0.891 1.632,2.413 2.334,3.916 0.278,0.596 0.269,1.073 1.005,1.102 0.758,0.948 1.326,2.018 2.119,2.824 0.2,0.202 0.51,0.303 0.733,0.498 0.26,0.228 0.383,0.57 0.638,0.778 0.541,0.441 1.432,0.832 2.035,1.659 0.16,0.22 0.229,0.451 0.406,0.682 0.414,0.539 1.191,1.866 1.81,2.013 C -0.241,0.085 -0.126,0.061 0,0" /></g></g></g><g
                 id="g54"
                 transform="translate(-21.47687,0)" /><g
                 id="g60"
                 transform="translate(-21.47687,0)"><g
                   style="opacity:0.69999701"
                   id="g62"
                   clip-path="url(#clipPath56)"><g
                     id="g64"
                     transform="translate(459.8965,349.4487)"><path
                       inkscape:connector-curvature="0"
                       id="path66"
                       style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"
                       d="m 0,0 c 0.688,-1.936 0.765,-4.106 0.935,-6.266 -0.019,-2.14 -0.168,-4.579 -0.715,-6.943 0.098,-0.492 -0.155,-1.108 -0.109,-1.623 -0.519,-0.752 -0.295,-1.25 -0.438,-1.876 0.718,-0.835 1.666,-1.609 1.155,-2.836 -0.37,-0.846 -1.118,-1.037 -1.845,-1.479 -0.64,-1.905 -1.226,-4.263 -1.846,-6.305 -0.187,-0.635 -0.212,-1.395 -0.447,-1.977 -0.547,-1.362 -1.111,-2.656 -1.597,-4.101 -0.416,-1.238 -0.356,-3.498 -1.652,-3.689 -0.61,-1.355 -0.978,-2.373 -1.674,-3.651 -0.35,-0.217 -0.512,0.119 -0.801,-0.013 -0.392,-0.456 -0.442,-1.063 -0.795,-1.445 -0.269,-0.298 -0.585,-0.226 -0.785,-0.514 -0.449,-0.651 -0.386,-1.58 -0.723,-2.425 -0.282,-0.266 -0.546,-0.564 -0.784,-0.888 -0.119,-0.162 -0.233,-0.33 -0.337,-0.505 l -0.153,-0.266 -0.072,-0.136 -0.034,-0.069 -0.003,-0.004 0,-10e-4 c 0.099,0.238 0.028,0.066 0.05,0.119 l -10e-4,-0.002 -0.001,-10e-4 -0.004,-0.01 -0.008,-0.019 -0.016,-0.037 c -0.697,-1.635 -0.851,-3.63 -1.895,-4.955 -0.335,-0.421 -0.872,-0.577 -1.142,-0.971 -0.259,-0.375 -0.491,-0.912 -0.746,-1.347 -0.366,-0.625 -0.722,-1.432 -1.046,-2.164 -1.085,-2.456 -2.571,-5.274 -3.572,-8.03 -0.188,-0.523 -0.205,-1.106 -0.385,-1.617 -0.422,-1.173 -1.022,-2.273 -1.394,-3.342 -0.626,-1.753 -1.474,-4.727 -3.01,-6.377 -0.182,-0.2 -0.567,-0.415 -0.732,-0.65 -0.22,-0.315 -0.191,-0.786 -0.42,-1.137 -0.106,-0.164 -0.475,-0.275 -0.642,-0.48 -0.254,-0.313 -0.383,-0.69 -0.594,-0.926 -0.503,-0.581 -1.23,-0.865 -1.714,-1.438 -0.365,-0.435 -0.562,-1.029 -0.958,-1.568 -0.426,-0.578 -0.991,-1.104 -1.428,-1.683 -0.65,-0.928 -1.251,-1.786 -1.828,-2.608 -0.592,-0.813 -1.215,-1.514 -2.047,-1.884 -0.495,-0.219 -1.042,-0.12 -1.539,-0.256 -0.353,0.473 0.086,1.071 0.061,1.524 -0.018,0.288 -0.25,0.504 -0.28,0.766 -0.07,0.615 -0.141,1.712 -0.035,2.387 0.099,0.676 0.548,1.191 0.712,2.005 0.125,0.708 -0.034,1.591 -0.025,2.359 0.004,0.387 0.13,0.791 0.153,1.206 0.038,0.668 -0.008,0.999 0.13,1.795 0.163,0.922 -0.034,1.854 -0.121,2.709 0.426,2.191 0.686,3.806 1.265,6.362 0.273,1.176 0.786,3.104 1.265,4.488 0.472,1.315 0.904,2.681 1.347,4.063 0.445,1.4 0.906,2.841 1.424,4.249 0.347,0.939 0.896,1.734 1.274,2.728 0.213,0.565 0.249,1.192 0.465,1.767 0.475,1.25 0.99,2.514 1.541,3.656 0.553,1.123 1.13,2.228 1.711,3.336 l 0.938,1.807 c 0.326,0.58 0.653,1.161 0.981,1.745 0.649,1.172 1.283,2.367 1.886,3.609 1.027,1.966 2.073,3.828 3.188,5.725 1.116,1.844 2.324,3.757 3.629,5.817 1.158,1.853 2.248,3.825 3.357,5.355 0.827,1.167 2.173,3.163 3.042,5.126 0.342,0.78 0.349,1.38 1.197,1.482 0.907,1.274 1.649,2.697 2.452,3.773 0.214,0.276 0.563,0.445 0.808,0.722 0.286,0.323 0.408,0.762 0.693,1.065 0.582,0.653 1.672,1.277 2.21,2.569 0.151,0.332 0.198,0.653 0.368,1.006 0.397,0.822 1.098,2.779 1.78,3.145 C -0.284,0.044 -0.151,0.044 0,0" /></g></g></g><path
                 inkscape:connector-curvature="0"
                 id="path70"
                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 416.68863,327.0015 c 0,0 -8,-30.667 -4.667,-56 0.667,8 4.667,56 4.667,56" /><path
                 inkscape:connector-curvature="0"
                 id="path74"
                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 426.18913,347.7256 c -0.61,2.147 -4.597,-59.478 -3.432,-61.636 1.166,-2.159 7.147,48.575 3.432,61.636" /><path
                 inkscape:connector-curvature="0"
                 id="path78"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 235.24913,465.60369 c 0,0 4.667,-26.6198 -38.667,-40.6198 -43.333,-14 -103.0605,-25.98239 -147.0605,-78.64939 -44.0000004,-52.666 -52.0000004,-139.999 -22,-197.333 30,-57.333 103.333,-128.667 235.333,-128.667 132,0 236.85312,101.50582 236.85312,171.50582 0,36.667 -20.1469,28.4918 -27.11433,-5.90828 C 466.30468,154.88286 408.18863,39.0015 262.18863,39.0015 c -146,0 -220.667,88.667 -230,164.667 -9.334,76 11.898969,141.46925 88.56597,180.80225 76.667,39.334 125.32039,23.66435 114.65339,80.99735"
                 sodipodi:nodetypes="cssssssscsc" /><path
                 inkscape:connector-curvature="0"
                 id="path82"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 198.85713,260.335 c 0,0 -8.667,-40.001 -50.667,-59.333 -42,-19.334 -60,-30 -66,-63.334 16,26.666 62.667,32 88.667,58 26,26 28,64.667 28,64.667" /><path
                 inkscape:connector-curvature="0"
                 id="path86"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 210.19013,353.0015 c 0,0 36,-46.667 78.667,-24 42.666,22.667 20.667,75.333 20,78.667 -0.667,3.333 4.666,-58.667 -27.334,-69.334 -32,-10.666 -71.333,14.667 -71.333,14.667" /><path
                 inkscape:connector-curvature="0"
                 id="path90"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 116.18913,74.3359 c 0,0 22.666,-1.334 39.333,17.332 16.667,18.668 7.334,48 34.667,58.668 27.333,10.666 46,4 46,4 0,0 -48.667,-6.668 -52.667,-34.668 -4,-28 -10.666,-40.666 -21.333,-49.332 -10.667,-8.668 -24.667,-10 -24.667,-10 l -21.333,14 z" /><path
                 inkscape:connector-curvature="0"
                 id="path94"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 219.02213,219.502 c 0,0 40.523,6.783 59,48 15.167,33.833 5,63 5,63 l -20.5,-3 c 0,0 8.5,-24.5 2,-46.5 -6.5,-22 -21.5,-47.5 -45.5,-61.5" /><path
                 inkscape:connector-curvature="0"
                 id="path98"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 437.13303,313.1621 c -14.461,-36.13 -35.773,-62.068 -38.265,-60.674 -4.494,2.513 -0.358,34.036 14.104,70.166 14.46,36.13 32.432,63.635 39.104,61.014 6.672,-2.621 -0.483,-34.376 -14.943,-70.506 m 20.999,72.506 c -16.442,8.934 -36.644,-24.449 -53.276,-63.334 -16.633,-38.885 -18.542,-70.229 -5.759,-75.836 17.092,-7.496 33.127,22.285 49.759,61.17 16.632,38.885 24,70 9.276,78" /><path
                 inkscape:connector-curvature="0"
                 id="path102"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 159.52163,189.668 c 0,0 10.331,-31.037 62,-24.666 48.667,6 69.59,24.744 99.333,43.334 21.334,13.332 20,7.332 22.667,6.666 2.667,-0.666 14.667,-8 27.333,-6.666 0.667,-6.668 -5.999,-1.334 -8.666,-7.334 -1.333,-4 10.12,-22.824 26.666,-20 27.334,4.666 19.667,16 25.001,28.666 5.333,12.666 9,19.334 -17.667,37.334 -20.667,18.666 -32,13.999 -42,13.999 -10,0 -36,-13.999 -54,-10.666 -18,3.333 -29.334,10 -29.334,10 l -11.999,-13.333 c 0,0 21.999,-16.666 47.333,-10.666 25.333,6 44.001,25.332 66.001,15.332 22,-10 26.282,-16.701 32.999,-21.666 7.667,-5.668 8.333,-11.666 3,-17 -5.334,-5.334 0.001,-9.334 -3.332,-15.334 -3.334,-6 -20,-8.666 -20,-8.666 0,0 18.273,23.477 -4,25.332 -16,1.334 -26,22.668 -48.667,11.334 -32.55,-16.277 -78.668,-44 -110.668,-47.332 -31.193,-3.248 -42.667,6.666 -50.667,25.332 -9.333,-8 -11.333,-14 -11.333,-14" /><path
                 inkscape:connector-curvature="0"
                 id="path106"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 274.18863,183.002 c 0,0 22.667,-12 16,-38 -6.667,-26 -36.667,-44 -56,-52.668 -19.333,-8.666 -33.743,-20.127 -19.333,-27.332 12,-6 18.667,9.334 36,12 17.333,2.666 32.667,-4 34,-14 -7.334,4 -12.667,4 -12.667,4 0,0 6,-4 6.667,-10.668 0.666,-6.666 -0.667,-3.332 -4.667,-3.332 -10,0 -11.333,8.666 -20,7.332 -22,-2 -23.333,-11.334 -35.333,-12.666 -12,-1.334 -32,5.334 -29.334,20.666 2.667,15.334 23.334,26 42.667,34 19.333,8 48.667,33.334 44.667,56 -4,22.668 -21.334,18 -21.334,18 l 18.667,6.668 z" /><path
                 inkscape:connector-curvature="0"
                 id="path110"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 331.02213,371.7515 c 0,0 9.5,-4.75 15.5,-28.75 4,-8.667 9.333,-15.667 14,-17.667 4.667,-2 -2,-4 -5.333,-3.333 -3.334,0.667 -10.334,3.667 -15,-0.333 -4.667,-4 -16,-14.667 -32,-12 -16,2.666 -29.667,12.833 -29.667,12.833 0,0 6,-26.5 41.667,-24.833 24.721,1.155 19.333,14 36,16.666 16.666,2.667 14.893,11.089 11.333,18 -5.667,11 -23.333,13.667 -25.333,45.834 -2,3.333 -14.5,-0.417 -11.167,-6.417" /><path
                 inkscape:connector-curvature="0"
                 id="path114"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 388.01383,204.4707 c 1.506,-1.477 -11.825,-31.469 -11.825,-31.469 0,0 -2.667,-7.334 -9.814,-4.75 -7.311,2.645 -5.413,7.948 -5.413,7.948 l 17.026,30.837 c 0,0 9.353,-1.906 10.026,-2.566" /><path
                 inkscape:connector-curvature="0"
                 id="path118"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 406.74623,247.168 c -0.667,-2 -3.333,-10 -3.333,-10 l -10.891,8.334 2.891,6.332 11.333,-4.666 z" /><path
                 inkscape:connector-curvature="0"
                 id="path122"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 284.85563,189.002 c -2,-7.334 23.333,-50.002 40.667,-47.334 17.333,2.666 19.999,-2.668 14.666,-6 -5.333,-3.334 -14.666,-4.668 -13.333,-9.334 1.333,-4.666 5,-9.334 -3.667,-8 -8.666,1.334 -26.333,10.668 -37,28.668 -3.333,-10.668 -4.666,-14 -4.666,-14 0,0 34,-35.334 68.666,-20.668 -6,4.668 -22.666,3.334 -8.666,11.334 14,8 24.666,10.666 31.333,-2 3.333,0.666 3.333,30 -40.667,28 -15.333,2 -36,32 -36,47.334 -4,-4 -9.333,-0.666 -11.333,-8" /><path
                 inkscape:connector-curvature="0"
                 id="path126"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 420.44553,336.5015 c 0,0 -8.75,-26.286 -5.104,-48 0.729,6.857 5.104,48 5.104,48" /><path
                 inkscape:connector-curvature="0"
                 id="path130"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 429.40543,352.0503 c -0.444,1.66 -4.07,-45.761 -3.203,-47.435 0.868,-1.673 5.909,37.339 3.203,47.435" /><path
                 inkscape:connector-curvature="0"
                 id="path134"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 312.85513,378.335 c 0,0 37.667,3.333 31,18.333 -20.105,45.239 -58.333,71.667 -129,69 40,16 74.00021,14.00025 106.667,-14 16.33311,-13.99988 23.89324,-31.04069 29.74979,-44.08296 9.34044,-20.80074 6.58914,-22.74696 -3.74979,-28.58304 -12.56847,-7.0946 -34.191,-2.57 -34.667,-0.667"
                 sodipodi:nodetypes="cccsssc" /><path
                 inkscape:connector-curvature="0"
                 id="path138"
                 style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
                 d="m 316.7084,372.58242 c 0,0 10.36415,-7.13802 18.50215,-1.32602 3.74086,3.84884 6.23323,5.95026 -4.37137,5.51213 l -12.90479,0.52875 c -8.94116,1.82452 -8.7647,-0.93753 -1.22599,-4.71486 z"
                 sodipodi:nodetypes="ccccc" /></g></svg>
        • manual.html
          <!doctype html>
          
          <title>CodeMirror: User Manual</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="activebookmark.js"></script>
          
          <script src="../lib/codemirror.js"></script>
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../addon/runmode/runmode.js"></script>
          <script src="../addon/runmode/colorize.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <style>
            dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }
            dd { margin-left: 1.5em; margin-bottom: 1em; }
            dt {margin-top: 1em;}
            dd dl, dd dt, dd dd, dd ul { margin-top: 0; margin-bottom: 0; }
            dt + dt { margin-top: 0; }
            dt.command { position: relative; }
            span.keybinding { position: absolute; right: 0; font-size: 80%; color: #555; text-indent: 0; }
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
            <ul>
              <li><a href="../index.html">Home</a></li>
              <li><a href="#overview" class=active data-default="true">Manual</a></li>
              <li><a href="https://github.com/codemirror/codemirror">Code</a></li>
            </ul>
            <ul>
              <li><a href="#usage">Basic Usage</a></li>
              <li><a href="#config">Configuration</a></li>
              <li><a href="#events">Events</a></li>
              <li><a href="#keymaps">Key maps</a></li>
              <li><a href="#commands">Commands</a></li>
              <li><a href="#styling">Customized Styling</a></li>
              <li><a href="#api">Programming API</a>
                <ul>
                  <li><a href="#api_constructor">Constructor</a></li>
                  <li><a href="#api_content">Content manipulation</a></li>
                  <li><a href="#api_selection">Selection</a></li>
                  <li><a href="#api_configuration">Configuration</a></li>
                  <li><a href="#api_doc">Document management</a></li>
                  <li><a href="#api_history">History</a></li>
                  <li><a href="#api_marker">Text-marking</a></li>
                  <li><a href="#api_decoration">Widget, gutter, and decoration</a></li>
                  <li><a href="#api_sizing">Sizing, scrolling, and positioning</a></li>
                  <li><a href="#api_mode">Mode, state, and tokens</a></li>
                  <li><a href="#api_misc">Miscellaneous methods</a></li>
                  <li><a href="#api_static">Static properties</a></li>
                </ul>
              </li>
              <li><a href="#addons">Addons</a></li>
              <li><a href="#modeapi">Writing CodeMirror Modes</a></li>
            </ul>
          </div>
          
          <article>
          
          <section class=first id=overview>
              <h2 style="position: relative">
                User manual and reference guide
                <span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.0.1</span>
              </h2>
          
              <p>CodeMirror is a code-editor component that can be embedded in
              Web pages. The core library provides <em>only</em> the editor
              component, no accompanying buttons, auto-completion, or other IDE
              functionality. It does provide a rich API on top of which such
              functionality can be straightforwardly implemented. See
              the <a href="#addons">addons</a> included in the distribution,
              and the <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">list
              of externally hosted addons</a>, for reusable
              implementations of extra features.</p>
          
              <p>CodeMirror works with language-specific modes. Modes are
              JavaScript programs that help color (and optionally indent) text
              written in a given language. The distribution comes with a number
              of modes (see the <a href="../mode/"><code>mode/</code></a>
              directory), and it isn't hard to <a href="#modeapi">write new
              ones</a> for other languages.</p>
          </section>
          
          <section id=usage>
              <h2>Basic Usage</h2>
          
              <p>The easiest way to use CodeMirror is to simply load the script
              and style sheet found under <code>lib/</code> in the distribution,
              plus a mode script from one of the <code>mode/</code> directories.
              (See <a href="compress.html">the compression helper</a> for an
              easy way to combine scripts.) For example:</p>
          
              <pre data-lang="text/html">&lt;script src="lib/codemirror.js">&lt;/script>
          &lt;link rel="stylesheet" href="../lib/codemirror.css">
          &lt;script src="mode/javascript/javascript.js">&lt;/script></pre>
          
              <p>(Alternatively, use a module loader. <a href="#modloader">More
              about that later.</a>)</p>
          
              <p>Having done this, an editor instance can be created like
              this:</p>
          
              <pre data-lang="javascript">var myCodeMirror = CodeMirror(document.body);</pre>
          
              <p>The editor will be appended to the document body, will start
              empty, and will use the mode that we loaded. To have more control
              over the new editor, a configuration object can be passed
              to <a href="#CodeMirror"><code>CodeMirror</code></a> as a second
              argument:</p>
          
              <pre data-lang="javascript">var myCodeMirror = CodeMirror(document.body, {
            value: "function myScript(){return 100;}\n",
            mode:  "javascript"
          });</pre>
          
              <p>This will initialize the editor with a piece of code already in
              it, and explicitly tell it to use the JavaScript mode (which is
              useful when multiple modes are loaded).
              See <a href="#config">below</a> for a full discussion of the
              configuration options that CodeMirror accepts.</p>
          
              <p>In cases where you don't want to append the editor to an
              element, and need more control over the way it is inserted, the
              first argument to the <code>CodeMirror</code> function can also
              be a function that, when given a DOM element, inserts it into the
              document somewhere. This could be used to, for example, replace a
              textarea with a real editor:</p>
          
              <pre data-lang="javascript">var myCodeMirror = CodeMirror(function(elt) {
            myTextArea.parentNode.replaceChild(elt, myTextArea);
          }, {value: myTextArea.value});</pre>
          
              <p>However, for this use case, which is a common way to use
              CodeMirror, the library provides a much more powerful
              shortcut:</p>
          
              <pre data-lang="javascript">var myCodeMirror = CodeMirror.fromTextArea(myTextArea);</pre>
          
              <p>This will, among other things, ensure that the textarea's value
              is updated with the editor's contents when the form (if it is part
              of a form) is submitted. See the <a href="#fromTextArea">API
              reference</a> for a full description of this method.</p>
          
              <h3 id=modloader>Module loaders</h3>
          
              <p>The files in the CodeMirror distribution contain shims for
              loading them (and their dependencies) in AMD or CommonJS
              environments. If the variables <code>exports</code>
              and <code>module</code> exist and have type object, CommonJS-style
              require will be used. If not, but there is a
              function <code>define</code> with an <code>amd</code> property
              present, AMD-style (RequireJS) will be used.</p>
          
              <p>It is possible to
              use <a href="http://browserify.org/">Browserify</a> or similar
              tools to statically build modules using CodeMirror. Alternatively,
              use <a href="http://requirejs.org/">RequireJS</a> to dynamically
              load dependencies at runtime. Both of these approaches have the
              advantage that they don't use the global namespace and can, thus,
              do things like load multiple versions of CodeMirror alongside each
              other.</p>
          
              <p>Here's a simple example of using RequireJS to load CodeMirror:</p>
          
              <pre data-lang="javascript">require([
            "cm/lib/codemirror", "cm/mode/htmlmixed/htmlmixed"
          ], function(CodeMirror) {
            CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              mode: "htmlmixed"
            });
          });</pre>
          
              <p>It will automatically load the modes that the mixed HTML mode
              depends on (XML, JavaScript, and CSS).</p>
          
          </section>
          
          <section id=config>
              <h2>Configuration</h2>
          
              <p>Both the <a href="#CodeMirror"><code>CodeMirror</code></a>
              function and its <code>fromTextArea</code> method take as second
              (optional) argument an object containing configuration options.
              Any option not supplied like this will be taken
              from <a href="#defaults"><code>CodeMirror.defaults</code></a>, an
              object containing the default options. You can update this object
              to change the defaults on your page.</p>
          
              <p>Options are not checked in any way, so setting bogus option
              values is bound to lead to odd errors.</p>
          
              <p>These are the supported options:</p>
          
              <dl>
                <dt id="option_value"><code><strong>value</strong>: string|CodeMirror.Doc</code></dt>
                <dd>The starting value of the editor. Can be a string, or
                a <a href="#api_doc">document object</a>.</dd>
          
                <dt id="option_mode"><code><strong>mode</strong>: string|object</code></dt>
                <dd>The mode to use. When not given, this will default to the
                first mode that was loaded. It may be a string, which either
                simply names the mode or is
                a <a href="http://en.wikipedia.org/wiki/MIME">MIME</a> type
                associated with the mode. Alternatively, it may be an object
                containing configuration options for the mode, with
                a <code>name</code> property that names the mode (for
                example <code>{name: "javascript", json: true}</code>). The demo
                pages for each mode contain information about what configuration
                parameters the mode supports. You can ask CodeMirror which modes
                and MIME types have been defined by inspecting
                the <code>CodeMirror.modes</code>
                and <code>CodeMirror.mimeModes</code> objects. The first maps
                mode names to their constructors, and the second maps MIME types
                to mode specs.</dd>
          
                <dt id="option_theme"><code><strong>theme</strong>: string</code></dt>
                <dd>The theme to style the editor with. You must make sure the
                CSS file defining the corresponding <code>.cm-s-[name]</code>
                styles is loaded (see
                the <a href="../theme/"><code>theme</code></a> directory in the
                distribution). The default is <code>"default"</code>, for which
                colors are included in <code>codemirror.css</code>. It is
                possible to use multiple theming classes at once—for
                example <code>"foo bar"</code> will assign both
                the <code>cm-s-foo</code> and the <code>cm-s-bar</code> classes
                to the editor.</dd>
          
                <dt id="option_indentUnit"><code><strong>indentUnit</strong>: integer</code></dt>
                <dd>How many spaces a block (whatever that means in the edited
                language) should be indented. The default is 2.</dd>
          
                <dt id="option_smartIndent"><code><strong>smartIndent</strong>: boolean</code></dt>
                <dd>Whether to use the context-sensitive indentation that the
                mode provides (or just indent the same as the line before).
                Defaults to true.</dd>
          
                <dt id="option_tabSize"><code><strong>tabSize</strong>: integer</code></dt>
                <dd>The width of a tab character. Defaults to 4.</dd>
          
                <dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
                <dd>Whether, when indenting, the first N*<code>tabSize</code>
                spaces should be replaced by N tabs. Default is false.</dd>
          
                <dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
                <dd>Configures whether the editor should re-indent the current
                line when a character is typed that might change its proper
                indentation (only works if the mode supports indentation).
                Default is true.</dd>
          
                <dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
                <dd>A regular expression used to determine which characters
                should be replaced by a
                special <a href="#option_specialCharPlaceholder">placeholder</a>.
                Mostly useful for non-printing special characters. The default
                is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
                <dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
                <dd>A function that, given a special character identified by
                the <a href="#option_specialChars"><code>specialChars</code></a>
                option, produces a DOM node that is used to represent the
                character. By default, a red dot (<span style="color: red">•</span>)
                is shown, with a title tooltip to indicate the character code.</dd>
          
                <dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
                <dd>Determines whether horizontal cursor movement through
                right-to-left (Arabic, Hebrew) text is visual (pressing the left
                arrow moves the cursor left) or logical (pressing the left arrow
                moves to the next lower index in the string, which is visually
                right in right-to-left text). The default is <code>false</code>
                on Windows, and <code>true</code> on other platforms.</dd>
          
                <dt id="option_keyMap"><code><strong>keyMap</strong>: string</code></dt>
                <dd>Configures the key map to use. The default
                is <code>"default"</code>, which is the only key map defined
                in <code>codemirror.js</code> itself. Extra key maps are found in
                the <a href="../keymap/"><code>key map</code></a> directory. See
                the <a href="#keymaps">section on key maps</a> for more
                information.</dd>
          
                <dt id="option_extraKeys"><code><strong>extraKeys</strong>: object</code></dt>
                <dd>Can be used to specify extra key bindings for the editor,
                alongside the ones defined
                by <a href="#option_keyMap"><code>keyMap</code></a>. Should be
                either null, or a valid <a href="#keymaps">key map</a> value.</dd>
          
                <dt id="option_lineWrapping"><code><strong>lineWrapping</strong>: boolean</code></dt>
                <dd>Whether CodeMirror should scroll or wrap for long lines.
                Defaults to <code>false</code> (scroll).</dd>
          
                <dt id="option_lineNumbers"><code><strong>lineNumbers</strong>: boolean</code></dt>
                <dd>Whether to show line numbers to the left of the editor.</dd>
          
                <dt id="option_firstLineNumber"><code><strong>firstLineNumber</strong>: integer</code></dt>
                <dd>At which number to start counting lines. Default is 1.</dd>
          
                <dt id="option_lineNumberFormatter"><code><strong>lineNumberFormatter</strong>: function(line: integer) → string</code></dt>
                <dd>A function used to format line numbers. The function is
                passed the line number, and should return a string that will be
                shown in the gutter.</dd>
          
                <dt id="option_gutters"><code><strong>gutters</strong>: array&lt;string&gt;</code></dt>
                <dd>Can be used to add extra gutters (beyond or instead of the
                line number gutter). Should be an array of CSS class names, each
                of which defines a <code>width</code> (and optionally a
                background), and which will be used to draw the background of
                the gutters. <em>May</em> include
                the <code>CodeMirror-linenumbers</code> class, in order to
                explicitly set the position of the line number gutter (it will
                default to be to the right of all other gutters). These class
                names are the keys passed
                to <a href="#setGutterMarker"><code>setGutterMarker</code></a>.</dd>
          
                <dt id="option_fixedGutter"><code><strong>fixedGutter</strong>: boolean</code></dt>
                <dd>Determines whether the gutter scrolls along with the content
                horizontally (false) or whether it stays fixed during horizontal
                scrolling (true, the default).</dd>
          
                <dt id="option_scrollbarStyle"><code><strong>scrollbarStyle</strong>: string</code></dt>
                <dd>Chooses a scrollbar implementation. The default
                is <code>"native"</code>, showing native scrollbars. The core
                library also provides the <code>"null"</code> style, which
                completely hides the
                scrollbars. <a href="#addon_simplescrollbars">Addons</a> can
                implement additional scrollbar models.</dd>
          
                <dt id="option_coverGutterNextToScrollbar"><code><strong>coverGutterNextToScrollbar</strong>: boolean</code></dt>
                <dd>When <a href="#option_fixedGutter"><code>fixedGutter</code></a>
                is on, and there is a horizontal scrollbar, by default the
                gutter will be visible to the left of this scrollbar. If this
                option is set to true, it will be covered by an element with
                class <code>CodeMirror-gutter-filler</code>.</dd>
          
                <dt id="option_inputStyle"><code><strong>inputStyle</strong>: string</code></dt>
                <dd>Selects the way CodeMirror handles input and focus. The core
                library defines the <code>"textarea"</code>
                and <code>"contenteditable"</code> input models. On mobile
                browsers, the default is <code>"contenteditable"</code>. On
                desktop browsers, the default is <code>"textarea"</code>.
                Support for IME and screen readers is better in
                the <code>"contenteditable"</code> model. The intention is to
                make it the default on modern desktop browsers in the
                future.</dd>
          
                <dt id="option_readOnly"><code><strong>readOnly</strong>: boolean|string</code></dt>
                <dd>This disables editing of the editor content by the user. If
                the special value <code>"nocursor"</code> is given (instead of
                simply <code>true</code>), focusing of the editor is also
                disallowed.</dd>
          
                <dt id="option_showCursorWhenSelecting"><code><strong>showCursorWhenSelecting</strong>: boolean</code></dt>
                <dd>Whether the cursor should be drawn when a selection is
                active. Defaults to false.</dd>
          
                <dt id="option_undoDepth"><code><strong>undoDepth</strong>: integer</code></dt>
                <dd>The maximum number of undo levels that the editor stores.
                Note that this includes selection change events. Defaults to
                200.</dd>
          
                <dt id="option_historyEventDelay"><code><strong>historyEventDelay</strong>: integer</code></dt>
                <dd>The period of inactivity (in milliseconds) that will cause a
                new history event to be started when typing or deleting.
                Defaults to 1250.</dd>
          
                <dt id="option_tabindex"><code><strong>tabindex</strong>: integer</code></dt>
                <dd>The <a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex">tab
                index</a> to assign to the editor. If not given, no tab index
                will be assigned.</dd>
          
                <dt id="option_autofocus"><code><strong>autofocus</strong>: boolean</code></dt>
                <dd>Can be used to make CodeMirror focus itself on
                initialization. Defaults to off.
                When <a href="#fromTextArea"><code>fromTextArea</code></a> is
                used, and no explicit value is given for this option, it will be
                set to true when either the source textarea is focused, or it
                has an <code>autofocus</code> attribute and no other element is
                focused.</dd>
              </dl>
          
              <p>Below this a few more specialized, low-level options are
              listed. These are only useful in very specific situations, you
              might want to skip them the first time you read this manual.</p>
          
              <dl>
                <dt id="option_dragDrop"><code><strong>dragDrop</strong>: boolean</code></dt>
                <dd>Controls whether drag-and-drop is enabled. On by default.</dd>
          
                <dt id="option_cursorBlinkRate"><code><strong>cursorBlinkRate</strong>: number</code></dt>
                <dd>Half-period in milliseconds used for cursor blinking. The default blink
                rate is 530ms. By setting this to zero, blinking can be disabled. A
                negative value hides the cursor entirely.</dd>
          
                <dt id="option_cursorScrollMargin"><code><strong>cursorScrollMargin</strong>: number</code></dt>
                <dd>How much extra space to always keep above and below the
                cursor when approaching the top or bottom of the visible view in
                a scrollable document. Default is 0.</dd>
          
                <dt id="option_cursorHeight"><code><strong>cursorHeight</strong>: number</code></dt>
                <dd>Determines the height of the cursor. Default is 1, meaning
                it spans the whole height of the line. For some fonts (and by
                some tastes) a smaller height (for example <code>0.85</code>),
                which causes the cursor to not reach all the way to the bottom
                of the line, looks better</dd>
          
                <dt id="option_resetSelectionOnContextMenu"><code><strong>resetSelectionOnContextMenu</strong>: boolean</code></dt>
                <dd>Controls whether, when the context menu is opened with a
                click outside of the current selection, the cursor is moved to
                the point of the click. Defaults to <code>true</code>.</dd>
          
                <dt id="option_workTime"><code id="option_wordkDelay"><strong>workTime</strong>, <strong>workDelay</strong>: number</code></dt>
                <dd>Highlighting is done by a pseudo background-thread that will
                work for <code>workTime</code> milliseconds, and then use
                timeout to sleep for <code>workDelay</code> milliseconds. The
                defaults are 200 and 300, you can change these options to make
                the highlighting more or less aggressive.</dd>
          
                <dt id="option_pollInterval"><code><strong>pollInterval</strong>: number</code></dt>
                <dd>Indicates how quickly CodeMirror should poll its input
                textarea for changes (when focused). Most input is captured by
                events, but some things, like IME input on some browsers, don't
                generate events that allow CodeMirror to properly detect it.
                Thus, it polls. Default is 100 milliseconds.</dd>
          
                <dt id="option_flattenSpans"><code><strong>flattenSpans</strong>: boolean</code></dt>
                <dd>By default, CodeMirror will combine adjacent tokens into a
                single span if they have the same class. This will result in a
                simpler DOM tree, and thus perform better. With some kinds of
                styling (such as rounded corners), this will change the way the
                document looks. You can set this option to false to disable this
                behavior.</dd>
          
                <dt id="option_addModeClass"><code><strong>addModeClass</strong>: boolean</code></dt>
                <dd>When enabled (off by default), an extra CSS class will be
                added to each token, indicating the
                (<a href="#innerMode">inner</a>) mode that produced it, prefixed
                with <code>"cm-m-"</code>. For example, tokens from the XML mode
                will get the <code>cm-m-xml</code> class.</dd>
          
                <dt id="option_maxHighlightLength"><code><strong>maxHighlightLength</strong>: number</code></dt>
                <dd>When highlighting long lines, in order to stay responsive,
                the editor will give up and simply style the rest of the line as
                plain text when it reaches a certain position. The default is
                10 000. You can set this to <code>Infinity</code> to turn off
                this behavior.</dd>
          
                <dt id="option_crudeMeasuringFrom"><code><strong>crudeMeasuringFrom</strong>: number</code></dt>
                <dd>When measuring the character positions in long lines, any
                line longer than this number (default is 10 000),
                when <a href="#option_lineWrapping">line wrapping</a>
                is <strong>off</strong>, will simply be assumed to consist of
                same-sized characters. This means that, on the one hand,
                measuring will be inaccurate when characters of varying size,
                right-to-left text, markers, or other irregular elements are
                present. On the other hand, it means that having such a line
                won't freeze the user interface because of the expensiveness of
                the measurements.</dd>
          
                <dt id="option_viewportMargin"><code><strong>viewportMargin</strong>: integer</code></dt>
                <dd>Specifies the amount of lines that are rendered above and
                below the part of the document that's currently scrolled into
                view. This affects the amount of updates needed when scrolling,
                and the amount of work that such an update does. You should
                usually leave it at its default, 10. Can be set
                to <code>Infinity</code> to make sure the whole document is
                always rendered, and thus the browser's text search works on it.
                This <em>will</em> have bad effects on performance of big
                documents.</dd>
              </dl>
          </section>
          
          <section id=events>
              <h2>Events</h2>
          
              <p>Various CodeMirror-related objects emit events, which allow
              client code to react to various situations. Handlers for such
              events can be registered with the <a href="#on"><code>on</code></a>
              and <a href="#off"><code>off</code></a> methods on the objects
              that the event fires on. To fire your own events,
              use <code>CodeMirror.signal(target, name, args...)</code>,
              where <code>target</code> is a non-DOM-node object.</p>
          
              <p>An editor instance fires the following events.
              The <code>instance</code> argument always refers to the editor
              itself.</p>
          
              <dl>
                <dt id="event_change"><code><strong>"change"</strong> (instance: CodeMirror, changeObj: object)</code></dt>
                <dd>Fires every time the content of the editor is changed.
                The <code>changeObj</code> is a <code>{from, to, text, removed,
                origin}</code> object containing information about the changes
                that occurred as second argument. <code>from</code>
                and <code>to</code> are the positions (in the pre-change
                coordinate system) where the change started and ended (for
                example, it might be <code>{ch:0, line:18}</code> if the
                position is at the beginning of line #19). <code>text</code> is
                an array of strings representing the text that replaced the
                changed range (split by line). <code>removed</code> is the text
                that used to be between <code>from</code> and <code>to</code>,
                which is overwritten by this change.</dd>
          
                <dt id="event_changes"><code><strong>"changes"</strong> (instance: CodeMirror, changes: array&lt;object&gt;)</code></dt>
                <dd>Like the <a href="#event_change"><code>"change"</code></a>
                event, but batched per <a href="#operation">operation</a>,
                passing an array containing all the changes that happened in the
                operation.</dd>
          
                <dt id="event_beforeChange"><code><strong>"beforeChange"</strong> (instance: CodeMirror, changeObj: object)</code></dt>
                <dd>This event is fired before a change is applied, and its
                handler may choose to modify or cancel the change.
                The <code>changeObj</code> object
                has <code>from</code>, <code>to</code>, and <code>text</code>
                properties, as with
                the <a href="#event_change"><code>"change"</code></a> event. It
                also has a <code>cancel()</code> method, which can be called to
                cancel the change, and, <strong>if</strong> the change isn't
                coming from an undo or redo event, an <code>update(from, to,
                text)</code> method, which may be used to modify the change.
                Undo or redo changes can't be modified, because they hold some
                metainformation for restoring old marked ranges that is only
                valid for that specific change. All three arguments
                to <code>update</code> are optional, and can be left off to
                leave the existing value for that field
                intact. <strong>Note:</strong> you may not do anything from
                a <code>"beforeChange"</code> handler that would cause changes
                to the document or its visualization. Doing so will, since this
                handler is called directly from the bowels of the CodeMirror
                implementation, probably cause the editor to become
                corrupted.</dd>
          
                <dt id="event_cursorActivity"><code><strong>"cursorActivity"</strong> (instance: CodeMirror)</code></dt>
                <dd>Will be fired when the cursor or selection moves, or any
                change is made to the editor content.</dd>
          
                <dt id="event_keyHandled"><code><strong>"keyHandled"</strong> (instance: CodeMirror, name: string, event: Event)</code></dt>
                <dd>Fired after a key is handled through a
                key map. <code>name</code> is the name of the handled key (for
                example <code>"Ctrl-X"</code> or <code>"'q'"</code>),
                and <code>event</code> is the DOM <code>keydown</code>
                or <code>keypress</code> event.</dd>
          
                <dt id="event_inputRead"><code><strong>"inputRead"</strong> (instance: CodeMirror, changeObj: object)</code></dt>
                <dd>Fired whenever new input is read from the hidden textarea
                (typed or pasted by the user).</dd>
          
                <dt id="event_beforeSelectionChange"><code><strong>"beforeSelectionChange"</strong> (instance: CodeMirror, obj: {ranges, update})</code></dt>
                <dd>This event is fired before the selection is moved. Its
                handler may inspect the set of selection ranges, present as an
                array of <code>{anchor, head}</code> objects in
                the <code>ranges</code> property of the <code>obj</code>
                argument, and optionally change them by calling
                the <code>update</code> method on this object, passing an array
                of ranges in the same format. Handlers for this event have the
                same restriction
                as <a href="#event_beforeChange"><code>"beforeChange"</code></a>
                handlers — they should not do anything to directly update the
                state of the editor.</dd>
          
                <dt id="event_viewportChange"><code><strong>"viewportChange"</strong> (instance: CodeMirror, from: number, to: number)</code></dt>
                <dd>Fires whenever the <a href="#getViewport">view port</a> of
                the editor changes (due to scrolling, editing, or any other
                factor). The <code>from</code> and <code>to</code> arguments
                give the new start and end of the viewport.</dd>
          
                <dt id="event_swapDoc"><code><strong>"swapDoc"</strong> (instance: CodeMirror, oldDoc: Doc)</code></dt>
                <dd>This is signalled when the editor's document is replaced
                using the <a href="#swapDoc"><code>swapDoc</code></a>
                method.</dd>
          
                <dt id="event_gutterClick"><code><strong>"gutterClick"</strong> (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event)</code></dt>
                <dd>Fires when the editor gutter (the line-number area) is
                clicked. Will pass the editor instance as first argument, the
                (zero-based) number of the line that was clicked as second
                argument, the CSS class of the gutter that was clicked as third
                argument, and the raw <code>mousedown</code> event object as
                fourth argument.</dd>
          
                <dt id="event_gutterContextMenu"><code><strong>"gutterContextMenu"</strong> (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event: Event)</code></dt>
                <dd>Fires when the editor gutter (the line-number area)
                receives a <code>contextmenu</code> event. Will pass the editor
                instance as first argument, the (zero-based) number of the line
                that was clicked as second argument, the CSS class of the
                gutter that was clicked as third argument, and the raw
                <code>contextmenu</code> mouse event object as fourth argument.
                You can <code>preventDefault</code> the event, to signal that
                CodeMirror should do no further handling.</dd>
          
                <dt id="event_focus"><code><strong>"focus"</strong> (instance: CodeMirror)</code></dt>
                <dd>Fires whenever the editor is focused.</dd>
          
                <dt id="event_blur"><code><strong>"blur"</strong> (instance: CodeMirror)</code></dt>
                <dd>Fires whenever the editor is unfocused.</dd>
          
                <dt id="event_scroll"><code><strong>"scroll"</strong> (instance: CodeMirror)</code></dt>
                <dd>Fires when the editor is scrolled.</dd>
          
                <dt id="event_scrollCursorIntoView"><code><strong>"scrollCursorIntoView"</strong> (instance: CodeMirror, event: Event)</code></dt>
                <dd>Fires when the editor tries to scroll its cursor into view.
                Can be hooked into to take care of additional scrollable
                containers around the editor. When the event object has
                its <code>preventDefault</code> method called, CodeMirror will
                not itself try to scroll the window.</dd>
          
                <dt id="event_update"><code><strong>"update"</strong> (instance: CodeMirror)</code></dt>
                <dd>Will be fired whenever CodeMirror updates its DOM display.</dd>
          
                <dt id="event_renderLine"><code><strong>"renderLine"</strong> (instance: CodeMirror, line: LineHandle, element: Element)</code></dt>
                <dd>Fired whenever a line is (re-)rendered to the DOM. Fired
                right after the DOM element is built, <em>before</em> it is
                added to the document. The handler may mess with the style of
                the resulting element, or add event handlers, but
                should <em>not</em> try to change the state of the editor.</dd>
          
                <dt id="event_dom"><code><strong>"mousedown"</strong>,
                <strong>"dblclick"</strong>, <strong>"contextmenu"</strong>, <strong>"keydown"</strong>, <strong>"keypress"</strong>,
                <strong>"keyup"</strong>, <strong>"dragstart"</strong>, <strong>"dragenter"</strong>,
                <strong>"dragover"</strong>, <strong>"drop"</strong>
                (instance: CodeMirror, event: Event)</code></dt>
                <dd>Fired when CodeMirror is handling a DOM event of this type.
                You can <code>preventDefault</code> the event, or give it a
                truthy <code>codemirrorIgnore</code> property, to signal that
                CodeMirror should do no further handling.</dd>
              </dl>
          
              <p>Document objects (instances
              of <a href="#Doc"><code>CodeMirror.Doc</code></a>) emit the
              following events:</p>
          
              <dl>
                <dt id="event_doc_change"><code><strong>"change"</strong> (doc: CodeMirror.Doc, changeObj: object)</code></dt>
                <dd>Fired whenever a change occurs to the
                document. <code>changeObj</code> has a similar type as the
                object passed to the
                editor's <a href="#event_change"><code>"change"</code></a>
                event.</dd>
          
                <dt id="event_doc_beforeChange"><code><strong>"beforeChange"</strong> (doc: CodeMirror.Doc, change: object)</code></dt>
                <dd>See the <a href="#event_beforeChange">description of the
                same event</a> on editor instances.</dd>
          
                <dt id="event_doc_cursorActivity"><code><strong>"cursorActivity"</strong> (doc: CodeMirror.Doc)</code></dt>
                <dd>Fired whenever the cursor or selection in this document
                changes.</dd>
          
                <dt id="event_doc_beforeSelectionChange"><code><strong>"beforeSelectionChange"</strong> (doc: CodeMirror.Doc, selection: {head, anchor})</code></dt>
                <dd>Equivalent to
                the <a href="#event_beforeSelectionChange">event by the same
                name</a> as fired on editor instances.</dd>
              </dl>
          
              <p>Line handles (as returned by, for
              example, <a href="#getLineHandle"><code>getLineHandle</code></a>)
              support these events:</p>
          
              <dl>
                <dt id="event_delete"><code><strong>"delete"</strong> ()</code></dt>
                <dd>Will be fired when the line object is deleted. A line object
                is associated with the <em>start</em> of the line. Mostly useful
                when you need to find out when your <a href="#setGutterMarker">gutter
                markers</a> on a given line are removed.</dd>
                <dt id="event_line_change"><code><strong>"change"</strong> (line: LineHandle, changeObj: object)</code></dt>
                <dd>Fires when the line's text content is changed in any way
                (but the line is not deleted outright). The <code>change</code>
                object is similar to the one passed
                to <a href="#event_change">change event</a> on the editor
                object.</dd>
              </dl>
          
              <p>Marked range handles (<code>CodeMirror.TextMarker</code>), as returned
              by <a href="#markText"><code>markText</code></a>
              and <a href="#setBookmark"><code>setBookmark</code></a>, emit the
              following events:</p>
          
              <dl>
                <dt id="event_beforeCursorEnter"><code><strong>"beforeCursorEnter"</strong> ()</code></dt>
                <dd>Fired when the cursor enters the marked range. From this
                event handler, the editor state may be inspected
                but <em>not</em> modified, with the exception that the range on
                which the event fires may be cleared.</dd>
                <dt id="event_clear"><code><strong>"clear"</strong> (from: {line, ch}, to: {line, ch})</code></dt>
                <dd>Fired when the range is cleared, either through cursor
                movement in combination
                with <a href="#mark_clearOnEnter"><code>clearOnEnter</code></a>
                or through a call to its <code>clear()</code> method. Will only
                be fired once per handle. Note that deleting the range through
                text editing does not fire this event, because an undo action
                might bring the range back into existence. <code>from</code>
                and <code>to</code> give the part of the document that the range
                spanned when it was cleared.</dd>
                <dt id="event_hide"><code><strong>"hide"</strong> ()</code></dt>
                <dd>Fired when the last part of the marker is removed from the
                document by editing operations.</dd>
                <dt id="event_unhide"><code><strong>"unhide"</strong> ()</code></dt>
                <dd>Fired when, after the marker was removed by editing, a undo
                operation brought the marker back.</dd>
              </dl>
          
              <p>Line widgets (<code>CodeMirror.LineWidget</code>), returned
              by <a href="#addLineWidget"><code>addLineWidget</code></a>, fire
              these events:</p>
          
              <dl>
                <dt id="event_redraw"><code><strong>"redraw"</strong> ()</code></dt>
                <dd>Fired whenever the editor re-adds the widget to the DOM.
                This will happen once right after the widget is added (if it is
                scrolled into view), and then again whenever it is scrolled out
                of view and back in again, or when changes to the editor options
                or the line the widget is on require the widget to be
                redrawn.</dd>
              </dl>
          </section>
          
          <section id=keymaps>
              <h2>Key Maps</h2>
          
              <p>Key maps are ways to associate keys with functionality. A key map
              is an object mapping strings that identify the keys to functions
              that implement their functionality.</p>
          
              <p>The CodeMirror distributions comes
              with <a href="../demo/emacs.html">Emacs</a>, <a href="../demo/vim.html">Vim</a>,
              and <a href="../demo/sublime.html">Sublime Text</a>-style keymaps.</p>
          
              <p>Keys are identified either by name or by character.
              The <code>CodeMirror.keyNames</code> object defines names for
              common keys and associates them with their key codes. Examples of
              names defined here are <code>Enter</code>, <code>F5</code>,
              and <code>Q</code>. These can be prefixed
              with <code>Shift-</code>, <code>Cmd-</code>, <code>Ctrl-</code>,
              and <code>Alt-</code> to specify a modifier. So for
              example, <code>Shift-Ctrl-Space</code> would be a valid key
              identifier.</p>
          
              <p>Common example: map the Tab key to insert spaces instead of a tab
              character.</p>
          
              <pre data-lang="javascript">
          editor.setOption("extraKeys", {
            Tab: function(cm) {
              var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
              cm.replaceSelection(spaces);
            }
          });</pre>
          
              <p>Alternatively, a character can be specified directly by
              surrounding it in single quotes, for example <code>'$'</code>
              or <code>'q'</code>. Due to limitations in the way browsers fire
              key events, these may not be prefixed with modifiers.</p>
          
              <p id="normalizeKeyMap">Multi-stroke key bindings can be specified
              by separating the key names by spaces in the property name, for
              example <code>Ctrl-X Ctrl-V</code>. When a map contains
              multi-stoke bindings or keys with modifiers that are not specified
              in the default order (<code>Shift-Cmd-Ctrl-Alt</code>), you must
              call <code>CodeMirror.normalizeKeyMap</code> on it before it can
              be used. This function takes a keymap and modifies it to normalize
              modifier order and properly recognize multi-stroke bindings. It
              will return the keymap itself.</p>
          
              <p>The <code>CodeMirror.keyMap</code> object associates key maps
              with names. User code and key map definitions can assign extra
              properties to this object. Anywhere where a key map is expected, a
              string can be given, which will be looked up in this object. It
              also contains the <code>"default"</code> key map holding the
              default bindings.</p>
          
              <p>The values of properties in key maps can be either functions of
              a single argument (the CodeMirror instance), strings, or
              <code>false</code>. Strings refer
              to <a href="#commands">commands</a>, which are described below. If
              the property is set to <code>false</code>, CodeMirror leaves
              handling of the key up to the browser. A key handler function may
              return <code>CodeMirror.Pass</code> to indicate that it has
              decided not to handle the key, and other handlers (or the default
              behavior) should be given a turn.</p>
          
              <p>Keys mapped to command names that start with the
              characters <code>"go"</code> or to functions that have a
              truthy <code>motion</code> property (which should be used for
              cursor-movement actions) will be fired even when an
              extra <code>Shift</code> modifier is present (i.e. <code>"Up":
              "goLineUp"</code> matches both up and shift-up). This is used to
              easily implement shift-selection.</p>
          
              <p>Key maps can defer to each other by defining
              a <code>fallthrough</code> property. This indicates that when a
              key is not found in the map itself, one or more other maps should
              be searched. It can hold either a single key map or an array of
              key maps.</p>
          
              <p>When a key map needs to set something up when it becomes
              active, or tear something down when deactivated, it can
              contain <code>attach</code> and/or <code>detach</code> properties,
              which should hold functions that take the editor instance and the
              next or previous keymap. Note that this only works for the
              <a href="#option_keyMap">top-level keymap</a>, not for fallthrough
              maps or maps added
              with <a href="#option_extraKeys"><code>extraKeys</code></a>
              or <a href="#addKeyMap"><code>addKeyMap</code></a>.</p>
          </section>
          
          <section id=commands>
              <h2>Commands</h2>
          
              <p>Commands are parameter-less actions that can be performed on an
              editor. Their main use is for key bindings. Commands are defined by
              adding properties to the <code>CodeMirror.commands</code> object.
              A number of common commands are defined by the library itself,
              most of them used by the default key bindings. The value of a
              command property must be a function of one argument (an editor
              instance).</p>
          
              <p>Some of the commands below are referenced in the default
              key map, but not defined by the core library. These are intended to
              be defined by user code or addons.</p>
          
              <p>Commands can also be run with
              the <a href="#execCommand"><code>execCommand</code></a>
              method.</p>
          
              <dl>
                <dt class=command id=command_selectAll><code><strong>selectAll</strong></code><span class=keybinding>Ctrl-A (PC), Cmd-A (Mac)</span></dt>
                <dd>Select the whole content of the editor.</dd>
          
                <dt class=command id=command_singleSelection><code><strong>singleSelection</strong></code><span class=keybinding>Esc</span></dt>
                <dd>When multiple selections are present, this deselects all but
                the primary selection.</dd>
          
                <dt class=command id=command_killLine><code><strong>killLine</strong></code><span class=keybinding>Ctrl-K (Mac)</span></dt>
                <dd>Emacs-style line killing. Deletes the part of the line after
                the cursor. If that consists only of whitespace, the newline at
                the end of the line is also deleted.</dd>
          
                <dt class=command id=command_deleteLine><code><strong>deleteLine</strong></code><span class=keybinding>Ctrl-D (PC), Cmd-D (Mac)</span></dt>
                <dd>Deletes the whole line under the cursor, including newline at the end.</dd>
          
                <dt class=command id=command_delLineLeft><code><strong>delLineLeft</strong></code></dt>
                <dd>Delete the part of the line before the cursor.</dd>
          
                <dt class=command id=command_delWrappedLineLeft><code><strong>delWrappedLineLeft</strong></code><span class=keybinding>Cmd-Backspace (Mac)</span></dt>
                <dd>Delete the part of the line from the left side of the visual line the cursor is on to the cursor.</dd>
          
                <dt class=command id=command_delWrappedLineRight><code><strong>delWrappedLineRight</strong></code><span class=keybinding>Cmd-Delete (Mac)</span></dt>
                <dd>Delete the part of the line from the cursor to the right side of the visual line the cursor is on.</dd>
          
                <dt class=command id=command_undo><code><strong>undo</strong></code><span class=keybinding>Ctrl-Z (PC), Cmd-Z (Mac)</span></dt>
                <dd>Undo the last change.</dd>
          
                <dt class=command id=command_redo><code><strong>redo</strong></code><span class=keybinding>Ctrl-Y (PC), Shift-Cmd-Z (Mac), Cmd-Y (Mac)</span></dt>
                <dd>Redo the last undone change.</dd>
          
                <dt class=command id=command_undoSelection><code><strong>undoSelection</strong></code><span class=keybinding>Ctrl-U (PC), Cmd-U (Mac)</span></dt>
                <dd>Undo the last change to the selection, or if there are no
                selection-only changes at the top of the history, undo the last
                change.</dd>
          
                <dt class=command id=command_redoSelection><code><strong>redoSelection</strong></code><span class=keybinding>Alt-U (PC), Shift-Cmd-U (Mac)</span></dt>
                <dd>Redo the last change to the selection, or the last text change if
                no selection changes remain.</dd>
          
                <dt class=command id=command_goDocStart><code><strong>goDocStart</strong></code><span class=keybinding>Ctrl-Up (PC), Cmd-Up (Mac), Cmd-Home (Mac)</span></dt>
                <dd>Move the cursor to the start of the document.</dd>
          
                <dt class=command id=command_goDocEnd><code><strong>goDocEnd</strong></code><span class=keybinding>Ctrl-Down (PC), Cmd-End (Mac), Cmd-Down (Mac)</span></dt>
                <dd>Move the cursor to the end of the document.</dd>
          
                <dt class=command id=command_goLineStart><code><strong>goLineStart</strong></code><span class=keybinding>Alt-Left (PC), Ctrl-A (Mac)</span></dt>
                <dd>Move the cursor to the start of the line.</dd>
          
                <dt class=command id=command_goLineStartSmart><code><strong>goLineStartSmart</strong></code><span class=keybinding>Home</span></dt>
                <dd>Move to the start of the text on the line, or if we are
                already there, to the actual start of the line (including
                whitespace).</dd>
          
                <dt class=command id=command_goLineEnd><code><strong>goLineEnd</strong></code><span class=keybinding>Alt-Right (PC), Ctrl-E (Mac)</span></dt>
                <dd>Move the cursor to the end of the line.</dd>
          
                <dt class=command id=command_goLineRight><code><strong>goLineRight</strong></code><span class=keybinding>Cmd-Right (Mac)</span></dt>
                <dd>Move the cursor to the right side of the visual line it is on.</dd>
          
                <dt class=command id=command_goLineLeft><code><strong>goLineLeft</strong></code><span class=keybinding>Cmd-Left (Mac)</span></dt>
                <dd>Move the cursor to the left side of the visual line it is on. If
                this line is wrapped, that may not be the start of the line.</dd>
          
                <dt class=command id=command_goLineLeftSmart><code><strong>goLineLeftSmart</strong></code></dt>
                <dd>Move the cursor to the left side of the visual line it is
                on. If that takes it to the start of the line, behave
                like <a href="#command_goLineStartSmart"><code>goLineStartSmart</code></a>.</dd>
          
                <dt class=command id=command_goLineUp><code><strong>goLineUp</strong></code><span class=keybinding>Up, Ctrl-P (Mac)</span></dt>
                <dd>Move the cursor up one line.</dd>
          
                <dt class=command id=command_goLineDown><code><strong>goLineDown</strong></code><span class=keybinding>Down, Ctrl-N (Mac)</span></dt>
                <dd>Move down one line.</dd>
          
                <dt class=command id=command_goPageUp><code><strong>goPageUp</strong></code><span class=keybinding>PageUp, Shift-Ctrl-V (Mac)</span></dt>
                <dd>Move the cursor up one screen, and scroll up by the same distance.</dd>
          
                <dt class=command id=command_goPageDown><code><strong>goPageDown</strong></code><span class=keybinding>PageDown, Ctrl-V (Mac)</span></dt>
                <dd>Move the cursor down one screen, and scroll down by the same distance.</dd>
          
                <dt class=command id=command_goCharLeft><code><strong>goCharLeft</strong></code><span class=keybinding>Left, Ctrl-B (Mac)</span></dt>
                <dd>Move the cursor one character left, going to the previous line
                when hitting the start of line.</dd>
          
                <dt class=command id=command_goCharRight><code><strong>goCharRight</strong></code><span class=keybinding>Right, Ctrl-F (Mac)</span></dt>
                <dd>Move the cursor one character right, going to the next line
                when hitting the end of line.</dd>
          
                <dt class=command id=command_goColumnLeft><code><strong>goColumnLeft</strong></code></dt>
                <dd>Move the cursor one character left, but don't cross line boundaries.</dd>
          
                <dt class=command id=command_goColumnRight><code><strong>goColumnRight</strong></code></dt>
                <dd>Move the cursor one character right, don't cross line boundaries.</dd>
          
                <dt class=command id=command_goWordLeft><code><strong>goWordLeft</strong></code><span class=keybinding>Alt-B (Mac)</span></dt>
                <dd>Move the cursor to the start of the previous word.</dd>
          
                <dt class=command id=command_goWordRight><code><strong>goWordRight</strong></code><span class=keybinding>Alt-F (Mac)</span></dt>
                <dd>Move the cursor to the end of the next word.</dd>
          
                <dt class=command id=command_goGroupLeft><code><strong>goGroupLeft</strong></code><span class=keybinding>Ctrl-Left (PC), Alt-Left (Mac)</span></dt>
                <dd>Move to the left of the group before the cursor. A group is
                a stretch of word characters, a stretch of punctuation
                characters, a newline, or a stretch of <em>more than one</em>
                whitespace character.</dd>
          
                <dt class=command id=command_goGroupRight><code><strong>goGroupRight</strong></code><span class=keybinding>Ctrl-Right (PC), Alt-Right (Mac)</span></dt>
                <dd>Move to the right of the group after the cursor
                (see <a href="#command_goGroupLeft">above</a>).</dd>
          
                <dt class=command id=command_delCharBefore><code><strong>delCharBefore</strong></code><span class=keybinding>Shift-Backspace, Ctrl-H (Mac)</span></dt>
                <dd>Delete the character before the cursor.</dd>
          
                <dt class=command id=command_delCharAfter><code><strong>delCharAfter</strong></code><span class=keybinding>Delete, Ctrl-D (Mac)</span></dt>
                <dd>Delete the character after the cursor.</dd>
          
                <dt class=command id=command_delWordBefore><code><strong>delWordBefore</strong></code><span class=keybinding>Alt-Backspace (Mac)</span></dt>
                <dd>Delete up to the start of the word before the cursor.</dd>
          
                <dt class=command id=command_delWordAfter><code><strong>delWordAfter</strong></code><span class=keybinding>Alt-D (Mac)</span></dt>
                <dd>Delete up to the end of the word after the cursor.</dd>
          
                <dt class=command id=command_delGroupBefore><code><strong>delGroupBefore</strong></code><span class=keybinding>Ctrl-Backspace (PC), Alt-Backspace (Mac)</span></dt>
                <dd>Delete to the left of the <a href="#command_goGroupLeft">group</a> before the cursor.</dd>
          
                <dt class=command id=command_delGroupAfter><code><strong>delGroupAfter</strong></code><span class=keybinding>Ctrl-Delete (PC), Ctrl-Alt-Backspace (Mac), Alt-Delete (Mac)</span></dt>
                <dd>Delete to the start of the <a href="#command_goGroupLeft">group</a> after the cursor.</dd>
          
                <dt class=command id=command_indentAuto><code><strong>indentAuto</strong></code><span class=keybinding>Shift-Tab</span></dt>
                <dd>Auto-indent the current line or selection.</dd>
          
                <dt class=command id=command_indentMore><code><strong>indentMore</strong></code><span class=keybinding>Ctrl-] (PC), Cmd-] (Mac)</span></dt>
                <dd>Indent the current line or selection by one <a href="#option_indentUnit">indent unit</a>.</dd>
          
                <dt class=command id=command_indentLess><code><strong>indentLess</strong></code><span class=keybinding>Ctrl-[ (PC), Cmd-[ (Mac)</span></dt>
                <dd>Dedent the current line or selection by one <a href="#option_indentUnit">indent unit</a>.</dd>
          
                <dt class=command id=command_insertTab><code><strong>insertTab</strong></code></dt>
                <dd>Insert a tab character at the cursor.</dd>
          
                <dt class=command id=command_insertSoftTab><code><strong>insertSoftTab</strong></code></dt>
                <dd>Insert the amount of spaces that match the width a tab at
                the cursor position would have.</dd>
          
                <dt class=command id=command_defaultTab><code><strong>defaultTab</strong></code><span class=keybinding>Tab</span></dt>
                <dd>If something is selected, indent it by
                one <a href="#option_indentUnit">indent unit</a>. If nothing is
                selected, insert a tab character.</dd>
          
                <dt class=command id=command_transposeChars><code><strong>transposeChars</strong></code><span class=keybinding>Ctrl-T (Mac)</span></dt>
                <dd>Swap the characters before and after the cursor.</dd>
          
                <dt class=command id=command_newlineAndIndent><code><strong>newlineAndIndent</strong></code><span class=keybinding>Enter</span></dt>
                <dd>Insert a newline and auto-indent the new line.</dd>
          
                <dt class=command id=command_toggleOverwrite><code><strong>toggleOverwrite</strong></code><span class=keybinding>Insert</span></dt>
                <dd>Flip the <a href="#toggleOverwrite">overwrite</a> flag.</dd>
          
                <dt class=command id=command_save><code><strong>save</strong></code><span class=keybinding>Ctrl-S (PC), Cmd-S (Mac)</span></dt>
                <dd>Not defined by the core library, only referred to in
                key maps. Intended to provide an easy way for user code to define
                a save command.</dd>
          
                <dt class=command id=command_find><code><strong>find</strong></code><span class=keybinding>Ctrl-F (PC), Cmd-F (Mac)</span></dt>
                <dt class=command id=command_findNext><code><strong>findNext</strong></code><span class=keybinding>Ctrl-G (PC), Cmd-G (Mac)</span></dt>
                <dt class=command id=command_findPrev><code><strong>findPrev</strong></code><span class=keybinding>Shift-Ctrl-G (PC), Shift-Cmd-G (Mac)</span></dt>
                <dt class=command id=command_replace><code><strong>replace</strong></code><span class=keybinding>Shift-Ctrl-F (PC), Cmd-Alt-F (Mac)</span></dt>
                <dt class=command id=command_replaceAll><code><strong>replaceAll</strong></code><span class=keybinding>Shift-Ctrl-R (PC), Shift-Cmd-Alt-F (Mac)</span></dt>
                <dd>Not defined by the core library, but defined in
                the <a href="#addon_search">search addon</a> (or custom client
                addons).</dd>
          
              </dl>
          
          </section>
          
          <section id=styling>
              <h2>Customized Styling</h2>
          
              <p>Up to a certain extent, CodeMirror's look can be changed by
              modifying style sheet files. The style sheets supplied by modes
              simply provide the colors for that mode, and can be adapted in a
              very straightforward way. To style the editor itself, it is
              possible to alter or override the styles defined
              in <a href="../lib/codemirror.css"><code>codemirror.css</code></a>.</p>
          
              <p>Some care must be taken there, since a lot of the rules in this
              file are necessary to have CodeMirror function properly. Adjusting
              colors should be safe, of course, and with some care a lot of
              other things can be changed as well. The CSS classes defined in
              this file serve the following roles:</p>
          
              <dl>
                <dt id="class_CodeMirror"><code><strong>CodeMirror</strong></code></dt>
                <dd>The outer element of the editor. This should be used for the
                editor width, height, borders and positioning. Can also be used
                to set styles that should hold for everything inside the editor
                (such as font and font size), or to set a background. Setting
                this class' <code>height</code> style to <code>auto</code> will
                make the editor <a href="../demo/resize.html">resize to fit its
                content</a> (it is recommended to also set
                the <a href="#option_viewportMargin"><code>viewportMargin</code>
                option</a> to <code>Infinity</code> when doing this.</dd>
          
                <dt id="class_CodeMirror_focused"><code><strong>CodeMirror-focused</strong></code></dt>
                <dd>Whenever the editor is focused, the top element gets this
                class. This is used to hide the cursor and give the selection a
                different color when the editor is not focused.</dd>
          
                <dt id="class_CodeMirror_gutters"><code><strong>CodeMirror-gutters</strong></code></dt>
                <dd>This is the backdrop for all gutters. Use it to set the
                default gutter background color, and optionally add a border on
                the right of the gutters.</dd>
          
                <dt id="class_CodeMirror_linenumbers"><code><strong>CodeMirror-linenumbers</strong></code></dt>
                <dd>Use this for giving a background or width to the line number
                gutter.</dd>
          
                <dt id="class_CodeMirror_linenumber"><code><strong>CodeMirror-linenumber</strong></code></dt>
                <dd>Used to style the actual individual line numbers. These
                won't be children of the <code>CodeMirror-linenumbers</code>
                (plural) element, but rather will be absolutely positioned to
                overlay it. Use this to set alignment and text properties for
                the line numbers.</dd>
          
                <dt id="class_CodeMirror_lines"><code><strong>CodeMirror-lines</strong></code></dt>
                <dd>The visible lines. This is where you specify vertical
                padding for the editor content.</dd>
          
                <dt id="class_CodeMirror_cursor"><code><strong>CodeMirror-cursor</strong></code></dt>
                <dd>The cursor is a block element that is absolutely positioned.
                You can make it look whichever way you want.</dd>
          
                <dt id="class_CodeMirror_selected"><code><strong>CodeMirror-selected</strong></code></dt>
                <dd>The selection is represented by <code>span</code> elements
                with this class.</dd>
          
                <dt id="class_CodeMirror_matchingbracket"><code><strong>CodeMirror-matchingbracket</strong></code>,
                  <code><strong>CodeMirror-nonmatchingbracket</strong></code></dt>
                <dd>These are used to style matched (or unmatched) brackets.</dd>
              </dl>
          
              <p>If your page's style sheets do funky things to
              all <code>div</code> or <code>pre</code> elements (you probably
              shouldn't do that), you'll have to define rules to cancel these
              effects out again for elements under the <code>CodeMirror</code>
              class.</p>
          
              <p>Themes are also simply CSS files, which define colors for
              various syntactic elements. See the files in
              the <a href="../theme/"><code>theme</code></a> directory.</p>
          </section>
          
          <section id=api>
              <h2>Programming API</h2>
          
              <p>A lot of CodeMirror features are only available through its
              API. Thus, you need to write code (or
              use <a href="#addons">addons</a>) if you want to expose them to
              your users.</p>
          
              <p>Whenever points in the document are represented, the API uses
              objects with <code>line</code> and <code>ch</code> properties.
              Both are zero-based. CodeMirror makes sure to 'clip' any positions
              passed by client code so that they fit inside the document, so you
              shouldn't worry too much about sanitizing your coordinates. If you
              give <code>ch</code> a value of <code>null</code>, or don't
              specify it, it will be replaced with the length of the specified
              line.</p>
          
              <p>Methods prefixed with <code>doc.</code> can, unless otherwise
              specified, be called both on <code>CodeMirror</code> (editor)
              instances and <code>CodeMirror.Doc</code> instances. Methods
              prefixed with <code>cm.</code> are <em>only</em> available
              on <code>CodeMirror</code> instances.</p>
          
              <h3 id="api_constructor">Constructor</h3>
          
              <p id="CodeMirror">Constructing an editor instance is done with
              the <code><strong>CodeMirror</strong>(place: Element|fn(Element),
              ?option: object)</code> constructor. If the <code>place</code>
              argument is a DOM element, the editor will be appended to it. If
              it is a function, it will be called, and is expected to place the
              editor into the document. <code>options</code> may be an element
              mapping <a href="#config">option names</a> to values. The options
              that it doesn't explicitly specify (or all options, if it is not
              passed) will be taken
              from <a href="#defaults"><code>CodeMirror.defaults</code></a>.</p>
          
              <p>Note that the options object passed to the constructor will be
              mutated when the instance's options
              are <a href="#setOption">changed</a>, so you shouldn't share such
              objects between instances.</p>
          
              <p>See <a href="#fromTextArea"><code>CodeMirror.fromTextArea</code></a>
              for another way to construct an editor instance.</p>
          
              <h3 id="api_content">Content manipulation methods</h3>
          
              <dl>
                <dt id="getValue"><code><strong>doc.getValue</strong>(?separator: string) → string</code></dt>
                <dd>Get the current editor content. You can pass it an optional
                argument to specify the string to be used to separate lines
                (defaults to <code>"\n"</code>).</dd>
                <dt id="setValue"><code><strong>doc.setValue</strong>(content: string)</code></dt>
                <dd>Set the editor content.</dd>
          
                <dt id="getRange"><code><strong>doc.getRange</strong>(from: {line, ch}, to: {line, ch}, ?separator: string) → string</code></dt>
                <dd>Get the text between the given points in the editor, which
                should be <code>{line, ch}</code> objects. An optional third
                argument can be given to indicate the line separator string to
                use (defaults to <code>"\n"</code>).</dd>
                <dt id="replaceRange"><code><strong>doc.replaceRange</strong>(replacement: string, from: {line, ch}, to: {line, ch}, ?origin: string)</code></dt>
                <dd>Replace the part of the document between <code>from</code>
                and <code>to</code> with the given string. <code>from</code>
                and <code>to</code> must be <code>{line, ch}</code>
                objects. <code>to</code> can be left off to simply insert the
                string at position <code>from</code>. When <code>origin</code>
                is given, it will be passed on
                to <a href="#event_change"><code>"change"</code> events</a>, and
                its first letter will be used to determine whether this change
                can be merged with previous history events, in the way described
                for <a href="#selection_origin">selection origins</a>.</dd>
          
                <dt id="getLine"><code><strong>doc.getLine</strong>(n: integer) → string</code></dt>
                <dd>Get the content of line <code>n</code>.</dd>
          
                <dt id="lineCount"><code><strong>doc.lineCount</strong>() → integer</code></dt>
                <dd>Get the number of lines in the editor.</dd>
                <dt id="firstLine"><code><strong>doc.firstLine</strong>() → integer</code></dt>
                <dd>Get the first line of the editor. This will
                usually be zero but for <a href="#linkedDoc_from">linked sub-views</a>,
                or <a href="#api_doc">documents</a> instantiated with a non-zero
                first line, it might return other values.</dd>
                <dt id="lastLine"><code><strong>doc.lastLine</strong>() → integer</code></dt>
                <dd>Get the last line of the editor. This will
                usually be <code>doc.lineCount() - 1</code>,
                but for <a href="#linkedDoc_from">linked sub-views</a>,
                it might return other values.</dd>
          
                <dt id="getLineHandle"><code><strong>doc.getLineHandle</strong>(num: integer) → LineHandle</code></dt>
                <dd>Fetches the line handle for the given line number.</dd>
                <dt id="getLineNumber"><code><strong>doc.getLineNumber</strong>(handle: LineHandle) → integer</code></dt>
                <dd>Given a line handle, returns the current position of that
                line (or <code>null</code> when it is no longer in the
                document).</dd>
                <dt id="eachLine"><code><strong>doc.eachLine</strong>(f: (line: LineHandle))</code></dt>
                <dt><code><strong>doc.eachLine</strong>(start: integer, end: integer, f: (line: LineHandle))</code></dt>
                <dd>Iterate over the whole document, or if <code>start</code>
                and <code>end</code> line numbers are given, the range
                from <code>start</code> up to (not including) <code>end</code>,
                and call <code>f</code> for each line, passing the line handle.
                This is a faster way to visit a range of line handlers than
                calling <a href="#getLineHandle"><code>getLineHandle</code></a>
                for each of them. Note that line handles have
                a <code>text</code> property containing the line's content (as a
                string).</dd>
          
                <dt id="markClean"><code><strong>doc.markClean</strong>()</code></dt>
                <dd>Set the editor content as 'clean', a flag that it will
                retain until it is edited, and which will be set again when such
                an edit is undone again. Useful to track whether the content
                needs to be saved. This function is deprecated in favor
                of <a href="#changeGeneration"><code>changeGeneration</code></a>,
                which allows multiple subsystems to track different notions of
                cleanness without interfering.</dd>
                <dt id="changeGeneration"><code><strong>doc.changeGeneration</strong>(?closeEvent: boolean) → integer</code></dt>
                <dd>Returns a number that can later be passed
                to <a href="#isClean"><code>isClean</code></a> to test whether
                any edits were made (and not undone) in the meantime.
                If <code>closeEvent</code> is true, the current history event
                will be ‘closed’, meaning it can't be combined with further
                changes (rapid typing or deleting events are typically
                combined).</dd>
                <dt id="isClean"><code><strong>doc.isClean</strong>(?generation: integer) → boolean</code></dt>
                <dd>Returns whether the document is currently clean — not
                modified since initialization or the last call
                to <a href="#markClean"><code>markClean</code></a> if no
                argument is passed, or since the matching call
                to <a href="#changeGeneration"><code>changeGeneration</code></a>
                if a generation value is given.</dd>
              </dl>
          
              <h3 id="api_selection">Cursor and selection methods</h3>
          
              <dl>
                <dt id="getSelection"><code><strong>doc.getSelection</strong>(?lineSep: string) → string</code></dt>
                <dd>Get the currently selected code. Optionally pass a line
                separator to put between the lines in the output. When multiple
                selections are present, they are concatenated with instances
                of <code>lineSep</code> in between.</dd>
                <dt id="getSelections"><code><strong>doc.getSelections</strong>(?lineSep: string) → string</code></dt>
                <dd>Returns an array containing a string for each selection,
                representing the content of the selections.</dd>
          
                <dt id="replaceSelection"><code><strong>doc.replaceSelection</strong>(replacement: string, ?select: string)</code></dt>
                <dd>Replace the selection(s) with the given string. By default,
                the new selection ends up after the inserted text. The
                optional <code>select</code> argument can be used to change
                this—passing <code>"around"</code> will cause the new text to be
                selected, passing <code>"start"</code> will collapse the
                selection to the start of the inserted text.</dd>
                <dt id="replaceSelections"><code><strong>doc.replaceSelections</strong>(replacements: array&lt;string&gt;, ?select: string)</code></dt>
                <dd>The length of the given array should be the same as the
                number of active selections. Replaces the content of the
                selections with the strings in the array.
                The <code>select</code> argument works the same as
                in <a href="#replaceSelection"><code>replaceSelection</code></a>.</dd>
          
                <dt id="getCursor"><code><strong>doc.getCursor</strong>(?start: string) → {line, ch}</code></dt>
                <dd>Retrieve one end of the <em>primary</em>
                selection. <code>start</code> is a an optional string indicating
                which end of the selection to return. It may
                be <code>"from"</code>, <code>"to"</code>, <code>"head"</code>
                (the side of the selection that moves when you press
                shift+arrow), or <code>"anchor"</code> (the fixed side of the
                selection). Omitting the argument is the same as
                passing <code>"head"</code>. A <code>{line, ch}</code> object
                will be returned.</dd>
                <dt id="listSelections"><code><strong>doc.listSelections</strong>() → array&lt;{anchor, head}&gt;</code></dt>
                <dd>Retrieves a list of all current selections. These will
                always be sorted, and never overlap (overlapping selections are
                merged). Each object in the array contains <code>anchor</code>
                and <code>head</code> properties referring to <code>{line,
                ch}</code> objects.</dd>
          
                <dt id="somethingSelected"><code><strong>doc.somethingSelected</strong>() → boolean</code></dt>
                <dd>Return true if any text is selected.</dd>
                <dt id="setCursor"><code><strong>doc.setCursor</strong>(pos: {line, ch}|number, ?ch: number, ?options: object)</code></dt>
                <dd>Set the cursor position. You can either pass a
                single <code>{line, ch}</code> object, or the line and the
                character as two separate parameters. Will replace all
                selections with a single, empty selection at the given position.
                The supported options are the same as for <a href="#setSelection"><code>setSelection</code></a>.</dd>
          
                <dt id="setSelection"><code><strong>doc.setSelection</strong>(anchor: {line, ch}, ?head: {line, ch}, ?options: object)</code></dt>
                <dd>Set a single selection range. <code>anchor</code>
                and <code>head</code> should be <code>{line, ch}</code>
                objects. <code>head</code> defaults to <code>anchor</code> when
                not given. These options are supported:
                <dl>
                  <dt id="selection_scroll"><code><strong>scroll</strong>: boolean</code></dt>
                  <dd>Determines whether the selection head should be scrolled
                  into view. Defaults to true.</dd>
                  <dt id="selection_origin"><code><strong>origin</strong>: string</code></dt>
                  <dd>Detemines whether the selection history event may be
                  merged with the previous one. When an origin starts with the
                  character <code>+</code>, and the last recorded selection had
                  the same origin and was similar (close
                  in <a href="#option_historyEventDelay">time</a>, both
                  collapsed or both non-collapsed), the new one will replace the
                  old one. When it starts with <code>*</code>, it will always
                  replace the previous event (if that had the same origin).
                  Built-in motion uses the <code>"+move"</code> origin.</dd>
                  <dt id="selection_bias"><code><strong>bias</strong>: number</code></dt>
                  <dd>Determine the direction into which the selection endpoints
                  should be adjusted when they fall inside
                  an <a href="#mark_atomic">atomic</a> range. Can be either -1
                  (backward) or 1 (forward). When not given, the bias will be
                  based on the relative position of the old selection—the editor
                  will try to move further away from that, to prevent getting
                  stuck.</dd>
                </dl></dd>
          
                <dt id="setSelections"><code><strong>doc.setSelections</strong>(ranges: array&lt;{anchor, head}&gt;, ?primary: integer, ?options: object)</code></dt>
                <dd>Sets a new set of selections. There must be at least one
                selection in the given array. When <code>primary</code> is a
                number, it determines which selection is the primary one. When
                it is not given, the primary index is taken from the previous
                selection, or set to the last range if the previous selection
                had less ranges than the new one. Supports the same options
                as <a href="#setSelection"><code>setSelection</code></a>.</dd>
                <dt id="addSelection"><code><strong>doc.addSelection</strong>(anchor: {line, ch}, ?head: {line, ch})</code></dt>
                <dd>Adds a new selection to the existing set of selections, and
                makes it the primary selection.</dd>
          
                <dt id="extendSelection"><code><strong>doc.extendSelection</strong>(from: {line, ch}, ?to: {line, ch}, ?options: object)</code></dt>
                <dd>Similar
                to <a href="#setSelection"><code>setSelection</code></a>, but
                will, if shift is held or
                the <a href="#setExtending">extending</a> flag is set, move the
                head of the selection while leaving the anchor at its current
                place. <code>to</code> is optional, and can be passed to ensure
                a region (for example a word or paragraph) will end up selected
                (in addition to whatever lies between that region and the
                current anchor). When multiple selections are present, all but
                the primary selection will be dropped by this method.
                Supports the same options as <a href="#setSelection"><code>setSelection</code></a>.</dd>
                <dt id="extendSelections"><code><strong>doc.extendSelections</strong>(heads: array&lt;{line, ch}&gt;, ?options: object)</code></dt>
                <dd>An equivalent
                of <a href="#extendSelection"><code>extendSelection</code></a>
                that acts on all selections at once.</dd>
                <dt id="extendSelectionsBy"><code><strong>doc.extendSelectionsBy</strong>(f: function(range: {anchor, head}) → {anchor, head}), ?options: object)</code></dt>
                <dd>Applies the given function to all existing selections, and
                calls <a href="#extendSelections"><code>extendSelections</code></a>
                on the result.</dd>
                <dt id="setExtending"><code><strong>doc.setExtending</strong>(value: boolean)</code></dt>
                <dd>Sets or clears the 'extending' flag, which acts similar to
                the shift key, in that it will cause cursor movement and calls
                to <a href="#extendSelection"><code>extendSelection</code></a>
                to leave the selection anchor in place.</dd>
                <dt id="getExtending"><code><strong>doc.getExtending</strong>() → boolean</code></dt>
                <dd>Get the value of the 'extending' flag.</dd>
          
                <dt id="hasFocus"><code><strong>cm.hasFocus</strong>() → boolean</code></dt>
                <dd>Tells you whether the editor currently has focus.</dd>
          
                <dt id="findPosH"><code><strong>cm.findPosH</strong>(start: {line, ch}, amount: integer, unit: string, visually: boolean) → {line, ch, ?hitSide: boolean}</code></dt>
                <dd>Used to find the target position for horizontal cursor
                motion. <code>start</code> is a <code>{line, ch}</code>
                object, <code>amount</code> an integer (may be negative),
                and <code>unit</code> one of the
                string <code>"char"</code>, <code>"column"</code>,
                or <code>"word"</code>. Will return a position that is produced
                by moving <code>amount</code> times the distance specified
                by <code>unit</code>. When <code>visually</code> is true, motion
                in right-to-left text will be visual rather than logical. When
                the motion was clipped by hitting the end or start of the
                document, the returned value will have a <code>hitSide</code>
                property set to true.</dd>
                <dt id="findPosV"><code><strong>cm.findPosV</strong>(start: {line, ch}, amount: integer, unit: string) → {line, ch, ?hitSide: boolean}</code></dt>
                <dd>Similar to <a href="#findPosH"><code>findPosH</code></a>,
                but used for vertical motion. <code>unit</code> may
                be <code>"line"</code> or <code>"page"</code>. The other
                arguments and the returned value have the same interpretation as
                they have in <code>findPosH</code>.</dd>
          
                <dt id="findWordAt"><code><strong>cm.findWordAt</strong>(pos: {line, ch}) → {anchor: {line, ch}, head: {line, ch}}</code></dt>
                <dd>Returns the start and end of the 'word' (the stretch of
                letters, whitespace, or punctuation) at the given position.</dd>
              </dl>
          
              <h3 id="api_configuration">Configuration methods</h3>
          
              <dl>
                <dt id="setOption"><code><strong>cm.setOption</strong>(option: string, value: any)</code></dt>
                <dd>Change the configuration of the editor. <code>option</code>
                should the name of an <a href="#config">option</a>,
                and <code>value</code> should be a valid value for that
                option.</dd>
                <dt id="getOption"><code><strong>cm.getOption</strong>(option: string) → any</code></dt>
                <dd>Retrieves the current value of the given option for this
                editor instance.</dd>
          
                <dt id="addKeyMap"><code><strong>cm.addKeyMap</strong>(map: object, bottom: boolean)</code></dt>
                <dd>Attach an additional <a href="#keymaps">key map</a> to the
                editor. This is mostly useful for addons that need to register
                some key handlers without trampling on
                the <a href="#option_extraKeys"><code>extraKeys</code></a>
                option. Maps added in this way have a higher precedence than
                the <code>extraKeys</code>
                and <a href="#option_keyMap"><code>keyMap</code></a> options,
                and between them, the maps added earlier have a lower precedence
                than those added later, unless the <code>bottom</code> argument
                was passed, in which case they end up below other key maps added
                with this method.</dd>
                <dt id="removeKeyMap"><code><strong>cm.removeKeyMap</strong>(map: object)</code></dt>
                <dd>Disable a keymap added
                with <a href="#addKeyMap"><code>addKeyMap</code></a>. Either
                pass in the key map object itself, or a string, which will be
                compared against the <code>name</code> property of the active
                key maps.</dd>
          
                <dt id="addOverlay"><code><strong>cm.addOverlay</strong>(mode: string|object, ?options: object)</code></dt>
                <dd>Enable a highlighting overlay. This is a stateless mini-mode
                that can be used to add extra highlighting. For example,
                the <a href="../demo/search.html">search addon</a> uses it to
                highlight the term that's currently being
                searched. <code>mode</code> can be a <a href="#option_mode">mode
                spec</a> or a mode object (an object with
                a <a href="#token"><code>token</code></a> method).
                The <code>options</code> parameter is optional. If given, it
                should be an object. Currently, only the <code>opaque</code>
                option is recognized. This defaults to off, but can be given to
                allow the overlay styling, when not <code>null</code>, to
                override the styling of the base mode entirely, instead of the
                two being applied together.</dd>
                <dt id="removeOverlay"><code><strong>cm.removeOverlay</strong>(mode: string|object)</code></dt>
                <dd>Pass this the exact value passed for the <code>mode</code>
                parameter to <a href="#addOverlay"><code>addOverlay</code></a>,
                or a string that corresponds to the <code>name</code> propery of
                that value, to remove an overlay again.</dd>
          
                <dt id="on"><code><strong>cm.on</strong>(type: string, func: (...args))</code></dt>
                <dd>Register an event handler for the given event type (a
                string) on the editor instance. There is also
                a <code>CodeMirror.on(object, type, func)</code> version
                that allows registering of events on any object.</dd>
                <dt id="off"><code><strong>cm.off</strong>(type: string, func: (...args))</code></dt>
                <dd>Remove an event handler on the editor instance. An
                equivalent <code>CodeMirror.off(object, type,
                func)</code> also exists.</dd>
              </dl>
          
              <h3 id="api_doc">Document management methods</h3>
          
              <p id="Doc">Each editor is associated with an instance
              of <code>CodeMirror.Doc</code>, its document. A document
              represents the editor content, plus a selection, an undo history,
              and a <a href="#option_mode">mode</a>. A document can only be
              associated with a single editor at a time. You can create new
              documents by calling the <code>CodeMirror.Doc(text, mode,
              firstLineNumber)</code> constructor. The last two arguments are
              optional and can be used to set a mode for the document and make
              it start at a line number other than 0, respectively.</p>
          
              <dl>
                <dt id="getDoc"><code><strong>cm.getDoc</strong>() → Doc</code></dt>
                <dd>Retrieve the currently active document from an editor.</dd>
                <dt id="getEditor"><code><strong>doc.getEditor</strong>() → CodeMirror</code></dt>
                <dd>Retrieve the editor associated with a document. May
                return <code>null</code>.</dd>
          
                <dt id="swapDoc"><code><strong>cm.swapDoc</strong>(doc: CodeMirror.Doc) → Doc</code></dt>
                <dd>Attach a new document to the editor. Returns the old
                document, which is now no longer associated with an editor.</dd>
          
                <dt id="copy"><code><strong>doc.copy</strong>(copyHistory: boolean) → Doc</code></dt>
                <dd>Create an identical copy of the given doc.
                When <code>copyHistory</code> is true, the history will also be
                copied. Can not be called directly on an editor.</dd>
          
                <dt id="linkedDoc"><code><strong>doc.linkedDoc</strong>(options: object) → Doc</code></dt>
                <dd>Create a new document that's linked to the target document.
                Linked documents will stay in sync (changes to one are also
                applied to the other) until <a href="#unlinkDoc">unlinked</a>.
                These are the options that are supported:
                  <dl>
                    <dt id="linkedDoc_sharedHist"><code><strong>sharedHist</strong>: boolean</code></dt>
                    <dd>When turned on, the linked copy will share an undo
                    history with the original. Thus, something done in one of
                    the two can be undone in the other, and vice versa.</dd>
                    <dt id="linkedDoc_from"><code><strong>from</strong>: integer</code></dt>
                    <dt id="linkedDoc_to"><code><strong>to</strong>: integer</code></dt>
                    <dd>Can be given to make the new document a subview of the
                    original. Subviews only show a given range of lines. Note
                    that line coordinates inside the subview will be consistent
                    with those of the parent, so that for example a subview
                    starting at line 10 will refer to its first line as line 10,
                    not 0.</dd>
                    <dt id="linkedDoc_mode"><code><strong>mode</strong>: string|object</code></dt>
                    <dd>By default, the new document inherits the mode of the
                    parent. This option can be set to
                    a <a href="#option_mode">mode spec</a> to give it a
                    different mode.</dd>
                  </dl></dd>
                <dt id="unlinkDoc"><code><strong>doc.unlinkDoc</strong>(doc: CodeMirror.Doc)</code></dt>
                <dd>Break the link between two documents. After calling this,
                changes will no longer propagate between the documents, and, if
                they had a shared history, the history will become
                separate.</dd>
                <dt id="iterLinkedDocs"><code><strong>doc.iterLinkedDocs</strong>(function: (doc: CodeMirror.Doc, sharedHist: boolean))</code></dt>
                <dd>Will call the given function for all documents linked to the
                target document. It will be passed two arguments, the linked document
                and a boolean indicating whether that document shares history
                with the target.</dd>
              </dl>
          
              <h3 id="api_history">History-related methods</h3>
          
              <dl>
                <dt id="undo"><code><strong>doc.undo</strong>()</code></dt>
                <dd>Undo one edit (if any undo events are stored).</dd>
                <dt id="redo"><code><strong>doc.redo</strong>()</code></dt>
                <dd>Redo one undone edit.</dd>
          
                <dt id="undoSelection"><code><strong>doc.undoSelection</strong>()</code></dt>
                <dd>Undo one edit or selection change.</dd>
                <dt id="redoSelection"><code><strong>doc.redoSelection</strong>()</code></dt>
                <dd>Redo one undone edit or selection change.</dd>
          
                <dt id="historySize"><code><strong>doc.historySize</strong>() → {undo: integer, redo: integer}</code></dt>
                <dd>Returns an object with <code>{undo, redo}</code> properties,
                both of which hold integers, indicating the amount of stored
                undo and redo operations.</dd>
                <dt id="clearHistory"><code><strong>doc.clearHistory</strong>()</code></dt>
                <dd>Clears the editor's undo history.</dd>
                <dt id="getHistory"><code><strong>doc.getHistory</strong>() → object</code></dt>
                <dd>Get a (JSON-serializeable) representation of the undo history.</dd>
                <dt id="setHistory"><code><strong>doc.setHistory</strong>(history: object)</code></dt>
                <dd>Replace the editor's undo history with the one provided,
                which must be a value as returned
                by <a href="#getHistory"><code>getHistory</code></a>. Note that
                this will have entirely undefined results if the editor content
                isn't also the same as it was when <code>getHistory</code> was
                called.</dd>
              </dl>
          
              <h3 id="api_marker">Text-marking methods</h3>
          
              <dl>
                <dt id="markText"><code><strong>doc.markText</strong>(from: {line, ch}, to: {line, ch}, ?options: object) → TextMarker</code></dt>
                <dd>Can be used to mark a range of text with a specific CSS
                class name. <code>from</code> and <code>to</code> should
                be <code>{line, ch}</code> objects. The <code>options</code>
                parameter is optional. When given, it should be an object that
                may contain the following configuration options:
                <dl>
                  <dt id="mark_className"><code><strong>className</strong>: string</code></dt>
                  <dd>Assigns a CSS class to the marked stretch of text.</dd>
                  <dt id="mark_inclusiveLeft"><code><strong>inclusiveLeft</strong>: boolean</code></dt>
                  <dd>Determines whether
                  text inserted on the left of the marker will end up inside
                  or outside of it.</dd>
                  <dt id="mark_inclusiveRight"><code><strong>inclusiveRight</strong>: boolean</code></dt>
                  <dd>Like <code>inclusiveLeft</code>,
                  but for the right side.</dd>
                  <dt id="mark_atomic"><code><strong>atomic</strong>: boolean</code></dt>
                  <dd>Atomic ranges act as a single unit when cursor movement is
                  concerned—i.e. it is impossible to place the cursor inside of
                  them. In atomic ranges, <code>inclusiveLeft</code>
                  and <code>inclusiveRight</code> have a different meaning—they
                  will prevent the cursor from being placed respectively
                  directly before and directly after the range.</dd>
                  <dt id="mark_collapsed"><code><strong>collapsed</strong>: boolean</code></dt>
                  <dd>Collapsed ranges do not show up in the display. Setting a
                  range to be collapsed will automatically make it atomic.</dd>
                  <dt id="mark_clearOnEnter"><code><strong>clearOnEnter</strong>: boolean</code></dt>
                  <dd>When enabled, will cause the mark to clear itself whenever
                  the cursor enters its range. This is mostly useful for
                  text-replacement widgets that need to 'snap open' when the
                  user tries to edit them. The
                  <a href="#event_clear"><code>"clear"</code></a> event
                  fired on the range handle can be used to be notified when this
                  happens.</dd>
                  <dt id="mark_clearWhenEmpty"><code><strong>clearWhenEmpty</strong>: boolean</code></dt>
                  <dd>Determines whether the mark is automatically cleared when
                  it becomes empty. Default is true.</dd>
                  <dt id="mark_replacedWith"><code><strong>replacedWith</strong>: Element</code></dt>
                  <dd>Use a given node to display this range. Implies both
                  collapsed and atomic. The given DOM node <em>must</em> be an
                  inline element (as opposed to a block element).</dd>
                  <dt><code><strong>handleMouseEvents</strong>: boolean</code></dt>
                  <dd>When <code>replacedWith</code> is given, this determines
                  whether the editor will capture mouse and drag events
                  occurring in this widget. Default is false—the events will be
                  left alone for the default browser handler, or specific
                  handlers on the widget, to capture.</dd>
                  <dt id="mark_readOnly"><code><strong>readOnly</strong>: boolean</code></dt>
                  <dd>A read-only span can, as long as it is not cleared, not be
                  modified except by
                  calling <a href="#setValue"><code>setValue</code></a> to reset
                  the whole document. <em>Note:</em> adding a read-only span
                  currently clears the undo history of the editor, because
                  existing undo events being partially nullified by read-only
                  spans would corrupt the history (in the current
                  implementation).</dd>
                  <dt id="mark_addToHistory"><code><strong>addToHistory</strong>: boolean</code></dt>
                  <dd>When set to true (default is false), adding this marker
                  will create an event in the undo history that can be
                  individually undone (clearing the marker).</dd>
                  <dt id="mark_startStyle"><code><strong>startStyle</strong>: string</code></dt><dd>Can be used to specify
                  an extra CSS class to be applied to the leftmost span that
                  is part of the marker.</dd>
                  <dt id="mark_endStyle"><code><strong>endStyle</strong>: string</code></dt><dd>Equivalent
                  to <code>startStyle</code>, but for the rightmost span.</dd>
                  <dt id="mark_css"><code><strong>css</strong>: string</code></dt>
                  <dd>A string of CSS to be applied to the covered text. For example <code>"color: #fe3"</code>.</dd>
                  <dt id="mark_title"><code><strong>title</strong>:
                  string</code></dt><dd>When given, will give the nodes created
                  for this span a HTML <code>title</code> attribute with the
                  given value.</dd>
                  <dt id="mark_shared"><code><strong>shared</strong>: boolean</code></dt><dd>When the
                  target document is <a href="#linkedDoc">linked</a> to other
                  documents, you can set <code>shared</code> to true to make the
                  marker appear in all documents. By default, a marker appears
                  only in its target document.</dd>
                </dl>
                The method will return an object that represents the marker
                (with constructor <code>CodeMirror.TextMarker</code>), which
                exposes three methods:
                <code><strong>clear</strong>()</code>, to remove the mark,
                <code><strong>find</strong>()</code>, which returns
                a <code>{from, to}</code> object (both holding document
                positions), indicating the current position of the marked range,
                or <code>undefined</code> if the marker is no longer in the
                document, and finally <code><strong>changed</strong>()</code>,
                which you can call if you've done something that might change
                the size of the marker (for example changing the content of
                a <a href="#mark_replacedWith"><code>replacedWith</code></a>
                node), and want to cheaply update the display.</dd>
          
                <dt id="setBookmark"><code><strong>doc.setBookmark</strong>(pos: {line, ch}, ?options: object) → TextMarker</code></dt>
                <dd>Inserts a bookmark, a handle that follows the text around it
                as it is being edited, at the given position. A bookmark has two
                methods <code>find()</code> and <code>clear()</code>. The first
                returns the current position of the bookmark, if it is still in
                the document, and the second explicitly removes the bookmark.
                The options argument is optional. If given, the following
                properties are recognized:
                <dl>
                  <dt><code><strong>widget</strong>: Element</code></dt><dd>Can be used to display a DOM
                  node at the current location of the bookmark (analogous to
                  the <a href="#mark_replacedWith"><code>replacedWith</code></a>
                  option to <a href="#markText"><code>markText</code></a>).</dd>
                  <dt><code><strong>insertLeft</strong>: boolean</code></dt><dd>By default, text typed
                  when the cursor is on top of the bookmark will end up to the
                  right of the bookmark. Set this option to true to make it go
                  to the left instead.</dd>
                  <dt><code><strong>shared</strong>: boolean</code></dt><dd>See
                  the corresponding <a href="#mark_shared">option</a>
                  to <code>markText</code>.</dd>
                </dl></dd>
          
                <dt id="findMarks"><code><strong>doc.findMarks</strong>(from: {line, ch}, to: {line, ch}) → array&lt;TextMarker&gt;</code></dt>
                <dd>Returns an array of all the bookmarks and marked ranges
                found between the given positions.</dd>
                <dt id="findMarksAt"><code><strong>doc.findMarksAt</strong>(pos: {line, ch}) → array&lt;TextMarker&gt;</code></dt>
                <dd>Returns an array of all the bookmarks and marked ranges
                present at the given position.</dd>
                <dt id="getAllMarks"><code><strong>doc.getAllMarks</strong>() → array&lt;TextMarker&gt;</code></dt>
                <dd>Returns an array containing all marked ranges in the document.</dd>
              </dl>
          
              <h3 id="api_decoration">Widget, gutter, and decoration methods</h3>
          
              <dl>
                <dt id="setGutterMarker"><code><strong>cm.setGutterMarker</strong>(line: integer|LineHandle, gutterID: string, value: Element) → LineHandle</code></dt>
                <dd>Sets the gutter marker for the given gutter (identified by
                its CSS class, see
                the <a href="#option_gutters"><code>gutters</code></a> option)
                to the given value. Value can be either <code>null</code>, to
                clear the marker, or a DOM element, to set it. The DOM element
                will be shown in the specified gutter next to the specified
                line.</dd>
          
                <dt id="clearGutter"><code><strong>cm.clearGutter</strong>(gutterID: string)</code></dt>
                <dd>Remove all gutter markers in
                the <a href="#option_gutters">gutter</a> with the given ID.</dd>
          
                <dt id="addLineClass"><code><strong>doc.addLineClass</strong>(line: integer|LineHandle, where: string, class: string) → LineHandle</code></dt>
                <dd>Set a CSS class name for the given line. <code>line</code>
                can be a number or a line handle. <code>where</code> determines
                to which element this class should be applied, can can be one
                of <code>"text"</code> (the text element, which lies in front of
                the selection), <code>"background"</code> (a background element
                that will be behind the selection), <code>"gutter"</code> (the
                line's gutter space), or <code>"wrap"</code> (the wrapper node
                that wraps all of the line's elements, including gutter
                elements). <code>class</code> should be the name of the class to
                apply.</dd>
          
                <dt id="removeLineClass"><code><strong>doc.removeLineClass</strong>(line: integer|LineHandle, where: string, class: string) → LineHandle</code></dt>
                <dd>Remove a CSS class from a line. <code>line</code> can be a
                line handle or number. <code>where</code> should be one
                of <code>"text"</code>, <code>"background"</code>,
                or <code>"wrap"</code>
                (see <a href="#addLineClass"><code>addLineClass</code></a>). <code>class</code>
                can be left off to remove all classes for the specified node, or
                be a string to remove only a specific class.</dd>
          
                <dt id="lineInfo"><code><strong>cm.lineInfo</strong>(line: integer|LineHandle) → object</code></dt>
                <dd>Returns the line number, text content, and marker status of
                the given line, which can be either a number or a line handle.
                The returned object has the structure <code>{line, handle, text,
                gutterMarkers, textClass, bgClass, wrapClass, widgets}</code>,
                where <code>gutterMarkers</code> is an object mapping gutter IDs
                to marker elements, and <code>widgets</code> is an array
                of <a href="#addLineWidget">line widgets</a> attached to this
                line, and the various class properties refer to classes added
                with <a href="#addLineClass"><code>addLineClass</code></a>.</dd>
          
                <dt id="addWidget"><code><strong>cm.addWidget</strong>(pos: {line, ch}, node: Element, scrollIntoView: boolean)</code></dt>
                <dd>Puts <code>node</code>, which should be an absolutely
                positioned DOM node, into the editor, positioned right below the
                given <code>{line, ch}</code> position.
                When <code>scrollIntoView</code> is true, the editor will ensure
                that the entire node is visible (if possible). To remove the
                widget again, simply use DOM methods (move it somewhere else, or
                call <code>removeChild</code> on its parent).</dd>
          
                <dt id="addLineWidget"><code><strong>cm.addLineWidget</strong>(line: integer|LineHandle, node: Element, ?options: object) → LineWidget</code></dt>
                <dd>Adds a line widget, an element shown below a line, spanning
                the whole of the editor's width, and moving the lines below it
                downwards. <code>line</code> should be either an integer or a
                line handle, and <code>node</code> should be a DOM node, which
                will be displayed below the given line. <code>options</code>,
                when given, should be an object that configures the behavior of
                the widget. The following options are supported (all default to
                false):
                  <dl>
                    <dt><code><strong>coverGutter</strong>: boolean</code></dt>
                    <dd>Whether the widget should cover the gutter.</dd>
                    <dt><code><strong>noHScroll</strong>: boolean</code></dt>
                    <dd>Whether the widget should stay fixed in the face of
                    horizontal scrolling.</dd>
                    <dt><code><strong>above</strong>: boolean</code></dt>
                    <dd>Causes the widget to be placed above instead of below
                    the text of the line.</dd>
                    <dt><code><strong>handleMouseEvents</strong>: boolean</code></dt>
                    <dd>Determines whether the editor will capture mouse and
                    drag events occurring in this widget. Default is false—the
                    events will be left alone for the default browser handler,
                    or specific handlers on the widget, to capture.</dd>
                    <dt><code><strong>insertAt</strong>: integer</code></dt>
                    <dd>By default, the widget is added below other widgets for
                    the line. This option can be used to place it at a different
                    position (zero for the top, N to put it after the Nth other
                    widget). Note that this only has effect once, when the
                    widget is created.
                  </dl>
                Note that the widget node will become a descendant of nodes with
                CodeMirror-specific CSS classes, and those classes might in some
                cases affect it. This method returns an object that represents
                the widget placement. It'll have a <code>line</code> property
                pointing at the line handle that it is associated with, and the following methods:
                  <dl>
                    <dt id="widget_clear"><code><strong>clear</strong>()</code></dt><dd>Removes the widget.</dd>
                    <dt id="widget_changed"><code><strong>changed</strong>()</code></dt><dd>Call
                    this if you made some change to the widget's DOM node that
                    might affect its height. It'll force CodeMirror to update
                    the height of the line that contains the widget.</dd>
                  </dl>
                </dd>
              </dl>
          
              <h3 id="api_sizing">Sizing, scrolling and positioning methods</h3>
          
              <dl>
                <dt id="setSize"><code><strong>cm.setSize</strong>(width: number|string, height: number|string)</code></dt>
                <dd>Programatically set the size of the editor (overriding the
                applicable <a href="#css-resize">CSS
                rules</a>). <code>width</code> and <code>height</code>
                can be either numbers (interpreted as pixels) or CSS units
                (<code>"100%"</code>, for example). You can
                pass <code>null</code> for either of them to indicate that that
                dimension should not be changed.</dd>
          
                <dt id="scrollTo"><code><strong>cm.scrollTo</strong>(x: number, y: number)</code></dt>
                <dd>Scroll the editor to a given (pixel) position. Both
                arguments may be left as <code>null</code>
                or <code>undefined</code> to have no effect.</dd>
                <dt id="getScrollInfo"><code><strong>cm.getScrollInfo</strong>() → {left, top, width, height, clientWidth, clientHeight}</code></dt>
                <dd>Get an <code>{left, top, width, height, clientWidth,
                clientHeight}</code> object that represents the current scroll
                position, the size of the scrollable area, and the size of the
                visible area (minus scrollbars).</dd>
                <dt id="scrollIntoView"><code><strong>cm.scrollIntoView</strong>(what: {line, ch}|{left, top, right, bottom}|{from, to}|null, ?margin: number)</code></dt>
                <dd>Scrolls the given position into view. <code>what</code> may
                be <code>null</code> to scroll the cursor into view,
                a <code>{line, ch}</code> position to scroll a character into
                view, a <code>{left, top, right, bottom}</code> pixel range (in
                editor-local coordinates), or a range <code>{from, to}</code>
                containing either two character positions or two pixel squares.
                The <code>margin</code> parameter is optional. When given, it
                indicates the amount of vertical pixels around the given area
                that should be made visible as well.</dd>
          
                <dt id="cursorCoords"><code><strong>cm.cursorCoords</strong>(where: boolean|{line, ch}, mode: string) → {left, top, bottom}</code></dt>
                <dd>Returns an <code>{left, top, bottom}</code> object
                containing the coordinates of the cursor position.
                If <code>mode</code> is <code>"local"</code>, they will be
                relative to the top-left corner of the editable document. If it
                is <code>"page"</code> or not given, they are relative to the
                top-left corner of the page. If <code>mode</code>
                is <code>"window"</code>, the coordinates are relative to the
                top-left corner of the currently visible (scrolled)
                window. <code>where</code> can be a boolean indicating whether
                you want the start (<code>true</code>) or the end
                (<code>false</code>) of the selection, or, if a <code>{line,
                ch}</code> object is given, it specifies the precise position at
                which you want to measure.</dd>
                <dt id="charCoords"><code><strong>cm.charCoords</strong>(pos: {line, ch}, ?mode: string) → {left, right, top, bottom}</code></dt>
                <dd>Returns the position and dimensions of an arbitrary
                character. <code>pos</code> should be a <code>{line, ch}</code>
                object. This differs from <code>cursorCoords</code> in that
                it'll give the size of the whole character, rather than just the
                position that the cursor would have when it would sit at that
                position.</dd>
                <dt id="coordsChar"><code><strong>cm.coordsChar</strong>(object: {left, top}, ?mode: string) → {line, ch}</code></dt>
                <dd>Given an <code>{left, top}</code> object, returns
                the <code>{line, ch}</code> position that corresponds to it. The
                optional <code>mode</code> parameter determines relative to what
                the coordinates are interpreted. It may
                be <code>"window"</code>, <code>"page"</code> (the default),
                or <code>"local"</code>.</dd>
                <dt id="lineAtHeight"><code><strong>cm.lineAtHeight</strong>(height: number, ?mode: string) → number</code></dt>
                <dd>Computes the line at the given pixel
                height. <code>mode</code> can be one of the same strings
                that <a href="#coordsChar"><code>coordsChar</code></a>
                accepts.</dd>
                <dt id="heightAtLine"><code><strong>cm.heightAtLine</strong>(line: number, ?mode: string) → number</code></dt>
                <dd>Computes the height of the top of a line, in the coordinate
                system specified by <code>mode</code>
                (see <a href="#coordsChar"><code>coordsChar</code></a>), which
                defaults to <code>"page"</code>. When a line below the bottom of
                the document is specified, the returned value is the bottom of
                the last line in the document.</dd>
                <dt id="defaultTextHeight"><code><strong>cm.defaultTextHeight</strong>() → number</code></dt>
                <dd>Returns the line height of the default font for the editor.</dd>
                <dt id="defaultCharWidth"><code><strong>cm.defaultCharWidth</strong>() → number</code></dt>
                <dd>Returns the pixel width of an 'x' in the default font for
                the editor. (Note that for non-monospace fonts, this is mostly
                useless, and even for monospace fonts, non-ascii characters
                might have a different width).</dd>
          
                <dt id="getViewport"><code><strong>cm.getViewport</strong>() → {from: number, to: number}</code></dt>
                <dd>Returns a <code>{from, to}</code> object indicating the
                start (inclusive) and end (exclusive) of the currently rendered
                part of the document. In big documents, when most content is
                scrolled out of view, CodeMirror will only render the visible
                part, and a margin around it. See also
                the <a href="#event_viewportChange"><code>viewportChange</code></a>
                event.</dd>
          
                <dt id="refresh"><code><strong>cm.refresh</strong>()</code></dt>
                <dd>If your code does something to change the size of the editor
                element (window resizes are already listened for), or unhides
                it, you should probably follow up by calling this method to
                ensure CodeMirror is still looking as intended.</dd>
              </dl>
          
              <h3 id="api_mode">Mode, state, and token-related methods</h3>
          
              <p>When writing language-aware functionality, it can often be
              useful to hook into the knowledge that the CodeMirror language
              mode has. See <a href="#modeapi">the section on modes</a> for a
              more detailed description of how these work.</p>
          
              <dl>
                <dt id="getMode"><code><strong>doc.getMode</strong>() → object</code></dt>
                <dd>Gets the (outer) mode object for the editor. Note that this
                is distinct from <code>getOption("mode")</code>, which gives you
                the mode specification, rather than the resolved, instantiated
                <a href="#defineMode">mode object</a>.</dd>
          
                <dt id="getModeAt"><code><strong>doc.getModeAt</strong>(pos: {line, ch}) → object</code></dt>
                <dd>Gets the inner mode at a given position. This will return
                the same as <a href="#getMode"><code>getMode</code></a> for
                simple modes, but will return an inner mode for nesting modes
                (such as <code>htmlmixed</code>).</dd>
          
                <dt id="getTokenAt"><code><strong>cm.getTokenAt</strong>(pos: {line, ch}, ?precise: boolean) → object</code></dt>
                <dd>Retrieves information about the token the current mode found
                before the given position (a <code>{line, ch}</code> object). The
                returned object has the following properties:
                <dl>
                  <dt><code><strong>start</strong></code></dt><dd>The character (on the given line) at which the token starts.</dd>
                  <dt><code><strong>end</strong></code></dt><dd>The character at which the token ends.</dd>
                  <dt><code><strong>string</strong></code></dt><dd>The token's string.</dd>
                  <dt><code><strong>type</strong></code></dt><dd>The token type the mode assigned
                  to the token, such as <code>"keyword"</code>
                  or <code>"comment"</code> (may also be null).</dd>
                  <dt><code><strong>state</strong></code></dt><dd>The mode's state at the end of this token.</dd>
                </dl>
                If <code>precise</code> is true, the token will be guaranteed to be accurate based on recent edits. If false or
                not specified, the token will use cached state information, which will be faster but might not be accurate if
                edits were recently made and highlighting has not yet completed.
                </dd>
          
                <dt id="getLineTokens"><code><strong>cm.getLineTokens</strong>(line: integer, ?precise: boolean) → array&lt;{start, end, string, type, state}&gt;</code></dt>
                <dd>This is similar
                to <a href="#getTokenAt"><code>getTokenAt</code></a>, but
                collects all tokens for a given line into an array. It is much
                cheaper than repeatedly calling <code>getTokenAt</code>, which
                re-parses the part of the line before the token for every call.</dd>
          
                <dt id="getTokenTypeAt"><code><strong>cm.getTokenTypeAt</strong>(pos: {line, ch}) → string</code></dt>
                <dd>This is a (much) cheaper version
                of <a href="#getTokenAt"><code>getTokenAt</code></a> useful for
                when you just need the type of the token at a given position,
                and no other information. Will return <code>null</code> for
                unstyled tokens, and a string, potentially containing multiple
                space-separated style names, otherwise.</dd>
          
                <dt id="getHelpers"><code><strong>cm.getHelpers</strong>(pos: {line, ch}, type: string) → array&lt;helper&gt;</code></dt>
                <dd>Fetch the set of applicable helper values for the given
                position. Helpers provide a way to look up functionality
                appropriate for a mode. The <code>type</code> argument provides
                the helper namespace (see
                <a href="#registerHelper"><code>registerHelper</code></a>), in
                which the values will be looked up. When the mode itself has a
                property that corresponds to the <code>type</code>, that
                directly determines the keys that are used to look up the helper
                values (it may be either a single string, or an array of
                strings). Failing that, the mode's <code>helperType</code>
                property and finally the mode's name are used.</dd>
                <dd>For example, the JavaScript mode has a
                property <code>fold</code> containing <code>"brace"</code>. When
                the <code>brace-fold</code> addon is loaded, that defines a
                helper named <code>brace</code> in the <code>fold</code>
                namespace. This is then used by
                the <a href="#addon_foldcode"><code>foldcode</code></a> addon to
                figure out that it can use that folding function to fold
                JavaScript code.</dd>
                <dd>When any <a href="#registerGlobalHelper">'global'</a>
                helpers are defined for the given namespace, their predicates
                are called on the current mode and editor, and all those that
                declare they are applicable will also be added to the array that
                is returned.</dd>
          
                <dt id="getHelper"><code><strong>cm.getHelper</strong>(pos: {line, ch}, type: string) → helper</code></dt>
                <dd>Returns the first applicable helper value.
                See <a href="#getHelpers"><code>getHelpers</code></a>.</dd>
          
                <dt id="getStateAfter"><code><strong>cm.getStateAfter</strong>(?line: integer, ?precise: boolean) → object</code></dt>
                <dd>Returns the mode's parser state, if any, at the end of the
                given line number. If no line number is given, the state at the
                end of the document is returned. This can be useful for storing
                parsing errors in the state, or getting other kinds of
                contextual information for a line. <code>precise</code> is defined
                as in <code>getTokenAt()</code>.</dd>
              </dl>
          
              <h3 id="api_misc">Miscellaneous methods</h3>
          
              <dl>
                <dt id="operation"><code><strong>cm.operation</strong>(func: () → any) → any</code></dt>
                <dd>CodeMirror internally buffers changes and only updates its
                DOM structure after it has finished performing some operation.
                If you need to perform a lot of operations on a CodeMirror
                instance, you can call this method with a function argument. It
                will call the function, buffering up all changes, and only doing
                the expensive update after the function returns. This can be a
                lot faster. The return value from this method will be the return
                value of your function.</dd>
          
                <dt id="indentLine"><code><strong>cm.indentLine</strong>(line: integer, ?dir: string|integer)</code></dt>
                <dd>Adjust the indentation of the given line. The second
                argument (which defaults to <code>"smart"</code>) may be one of:
                  <dl>
                    <dt><code><strong>"prev"</strong></code></dt>
                    <dd>Base indentation on the indentation of the previous line.</dd>
                    <dt><code><strong>"smart"</strong></code></dt>
                    <dd>Use the mode's smart indentation if available, behave
                    like <code>"prev"</code> otherwise.</dd>
                    <dt><code><strong>"add"</strong></code></dt>
                    <dd>Increase the indentation of the line by
                    one <a href="#option_indentUnit">indent unit</a>.</dd>
                    <dt><code><strong>"subtract"</strong></code></dt>
                    <dd>Reduce the indentation of the line.</dd>
                    <dt><code><strong>&lt;integer></strong></code></dt>
                    <dd>Add (positive number) or reduce (negative number) the
                    indentation by the given amount of spaces.</dd>
                  </dl></dd>
          
                <dt id="toggleOverwrite"><code><strong>cm.toggleOverwrite</strong>(?value: bool)</code></dt>
                <dd>Switches between overwrite and normal insert mode (when not
                given an argument), or sets the overwrite mode to a specific
                state (when given an argument).</dd>
          
                <dt id="execCommand"><code><strong>cm.execCommand</strong>(name: string)</code></dt>
                <dd>Runs the <a href="#commands">command</a> with the given name on the editor.</dd>
          
                <dt id="posFromIndex"><code><strong>doc.posFromIndex</strong>(index: integer) → {line, ch}</code></dt>
                <dd>Calculates and returns a <code>{line, ch}</code> object for a
                zero-based <code>index</code> who's value is relative to the start of the
                editor's text. If the <code>index</code> is out of range of the text then
                the returned object is clipped to start or end of the text
                respectively.</dd>
                <dt id="indexFromPos"><code><strong>doc.indexFromPos</strong>(object: {line, ch}) → integer</code></dt>
                <dd>The reverse of <a href="#posFromIndex"><code>posFromIndex</code></a>.</dd>
          
                <dt id="focus"><code><strong>cm.focus</strong>()</code></dt>
                <dd>Give the editor focus.</dd>
          
                <dt id="getInputField"><code><strong>cm.getInputField</strong>() → Element</code></dt>
                <dd>Returns the input field for the editor. Will be a textarea
                or an editable div, depending on the value of
                the <a href="#option_inputStyle"><code>inputStyle</code></a>
                option.</dd>
                <dt id="getWrapperElement"><code><strong>cm.getWrapperElement</strong>() → Element</code></dt>
                <dd>Returns the DOM node that represents the editor, and
                controls its size. Remove this from your tree to delete an
                editor instance.</dd>
                <dt id="getScrollerElement"><code><strong>cm.getScrollerElement</strong>() → Element</code></dt>
                <dd>Returns the DOM node that is responsible for the scrolling
                of the editor.</dd>
                <dt id="getGutterElement"><code><strong>cm.getGutterElement</strong>() → Element</code></dt>
                <dd>Fetches the DOM node that contains the editor gutters.</dd>
              </dl>
          
              <h3 id="api_static">Static properties</h3>
              <p>The <code>CodeMirror</code> object itself provides
              several useful properties.</p>
          
              <dl>
                <dt id="version"><code><strong>CodeMirror.version</strong>: string</code></dt>
                <dd>It contains a string that indicates the version of the
                library. This is a triple of
                integers <code>"major.minor.patch"</code>,
                where <code>patch</code> is zero for releases, and something
                else (usually one) for dev snapshots.</dd>
          
                <dt id="fromTextArea"><code><strong>CodeMirror.fromTextArea</strong>(textArea: TextAreaElement, ?config: object)</code></dt>
                <dd>
                  The method provides another way to initialize an editor. It
                  takes a textarea DOM node as first argument and an optional
                  configuration object as second. It will replace the textarea
                  with a CodeMirror instance, and wire up the form of that
                  textarea (if any) to make sure the editor contents are put
                  into the textarea when the form is submitted. The text in the
                  textarea will provide the content for the editor. A CodeMirror
                  instance created this way has three additional methods:
                  <dl>
                    <dt id="save"><code><strong>cm.save</strong>()</code></dt>
                    <dd>Copy the content of the editor into the textarea.</dd>
          
                    <dt id="toTextArea"><code><strong>cm.toTextArea</strong>()</code></dt>
                    <dd>Remove the editor, and restore the original textarea (with
                    the editor's current content).</dd>
          
                    <dt id="getTextArea"><code><strong>cm.getTextArea</strong>() → TextAreaElement</code></dt>
                    <dd>Returns the textarea that the instance was based on.</dd>
                  </dl>
                </dd>
          
                <dt id="defaults"><code><strong>CodeMirror.defaults</strong>: object</code></dt>
                <dd>An object containing default values for
                all <a href="#config">options</a>. You can assign to its
                properties to modify defaults (though this won't affect editors
                that have already been created).</dd>
          
                <dt id="defineExtension"><code><strong>CodeMirror.defineExtension</strong>(name: string, value: any)</code></dt>
                <dd>If you want to define extra methods in terms of the
                CodeMirror API, it is possible to
                use <code>defineExtension</code>. This will cause the given
                value (usually a method) to be added to all CodeMirror instances
                created from then on.</dd>
          
                <dt id="defineDocExtension"><code><strong>CodeMirror.defineDocExtension</strong>(name: string, value: any)</code></dt>
                <dd>Like <a href="#defineExtenstion"><code>defineExtension</code></a>,
                but the method will be added to the interface
                for <a href="#Doc"><code>Doc</code></a> objects instead.</dd>
          
                <dt id="defineOption"><code><strong>CodeMirror.defineOption</strong>(name: string,
                default: any, updateFunc: function)</code></dt>
                <dd>Similarly, <code>defineOption</code> can be used to define new options for
                CodeMirror. The <code>updateFunc</code> will be called with the
                editor instance and the new value when an editor is initialized,
                and whenever the option is modified
                through <a href="#setOption"><code>setOption</code></a>.</dd>
          
                <dt id="defineInitHook"><code><strong>CodeMirror.defineInitHook</strong>(func: function)</code></dt>
                <dd>If your extention just needs to run some
                code whenever a CodeMirror instance is initialized,
                use <code>CodeMirror.defineInitHook</code>. Give it a function as
                its only argument, and from then on, that function will be called
                (with the instance as argument) whenever a new CodeMirror instance
                is initialized.</dd>
          
                <dt id="registerHelper"><code><strong>CodeMirror.registerHelper</strong>(type: string, name: string, value: helper)</code></dt>
                <dd>Registers a helper value with the given <code>name</code> in
                the given namespace (<code>type</code>). This is used to define
                functionality that may be looked up by mode. Will create (if it
                doesn't already exist) a property on the <code>CodeMirror</code>
                object for the given <code>type</code>, pointing to an object
                that maps names to values. I.e. after
                doing <code>CodeMirror.registerHelper("hint", "foo",
                myFoo)</code>, the value <code>CodeMirror.hint.foo</code> will
                point to <code>myFoo</code>.</dd>
          
                <dt id="registerGlobalHelper"><code><strong>CodeMirror.registerGlobalHelper</strong>(type: string, name: string, predicate: fn(mode, CodeMirror), value: helper)</code></dt>
                <dd>Acts
                like <a href="#registerHelper"><code>registerHelper</code></a>,
                but also registers this helper as 'global', meaning that it will
                be included by <a href="#getHelpers"><code>getHelpers</code></a>
                whenever the given <code>predicate</code> returns true when
                called with the local mode and editor.</dd>
          
                <dt id="Pos"><code><strong>CodeMirror.Pos</strong>(line: integer, ?ch: integer)</code></dt>
                <dd>A constructor for the <code>{line, ch}</code> objects that
                are used to represent positions in editor documents.</dd>
          
                <dt id="changeEnd"><code><strong>CodeMirror.changeEnd</strong>(change: object) → {line, ch}</code></dt>
                <dd>Utility function that computes an end position from a change
                (an object with <code>from</code>, <code>to</code>,
                and <code>text</code> properties, as passed to
                various <a href="#event_change">event handlers</a>). The
                returned position will be the end of the changed
                range, <em>after</em> the change is applied.</dd>
              </dl>
          </section>
          
          <section id=addons>
              <h2 id="addons">Addons</h2>
          
              <p>The <code>addon</code> directory in the distribution contains a
              number of reusable components that implement extra editor
              functionality (on top of extension functions
              like <a href="#defineOption"><code>defineOption</code></a>, <a href="#defineExtension"><code>defineExtension</code></a>,
              and <a href="#registerHelper"><code>registerHelper</code></a>). In
              brief, they are:</p>
          
              <dl>
                <dt id="addon_dialog"><a href="../addon/dialog/dialog.js"><code>dialog/dialog.js</code></a></dt>
                <dd>Provides a very simple way to query users for text input.
                Adds the <strong><code>openDialog(template, callback, options) →
                closeFunction</code></strong> method to CodeMirror instances,
                which can be called with an HTML fragment or a detached DOM
                node that provides the prompt (should include an <code>input</code>
                or <code>button</code> tag), and a callback function that is called
                when the user presses enter. It returns a function <code>closeFunction</code>
                which, if called, will close the dialog immediately.
                <strong><code>openDialog</code></strong> takes the following options:
                  <dl>
                    <dt><code><strong>closeOnEnter</strong></code>:</dt>
                    <dd>If true, the dialog will be closed when the user presses
                    enter in the input. Defaults to <code>true</code>.</dd>
                    <dt><code><strong>onKeyDown</strong></code>:</dt>
                    <dd>An event handler of the signature <code>(event, value, closeFunction)</code>
                    that will be called whenever <code>keydown</code> fires in the
                    dialog's input. If your callback returns <code>true</code>,
                    the dialog will not do any further processing of the event.</dd>
                    <dt><code><strong>onKeyUp</strong></code>:</dt>
                    <dd>Same as <code>onKeyDown</code> but for the
                    <code>keyup</code> event.</dd>
                    <dt><code><strong>onInput</strong></code>:</dt>
                    <dd>Same as <code>onKeyDown</code> but for the
                    <code>input</code> event.</dd>
                    <dt><code><strong>onClose</strong></code>:</dt>
                    <dd>A callback of the signature <code>(dialogInstance)</code>
                    that will be called after the dialog has been closed and
                    removed from the DOM. No return value.</dd>
                  </dl>
          
                <p>Also adds an <strong><code>openNotification(template, options) →
                closeFunction</code></strong> function that simply shows an HTML
                fragment as a notification at the top of the editor. It takes a
                single option: <code>duration</code>, the amount of time after
                which the notification will be automatically closed. If <code>
                duration</code> is zero, the dialog will not be closed automatically.</p>
          
                <p>Depends on <code>addon/dialog/dialog.css</code>.</p></dd>
          
                <dt id="addon_searchcursor"><a href="../addon/search/searchcursor.js"><code>search/searchcursor.js</code></a></dt>
                <dd>Adds the <code>getSearchCursor(query, start, caseFold) →
                cursor</code> method to CodeMirror instances, which can be used
                to implement search/replace functionality. <code>query</code>
                can be a regular expression or a string (only strings will match
                across lines—if they contain newlines). <code>start</code>
                provides the starting position of the search. It can be
                a <code>{line, ch}</code> object, or can be left off to default
                to the start of the document. <code>caseFold</code> is only
                relevant when matching a string. It will cause the search to be
                case-insensitive. A search cursor has the following methods:
                  <dl>
                    <dt><code><strong>findNext</strong>() → boolean</code></dt>
                    <dt><code><strong>findPrevious</strong>() → boolean</code></dt>
                    <dd>Search forward or backward from the current position.
                    The return value indicates whether a match was found. If
                    matching a regular expression, the return value will be the
                    array returned by the <code>match</code> method, in case you
                    want to extract matched groups.</dd>
                    <dt><code><strong>from</strong>() → {line, ch}</code></dt>
                    <dt><code><strong>to</strong>() → {line, ch}</code></dt>
                    <dd>These are only valid when the last call
                    to <code>findNext</code> or <code>findPrevious</code> did
                    not return false. They will return <code>{line, ch}</code>
                    objects pointing at the start and end of the match.</dd>
                    <dt><code><strong>replace</strong>(text: string)</code></dt>
                    <dd>Replaces the currently found match with the given text
                    and adjusts the cursor position to reflect the
                    replacement.</dd>
                  </dl></dd>
          
                <dt id="addon_search"><a href="../addon/search/search.js"><code>search/search.js</code></a></dt>
                <dd>Implements the search commands. CodeMirror has keys bound to
                these by default, but will not do anything with them unless an
                implementation is provided. Depends
                on <code>searchcursor.js</code>, and will make use
                of <a href="#addon_dialog"><code>openDialog</code></a> when
                available to make prompting for search queries less ugly.</dd>
          
                <dt id="addon_matchesonscrollbar"><a href="../addon/search/matchesonscrollbar.js"><code>search/matchesonscrollbar.js</code></a></dt>
                <dd>Adds a <code>showMatchesOnScrollbar</code> method to editor
                instances, which should be given a query (string or regular
                expression), optionally a case-fold flag (only applicable for
                strings), and optionally a class name (defaults
                to <code>CodeMirror-search-match</code>) as arguments. When
                called, matches of the given query will be displayed on the
                editor's vertical scrollbar. The method returns an object with
                a <code>clear</code> method that can be called to remove the
                matches. Depends on
                the <a href="#addon_annotatescrollbar"><code>annotatescrollbar</code></a>
                addon, and
                the <a href="../addon/search/matchesonscrollbar.css"><code>matchesonscrollbar.css</code></a>
                file provides a default (transparent yellowish) definition of
                the CSS class applied to the matches. Note that the matches are
                only perfectly aligned if your scrollbar does not have buttons
                at the top and bottom. You can use
                the <a href="#addon_simplescrollbars"><code>simplescrollbar</code></a>
                addon to make sure of this. If this addon is loaded,
                the <a href="#addon_search"><code>search</code></a> addon will
                automatically use it.</dd>
          
                <dt id="addon_matchbrackets"><a href="../addon/edit/matchbrackets.js"><code>edit/matchbrackets.js</code></a></dt>
                <dd>Defines an option <code>matchBrackets</code> which, when set
                to true, causes matching brackets to be highlighted whenever the
                cursor is next to them. It also adds a
                method <code>matchBrackets</code> that forces this to happen
                once, and a method <code>findMatchingBracket</code> that can be
                used to run the bracket-finding algorithm that this uses
                internally.</dd>
          
                <dt id="addon_closebrackets"><a href="../addon/edit/closebrackets.js"><code>edit/closebrackets.js</code></a></dt>
                <dd>Defines an option <code>autoCloseBrackets</code> that will
                auto-close brackets and quotes when typed. By default, it'll
                auto-close <code>()[]{}''""</code>, but you can pass it a string
                similar to that (containing pairs of matching characters), or an
                object with <code>pairs</code> and
                optionally <code>explode</code> properties to customize
                it. <code>explode</code> should be a similar string that gives
                the pairs of characters that, when enter is pressed between
                them, should have the second character also moved to its own
                line. <a href="../demo/closebrackets.html">Demo here</a>.</dd>
          
                <dt id="addon_matchtags"><a href="../addon/edit/matchtags.js"><code>edit/matchtags.js</code></a></dt>
                <dd>Defines an option <code>matchTags</code> that, when enabled,
                will cause the tags around the cursor to be highlighted (using
                the <code>CodeMirror-matchingtag</code> class). Also
                defines
                a <a href="#commands">command</a> <code>toMatchingTag</code>,
                which you can bind a key to in order to jump to the tag mathing
                the one under the cursor. Depends on
                the <code>addon/fold/xml-fold.js</code>
                addon. <a href="../demo/matchtags.html">Demo here.</a></dd>
          
                <dt id="addon_trailingspace"><a href="../addon/edit/trailingspace.js"><code>edit/trailingspace.js</code></a></dt>
                <dd>Adds an option <code>showTrailingSpace</code> which, when
                enabled, adds the CSS class <code>cm-trailingspace</code> to
                stretches of whitespace at the end of lines.
                The <a href="../demo/trailingspace.html">demo</a> has a nice
                squiggly underline style for this class.</dd>
          
                <dt id="addon_closetag"><a href="../addon/edit/closetag.js"><code>edit/closetag.js</code></a></dt>
                <dd>Defines an <code>autoCloseTags</code> option that will
                auto-close XML tags when '<code>&gt;</code>' or '<code>/</code>'
                is typed, and
                a <code>closeTag</code> <a href="#commands">command</a> that
                closes the nearest open tag. Depends on
                the <code>fold/xml-fold.js</code> addon. See
                the <a href="../demo/closetag.html">demo</a>.</dd>
          
                <dt id="addon_continuelist"><a href="../addon/edit/continuelist.js"><code>edit/continuelist.js</code></a></dt>
                <dd>Markdown specific. Defines
                a <code>"newlineAndIndentContinueMarkdownList"</code> <a href="#commands">command</a>
                command that can be bound to <code>enter</code> to automatically
                insert the leading characters for continuing a list. See
                the <a href="../mode/markdown/index.html">Markdown mode
                demo</a>.</dd>
          
                <dt id="addon_comment"><a href="../addon/comment/comment.js"><code>comment/comment.js</code></a></dt>
                <dd>Addon for commenting and uncommenting code. Adds three
                methods to CodeMirror instances:
                <dl>
                  <dt id="lineComment"><code><strong>lineComment</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
                  <dd>Set the lines in the given range to be line comments. Will
                  fall back to <code>blockComment</code> when no line comment
                  style is defined for the mode.</dd>
                  <dt id="blockComment"><code><strong>blockComment</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
                  <dd>Wrap the code in the given range in a block comment. Will
                  fall back to <code>lineComment</code> when no block comment
                  style is defined for the mode.</dd>
                  <dt id="uncomment"><code><strong>uncomment</strong>(from: {line, ch}, to: {line, ch}, ?options: object) → boolean</code></dt>
                  <dd>Try to uncomment the given range.
                    Returns <code>true</code> if a comment range was found and
                    removed, <code>false</code> otherwise.</dd>
                </dl>
                The <code>options</code> object accepted by these methods may
                have the following properties:
                <dl>
                  <dt><code>blockCommentStart, blockCommentEnd, blockCommentLead, lineComment: string</code></dt>
                  <dd>Override the <a href="#mode_comment">comment string
                  properties</a> of the mode with custom comment strings.</dd>
                  <dt><code><strong>padding</strong>: string</code></dt>
                  <dd>A string that will be inserted after opening and leading
                  markers, and before closing comment markers. Defaults to a
                  single space.</dd>
                  <dt><code><strong>commentBlankLines</strong>: boolean</code></dt>
                  <dd>Whether, when adding line comments, to also comment lines
                  that contain only whitespace.</dd>
                  <dt><code><strong>indent</strong>: boolean</code></dt>
                  <dd>When adding line comments and this is turned on, it will
                  align the comment block to the current indentation of the
                  first line of the block.</dd>
                  <dt><code><strong>fullLines</strong>: boolean</code></dt>
                  <dd>When block commenting, this controls whether the whole
                  lines are indented, or only the precise range that is given.
                  Defaults to <code>true</code>.</dd>
                </dl>
                The addon also defines
                a <code>toggleComment</code> <a href="#commands">command</a>,
                which will try to uncomment the current selection, and if that
                fails, line-comments it.</dd>
          
                <dt id="addon_foldcode"><a href="../addon/fold/foldcode.js"><code>fold/foldcode.js</code></a></dt>
                <dd>Helps with code folding. Adds a <code>foldCode</code> method
                to editor instances, which will try to do a code fold starting
                at the given line, or unfold the fold that is already present.
                The method takes as first argument the position that should be
                folded (may be a line number or
                a <a href="#Pos"><code>Pos</code></a>), and as second optional
                argument either a range-finder function, or an options object,
                supporting the following properties:
                <dl>
                  <dt><code><strong>rangeFinder</strong>: fn(CodeMirror, Pos)</code></dt>
                  <dd id="helper_fold_auto">The function that is used to find
                  foldable ranges. If this is not directly passed, it will
                  default to <code>CodeMirror.fold.auto</code>, which
                  uses <a href="#getHelpers"><code>getHelpers</code></a> with
                  a <code>"fold"</code> type to find folding functions
                  appropriate for the local mode. There are files in
                  the <a href="../addon/fold/"><code>addon/fold/</code></a>
                  directory providing <code>CodeMirror.fold.brace</code>, which
                  finds blocks in brace languages (JavaScript, C, Java,
                  etc), <code>CodeMirror.fold.indent</code>, for languages where
                  indentation determines block structure (Python, Haskell),
                  and <code>CodeMirror.fold.xml</code>, for XML-style languages,
                  and <code>CodeMirror.fold.comment</code>, for folding comment
                  blocks.</dd>
                  <dt><code><strong>widget</strong>: string|Element</code></dt>
                  <dd>The widget to show for folded ranges. Can be either a
                  string, in which case it'll become a span with
                  class <code>CodeMirror-foldmarker</code>, or a DOM node.</dd>
                  <dt><code><strong>scanUp</strong>: boolean</code></dt>
                  <dd>When true (default is false), the addon will try to find
                  foldable ranges on the lines above the current one if there
                  isn't an eligible one on the given line.</dd>
                  <dt><code><strong>minFoldSize</strong>: integer</code></dt>
                  <dd>The minimum amount of lines that a fold should span to be
                  accepted. Defaults to 0, which also allows single-line
                  folds.</dd>
                </dl>
                See <a href="../demo/folding.html">the demo</a> for an
                example.</dd>
          
                <dt id="addon_foldgutter"><a href="../addon/fold/foldgutter.js"><code>fold/foldgutter.js</code></a></dt>
                <dd>Provides an option <code>foldGutter</code>, which can be
                used to create a gutter with markers indicating the blocks that
                can be folded. Create a gutter using
                the <a href="#option_gutters"><code>gutters</code></a> option,
                giving it the class <code>CodeMirror-foldgutter</code> or
                something else if you configure the addon to use a different
                class, and this addon will show markers next to folded and
                foldable blocks, and handle clicks in this gutter. Note that
                CSS styles should be applied to make the gutter, and the fold
                markers within it, visible. A default set of CSS styles are
                available in:
                <a href="../addon/fold/foldgutter.css">
                  <code>addon/fold/foldgutter.css</code>
                </a>.
                The option
                can be either set to <code>true</code>, or an object containing
                the following optional option fields:
                <dl>
                  <dt><code><strong>gutter</strong>: string</code></dt>
                  <dd>The CSS class of the gutter. Defaults
                  to <code>"CodeMirror-foldgutter"</code>. You will have to
                  style this yourself to give it a width (and possibly a
                  background). See the default gutter style rules above.</dd>
                  <dt><code><strong>indicatorOpen</strong>: string | Element</code></dt>
                  <dd>A CSS class or DOM element to be used as the marker for
                  open, foldable blocks. Defaults
                  to <code>"CodeMirror-foldgutter-open"</code>.</dd>
                  <dt><code><strong>indicatorFolded</strong>: string | Element</code></dt>
                  <dd>A CSS class or DOM element to be used as the marker for
                  folded blocks. Defaults to <code>"CodeMirror-foldgutter-folded"</code>.</dd>
                  <dt><code><strong>rangeFinder</strong>: fn(CodeMirror, Pos)</code></dt>
                  <dd>The range-finder function to use when determining whether
                  something can be folded. When not
                  given, <a href="#helper_fold_auto"><code>CodeMirror.fold.auto</code></a>
                  will be used as default.</dd>
                </dl>
                The <code>foldOptions</code> editor option can be set to an
                object to provide an editor-wide default configuration.
                Demo <a href="../demo/folding.html">here</a>.</dd>
          
                <dt id="addon_runmode"><a href="../addon/runmode/runmode.js"><code>runmode/runmode.js</code></a></dt>
                <dd>Can be used to run a CodeMirror mode over text without
                actually opening an editor instance.
                See <a href="../demo/runmode.html">the demo</a> for an example.
                There are alternate versions of the file avaible for
                running <a href="../addon/runmode/runmode-standalone.js">stand-alone</a>
                (without including all of CodeMirror) and
                for <a href="../addon/runmode/runmode.node.js">running under
                node.js</a>.</dd>
          
                <dt id="addon_colorize"><a href="../addon/runmode/colorize.js"><code>runmode/colorize.js</code></a></dt>
                <dd>Provides a convenient way to syntax-highlight code snippets
                in a webpage. Depends on
                the <a href="#addon_runmode"><code>runmode</code></a> addon (or
                its standalone variant). Provides
                a <code>CodeMirror.colorize</code> function that can be called
                with an array (or other array-ish collection) of DOM nodes that
                represent the code snippets. By default, it'll get
                all <code>pre</code> tags. Will read the <code>data-lang</code>
                attribute of these nodes to figure out their language, and
                syntax-color their content using the relevant CodeMirror mode
                (you'll have to load the scripts for the relevant modes
                yourself). A second argument may be provided to give a default
                mode, used when no language attribute is found for a node. Used
                in this manual to highlight example code.</dd>
          
                <dt id="addon_overlay"><a href="../addon/mode/overlay.js"><code>mode/overlay.js</code></a></dt>
                <dd>Mode combinator that can be used to extend a mode with an
                'overlay' — a secondary mode is run over the stream, along with
                the base mode, and can color specific pieces of text without
                interfering with the base mode.
                Defines <code>CodeMirror.overlayMode</code>, which is used to
                create such a mode. See <a href="../demo/mustache.html">this
                demo</a> for a detailed example.</dd>
          
                <dt id="addon_multiplex"><a href="../addon/mode/multiplex.js"><code>mode/multiplex.js</code></a></dt>
                <dd>Mode combinator that can be used to easily 'multiplex'
                between several modes.
                Defines <code>CodeMirror.multiplexingMode</code> which, when
                given as first argument a mode object, and as other arguments
                any number of <code>{open, close, mode [, delimStyle, innerStyle]}</code>
                objects, will return a mode object that starts parsing using the
                mode passed as first argument, but will switch to another mode
                as soon as it encounters a string that occurs in one of
                the <code>open</code> fields of the passed objects. When in a
                sub-mode, it will go back to the top mode again when
                the <code>close</code> string is encountered.
                Pass <code>"\n"</code> for <code>open</code> or <code>close</code>
                if you want to switch on a blank line.
                <ul><li>When <code>delimStyle</code> is specified, it will be the token
                style returned for the delimiter tokens.</li>
                <li>When <code>innerStyle</code> is specified, it will be the token
                style added for each inner mode token.</li></ul>
                The outer mode will not see the content between the delimiters.
                See <a href="../demo/multiplex.html">this demo</a> for an
                example.</dd>
          
                <dt id="addon_show-hint"><a href="../addon/hint/show-hint.js"><code>hint/show-hint.js</code></a></dt>
                <dd>Provides a framework for showing autocompletion hints.
                Defines <code>editor.showHint</code>, which takes an optional
                options object, and pops up a widget that allows the user to
                select a completion. Finding hints is done with a hinting
                functions (the <code>hint</code> option), which is a function
                that take an editor instance and options object, and return
                a <code>{list, from, to}</code> object, where <code>list</code>
                is an array of strings or objects (the completions),
                and <code>from</code> and <code>to</code> give the start and end
                of the token that is being completed as <code>{line, ch}</code>
                objects.</dd>
                <dd>If no hinting function is given, the addon will
                use <code>CodeMirror.hint.auto</code>, which
                calls <a href="#getHelpers"><code>getHelpers</code></a> with
                the <code>"hint"</code> type to find applicable hinting
                functions, and tries them one by one. If that fails, it looks
                for a <code>"hintWords"</code> helper to fetch a list of
                completable words for the mode, and
                uses <code>CodeMirror.hint.fromList</code> to complete from
                those.</dd>
                <dd>When completions aren't simple strings, they should be
                objects with the following properties:
                <dl>
                  <dt><code><strong>text</strong>: string</code></dt>
                  <dd>The completion text. This is the only required
                  property.</dd>
                  <dt><code><strong>displayText</strong>: string</code></dt>
                  <dd>The text that should be displayed in the menu.</dd>
                  <dt><code><strong>className</strong>: string</code></dt>
                  <dd>A CSS class name to apply to the completion's line in the
                  menu.</dd>
                  <dt><code><strong>render</strong>: fn(Element, self, data)</code></dt>
                  <dd>A method used to create the DOM structure for showing the
                  completion by appending it to its first argument.</dd>
                  <dt><code><strong>hint</strong>: fn(CodeMirror, self, data)</code></dt>
                  <dd>A method used to actually apply the completion, instead of
                  the default behavior.</dd>
                  <dt><code><strong>from</strong>: {line, ch}</code></dt>
                  <dd>Optional <code>from</code> position that will be used by <code>pick()</code> instead
                  of the global one passed with the full list of completions.</dd>
                  <dt><code><strong>to</strong>: {line, ch}</code></dt>
                  <dd>Optional <code>to</code> position that will be used by <code>pick()</code> instead
                  of the global one passed with the full list of completions.</dd>
                </dl>
                The plugin understands the following options (the options object
                will also be passed along to the hinting function, which may
                understand additional options):
                <dl>
                  <dt><code><strong>hint</strong>: function</code></dt>
                  <dd>A hinting function, as specified above. It is possible to
                  set the <code>async</code> property on a hinting function to
                  true, in which case it will be called with
                  arguments <code>(cm, callback, ?options)</code>, and the
                  completion interface will only be popped up when the hinting
                  function calls the callback, passing it the object holding the
                  completions.</dd>
                  <dt><code><strong>completeSingle</strong>: boolean</code></dt>
                  <dd>Determines whether, when only a single completion is
                  available, it is completed without showing the dialog.
                  Defaults to true.</dd>
                  <dt><code><strong>alignWithWord</strong>: boolean</code></dt>
                  <dd>Whether the pop-up should be horizontally aligned with the
                  start of the word (true, default), or with the cursor (false).</dd>
                  <dt><code><strong>closeOnUnfocus</strong>: boolean</code></dt>
                  <dd>When enabled (which is the default), the pop-up will close
                  when the editor is unfocused.</dd>
                  <dt><code><strong>customKeys</strong>: keymap</code></dt>
                  <dd>Allows you to provide a custom key map of keys to be active
                  when the pop-up is active. The handlers will be called with an
                  extra argument, a handle to the completion menu, which
                  has <code>moveFocus(n)</code>, <code>setFocus(n)</code>, <code>pick()</code>,
                  and <code>close()</code> methods (see the source for details),
                  that can be used to change the focused element, pick the
                  current element or close the menu. Additionnaly <code>menuSize()</code>
                  can give you access to the size of the current dropdown menu,
                  <code>length</code> give you the number of availlable completions, and
                  <code>data</code> give you full access to the completion returned by the
                  hinting function.</dd>
                  <dt><code><strong>extraKeys</strong>: keymap</code></dt>
                  <dd>Like <code>customKeys</code> above, but the bindings will
                  be added to the set of default bindings, instead of replacing
                  them.</dd>
                </dl>
                The following events will be fired on the completions object
                during completion:
                <dl>
                  <dt><code><strong>"shown"</strong> ()</code></dt>
                  <dd>Fired when the pop-up is shown.</dd>
                  <dt><code><strong>"select"</strong> (completion, Element)</code></dt>
                  <dd>Fired when a completion is selected. Passed the completion
                  value (string or object) and the DOM node that represents it
                  in the menu.</dd>
                  <dt><code><strong>"pick"</strong> (completion)</code></dt>
                  <dd>Fired when a completion is picked. Passed the completion value
                  (string or object).</dd>
                  <dt><code><strong>"close"</strong> ()</code></dt>
                  <dd>Fired when the completion is finished.</dd>
                </dl>
                This addon depends on styles
                from <code>addon/hint/show-hint.css</code>. Check
                out <a href="../demo/complete.html">the demo</a> for an
                example.</dd>
          
                <dt id="addon_javascript-hint"><a href="../addon/hint/javascript-hint.js"><code>hint/javascript-hint.js</code></a></dt>
                <dd>Defines a simple hinting function for JavaScript
                (<code>CodeMirror.hint.javascript</code>) and CoffeeScript
                (<code>CodeMirror.hint.coffeescript</code>) code. This will
                simply use the JavaScript environment that the editor runs in as
                a source of information about objects and their properties.</dd>
          
                <dt id="addon_xml-hint"><a href="../addon/hint/xml-hint.js"><code>hint/xml-hint.js</code></a></dt>
                <dd>Defines <code>CodeMirror.hint.xml</code>, which produces
                hints for XML tagnames, attribute names, and attribute values,
                guided by a <code>schemaInfo</code> option (a property of the
                second argument passed to the hinting function, or the third
                argument passed to <code>CodeMirror.showHint</code>).<br>The
                schema info should be an object mapping tag names to information
                about these tags, with optionally a <code>"!top"</code> property
                containing a list of the names of valid top-level tags. The
                values of the properties should be objects with optional
                properties <code>children</code> (an array of valid child
                element names, omit to simply allow all tags to appear)
                and <code>attrs</code> (an object mapping attribute names
                to <code>null</code> for free-form attributes, and an array of
                valid values for restricted
                attributes). <a href="../demo/xmlcomplete.html">Demo
                here.</a></dd>
          
                <dt id="addon_html-hint"><a href="../addon/hint/html-hint.js"><code>hint/html-hint.js</code></a></dt>
                <dd>Provides schema info to
                the <a href="#addon_xml-hint">xml-hint</a> addon for HTML
                documents. Defines a schema
                object <code>CodeMirror.htmlSchema</code> that you can pass to
                as a <code>schemaInfo</code> option, and
                a <code>CodeMirror.hint.html</code> hinting function that
                automatically calls <code>CodeMirror.hint.xml</code> with this
                schema data. See
                the <a href="../demo/html5complete.html">demo</a>.</dd>
          
                <dt id="addon_css-hint"><a href="../addon/hint/css-hint.js"><code>hint/css-hint.js</code></a></dt>
                <dd>A hinting function for CSS, SCSS, or LESS code.
                Defines <code>CodeMirror.hint.css</code>.</dd>
          
                <dt id="addon_anyword-hint"><a href="../addon/hint/anyword-hint.js"><code>hint/anyword-hint.js</code></a></dt>
                <dd>A very simple hinting function
                (<code>CodeMirror.hint.anyword</code>) that simply looks for
                words in the nearby code and completes to those. Takes two
                optional options, <code>word</code>, a regular expression that
                matches words (sequences of one or more character),
                and <code>range</code>, which defines how many lines the addon
                should scan when completing (defaults to 500).</dd>
          
                <dt id="addon_sql-hint"><a href="../addon/hint/sql-hint.js"><code>hint/sql-hint.js</code></a></dt>
                <dd>A simple SQL hinter. Defines <code>CodeMirror.hint.sql</code>.
                Takes two optional options, <code>tables</code>, a object with
                table names as keys and array of respective column names as values,
                and <code>defaultTable</code>, a string corresponding to a
                table name in <code>tables</code> for autocompletion.</dd>
          
                <dt id="addon_match-highlighter"><a href="../addon/search/match-highlighter.js"><code>search/match-highlighter.js</code></a></dt>
                <dd>Adds a <code>highlightSelectionMatches</code> option that
                can be enabled to highlight all instances of a currently
                selected word. Can be set either to true or to an object
                containing the following options: <code>minChars</code>, for the
                minimum amount of selected characters that triggers a highlight
                (default 2), <code>style</code>, for the style to be used to
                highlight the matches (default <code>"matchhighlight"</code>,
                which will correspond to CSS
                class <code>cm-matchhighlight</code>),
                and <code>showToken</code> which can be set to <code>true</code>
                or to a regexp matching the characters that make up a word. When
                enabled, it causes the current word to be highlighted when
                nothing is selected (defaults to off).
                Demo <a href="../demo/matchhighlighter.html">here</a>.</dd>
          
                <dt id="addon_lint"><a href="../addon/lint/lint.js"><code>lint/lint.js</code></a></dt>
                <dd>Defines an interface component for showing linting warnings,
                with pluggable warning sources
                (see <a href="../addon/lint/json-lint.js"><code>json-lint.js</code></a>,
                <a href="../addon/lint/javascript-lint.js"><code>javascript-lint.js</code></a>,
                <a href="../addon/lint/coffeescript-lint.js"><code>coffeescript-lint.js</code></a>,
                and <a href="../addon/lint/css-lint.js"><code>css-lint.js</code></a>
                in the same directory). Defines a <code>lint</code> option that
                can be set to a warning source (for
                example <code>CodeMirror.lint.javascript</code>), or
                to <code>true</code>, in which
                case <a href="#getHelper"><code>getHelper</code></a> with
                type <code>"lint"</code> is used to determined a validator
                function. Depends on <code>addon/lint/lint.css</code>. A demo
                can be found <a href="../demo/lint.html">here</a>.</dd>
          
                <dt id="addon_mark-selection"><a href="../addon/selection/mark-selection.js"><code>selection/mark-selection.js</code></a></dt>
                <dd>Causes the selected text to be marked with the CSS class
                <code>CodeMirror-selectedtext</code> when the <code>styleSelectedText</code> option
                is enabled. Useful to change the colour of the selection (in addition to the background),
                like in <a href="../demo/markselection.html">this demo</a>.</dd>
          
                <dt id="addon_active-line"><a href="../addon/selection/active-line.js"><code>selection/active-line.js</code></a></dt>
                <dd>Defines a <code>styleActiveLine</code> option that, when enabled,
                gives the wrapper of the active line the class <code>CodeMirror-activeline</code>,
                and adds a background with the class <code>CodeMirror-activeline-background</code>.
                is enabled. See the <a href="../demo/activeline.html">demo</a>.</dd>
          
                <dt id="addon_selection-pointer"><a href="../addon/selection/selection-pointer.js"><code>selection/selection-pointer.js</code></a></dt>
                <dd>Defines a <code>selectionPointer</code> option which you can
                use to control the mouse cursor appearance when hovering over
                the selection. It can be set to a string,
                like <code>"pointer"</code>, or to true, in which case
                the <code>"default"</code> (arrow) cursor will be used. You can
                see a demo <a href="../mode/htmlmixed/index.html">here</a>.</dd>
          
                <dt id="addon_loadmode"><a href="../addon/mode/loadmode.js"><code>mode/loadmode.js</code></a></dt>
                <dd>Defines a <code>CodeMirror.requireMode(modename,
                callback)</code> function that will try to load a given mode and
                call the callback when it succeeded. You'll have to
                set <code>CodeMirror.modeURL</code> to a string that mode paths
                can be constructed from, for
                example <code>"mode/%N/%N.js"</code>—the <code>%N</code>'s will
                be replaced with the mode name. Also
                defines <code>CodeMirror.autoLoadMode(instance, mode)</code>,
                which will ensure the given mode is loaded and cause the given
                editor instance to refresh its mode when the loading
                succeeded. See the <a href="../demo/loadmode.html">demo</a>.</dd>
          
                <dt id="addon_meta"><a href="../mode/meta.js"><code>mode/meta.js</code></a></dt>
                <dd>Provides meta-information about all the modes in the
                distribution in a single file.
                Defines <code>CodeMirror.modeInfo</code>, an array of objects
                with <code>{name, mime, mode}</code> properties,
                where <code>name</code> is the human-readable
                name, <code>mime</code> the MIME type, and <code>mode</code> the
                name of the mode file that defines this MIME. There are optional
                properties <code>mimes</code>, which holds an array of MIME
                types for modes with multiple MIMEs associated,
                and <code>ext</code>, which holds an array of file extensions
                associated with this mode. Four convenience
                functions, <code>CodeMirror.findModeByMIME</code>,
                <code>CodeMirror.findModeByExtension</code>,
                <code>CodeMirror.findModeByFileName</code>
                and <code>CodeMirror.findModeByName</code> are provided, which
                return such an object given a MIME, extension, file name or mode name
                string. Note that, for historical reasons, this file resides in the
                top-level <code>mode</code> directory, not
                under <code>addon</code>. <a href="../demo/loadmode.html">Demo</a>.</dd>
          
                <dt id="addon_continuecomment"><a href="../addon/comment/continuecomment.js"><code>comment/continuecomment.js</code></a></dt>
                <dd>Adds a <code>continueComments</code> option, which sets whether the
                editor will make the next line continue a comment when you press Enter
                inside a comment block. Can be set to a boolean to enable/disable this
                functionality. Set to a string, it will continue comments using a custom
                shortcut. Set to an object, it will use the <code>key</code> property for
                a custom shortcut and the boolean <code>continueLineComment</code>
                property to determine whether single-line comments should be continued
                (defaulting to <code>true</code>).</dd>
          
                <dt id="addon_placeholder"><a href="../addon/display/placeholder.js"><code>display/placeholder.js</code></a></dt>
                <dd>Adds a <code>placeholder</code> option that can be used to
                make text appear in the editor when it is empty and not focused.
                Also gives the editor a <code>CodeMirror-empty</code> CSS class
                whenever it doesn't contain any text.
                See <a href="../demo/placeholder.html">the demo</a>.</dd>
          
                <dt id="addon_fullscreen"><a href="../addon/display/fullscreen.js"><code>display/fullscreen.js</code></a></dt>
                <dd>Defines an option <code>fullScreen</code> that, when set
                to <code>true</code>, will make the editor full-screen (as in,
                taking up the whole browser window). Depends
                on <a href="../addon/display/fullscreen.css"><code>fullscreen.css</code></a>. <a href="../demo/fullscreen.html">Demo
                here</a>.</dd>
          
                <dt id="addon_simplescrollbars"><a href="../addon/scroll/simplescrollbars.js"><code>scroll/simplescrollbars.js</code></a></dt>
                <dd>Defines two additional scrollbar
                models, <code>"simple"</code> and <code>"overlay"</code>
                (see <a href="../demo/simplescrollbars.html">demo</a>) that can
                be selected with
                the <a href="#option_scrollbarStyle"><code>scrollbarStyle</code></a>
                option. Depends
                on <a href="../addon/scroll/simplescrollbars.css"><code>simplescrollbars.css</code></a>,
                which can be further overridden to style your own
                scrollbars.</dd>
          
                <dt id="addon_annotatescrollbar"><a href="../addon/scroll/annotatescrollbar.js"><code>scroll/annotatescrollbar.js</code></a></dt>
                <dd>Provides functionality for showing markers on the scrollbar
                to call out certain parts of the document. Adds a
                method <code>annotateScrollbar</code> to editor instances that
                can be called, with a CSS class name as argument, to create a
                set of annotations. The method returns an object
                whose <code>update</code> method can be called with an array
                of <code>{from: Pos, to: Pos}</code> objects marking the ranges
                to be higlighed. To detach the annotations, call the
                object's <code>clear</code> method.</dd>
          
                <dt id="addon_rulers"><a href="../addon/display/rulers.js"><code>display/rulers.js</code></a></dt>
                <dd>Adds a <code>rulers</code> option, which can be used to show
                one or more vertical rulers in the editor. The option, if
                defined, should be given an array of <code>{column [, className,
                color, lineStyle, width]}</code> objects or numbers (wich
                indicate a column). The ruler will be displayed at the column
                indicated by the number or the <code>column</code> property.
                The <code>className</code> property can be used to assign a
                custom style to a ruler. <a href="../demo/rulers.html">Demo
                here</a>.</dd>
          
                <dt id="addon_panel"><a href="../addon/display/panel.js"><code>display/panel.js</code></a></dt>
                <dd>Defines an <code>addPanel</code> method for CodeMirror
                instances, which places a DOM node above or below an editor, and
                shrinks the editor to make room for the node. The method takes
                as first argument as DOM node, and as second an optional options
                object. By default, the panel ends up above the editor. This can
                be changed by passing a <code>position</code> option with the
                value <code>"bottom"</code>. The object returned by this method
                has a <code>clear</code> method that is used to remove the
                panel, and a <code>changed</code> method that can be used to
                notify the addon when the size of the panel's DOM node has
                changed.</dd>
          
                <dt id="addon_hardwrap"><a href="../addon/wrap/hardwrap.js"><code>wrap/hardwrap.js</code></a></dt>
                <dd>Addon to perform hard line wrapping/breaking for paragraphs
                of text. Adds these methods to editor instances:
                  <dl>
                    <dt><code><strong>wrapParagraph</strong>(?pos: {line, ch}, ?options: object)</code></dt>
                    <dd>Wraps the paragraph at the given position.
                    If <code>pos</code> is not given, it defaults to the cursor
                    position.</dd>
                    <dt><code><strong>wrapRange</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
                    <dd>Wraps the given range as one big paragraph.</dd>
                    <dt><code><strong>wrapParagraphsInRange</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
                    <dd>Wrapps the paragraphs in (and overlapping with) the
                    given range individually.</dd>
                  </dl>
                  The following options are recognized:
                  <dl>
                    <dt><code><strong>paragraphStart</strong>, <strong>paragraphEnd</strong>: RegExp</code></dt>
                    <dd>Blank lines are always considered paragraph boundaries.
                    These options can be used to specify a pattern that causes
                    lines to be considered the start or end of a paragraph.</dd>
                    <dt><code><strong>column</strong>: number</code></dt>
                    <dd>The column to wrap at. Defaults to 80.</dd>
                    <dt><code><strong>wrapOn</strong>: RegExp</code></dt>
                    <dd>A regular expression that matches only those
                    two-character strings that allow wrapping. By default, the
                    addon wraps on whitespace and after dash characters.</dd>
                    <dt><code><strong>killTrailingSpace</strong>: boolean</code></dt>
                    <dd>Whether trailing space caused by wrapping should be
                    preserved, or deleted. Defaults to true.</dd>
                  </dl>
                  A demo of the addon is available <a href="../demo/hardwrap.html">here</a>.
                </dd>
          
                <dt id="addon_merge"><a href="../addon/merge/merge.js"><code>merge/merge.js</code></a></dt>
                <dd>Implements an interface for merging changes, using either a
                2-way or a 3-way view. The <code>CodeMirror.MergeView</code>
                constructor takes arguments similar to
                the <a href="#CodeMirror"><code>CodeMirror</code></a>
                constructor, first a node to append the interface to, and then
                an options object. Options are passed through to the editors
                inside the view. These extra options are recognized:
                  <dl>
                    <dt><code><strong>origLeft</strong></code> and <code><strong>origRight</strong>: string</code></dt>
                    <dd>If given these provide original versions of the
                    document, which will be shown to the left and right of the
                    editor in non-editable CodeMirror instances. The merge
                    interface will highlight changes between the editable
                    document and the original(s). To create a 2-way (as opposed
                    to 3-way) merge view, provide only one of them.</dd>
                    <dt><code><strong>revertButtons</strong>: boolean</code></dt>
                    <dd>Determines whether buttons that allow the user to revert
                    changes are shown. Defaults to true.</dd>
                    <dt><code><strong>connect</strong>: string</code></dt>
                    <dd>Sets the style used to connect changed chunks of code.
                    By default, connectors are drawn. When this is set
                    to <code>"align"</code>, the smaller chunk is padded to
                    align with the bigger chunk instead.</dd>
                    <dt><code><strong>collapseIdentical</strong>: boolean|number</code></dt>
                    <dd>When true (default is false), stretches of unchanged
                    text will be collapsed. When a number is given, this
                    indicates the amount of lines to leave visible around such
                    stretches (which defaults to 2).</dd>
                    <dt><code><strong>allowEditingOriginals</strong>: boolean</code></dt>
                    <dd>Determines whether the original editor allows editing.
                    Defaults to false.</dd>
                    <dt><code><strong>showDifferences</strong>: boolean</code></dt>
                    <dd>When true (the default), changed pieces of text are
                    highlighted.</dd>
                  </dl>
                  <a href="../demo/merge.html">Demo here</a>.</dd>
          
                <dt id="addon_tern"><a href="../addon/tern/tern.js"><code>tern/tern.js</code></a></dt>
                <dd>Provides integration with
                the <a href="http://ternjs.net">Tern</a> JavaScript analysis
                engine, for completion, definition finding, and minor
                refactoring help. See the <a href="../demo/tern.html">demo</a>
                for a very simple integration. For more involved scenarios, see
                the comments at the top of
                the <a href="../addon/tern/tern.js">addon</a> and the
                implementation of the
                (multi-file) <a href="http://ternjs.net/doc/demo.html">demonstration
                on the Tern website</a>.</dd>
              </dl>
          </section>
          
          <section id=modeapi>
              <h2>Writing CodeMirror Modes</h2>
          
              <p>Modes typically consist of a single JavaScript file. This file
              defines, in the simplest case, a lexer (tokenizer) for your
              language—a function that takes a character stream as input,
              advances it past a token, and returns a style for that token. More
              advanced modes can also handle indentation for the language.</p>
          
              <p>This section describes the low-level mode interface. Many modes
              are written directly against this, since it offers a lot of
              control, but for a quick mode definition, you might want to use
              the <a href="../demo/simplemode.html">simple mode addon</a>.</p>
          
              <p id="defineMode">The mode script should
              call <code><strong>CodeMirror.defineMode</strong></code> to
              register itself with CodeMirror. This function takes two
              arguments. The first should be the name of the mode, for which you
              should use a lowercase string, preferably one that is also the
              name of the files that define the mode (i.e. <code>"xml"</code> is
              defined in <code>xml.js</code>). The second argument should be a
              function that, given a CodeMirror configuration object (the thing
              passed to the <code>CodeMirror</code> function) and an optional
              mode configuration object (as in
              the <a href="#option_mode"><code>mode</code></a> option), returns
              a mode object.</p>
          
              <p>Typically, you should use this second argument
              to <code>defineMode</code> as your module scope function (modes
              should not leak anything into the global scope!), i.e. write your
              whole mode inside this function.</p>
          
              <p>The main responsibility of a mode script is <em>parsing</em>
              the content of the editor. Depending on the language and the
              amount of functionality desired, this can be done in really easy
              or extremely complicated ways. Some parsers can be stateless,
              meaning that they look at one element (<em>token</em>) of the code
              at a time, with no memory of what came before. Most, however, will
              need to remember something. This is done by using a <em>state
              object</em>, which is an object that is always passed when
              reading a token, and which can be mutated by the tokenizer.</p>
          
              <p id="startState">Modes that use a state must define
              a <code><strong>startState</strong></code> method on their mode
              object. This is a function of no arguments that produces a state
              object to be used at the start of a document.</p>
          
              <p id="token">The most important part of a mode object is
              its <code><strong>token</strong>(stream, state)</code> method. All
              modes must define this method. It should read one token from the
              stream it is given as an argument, optionally update its state,
              and return a style string, or <code>null</code> for tokens that do
              not have to be styled. For your styles, you are encouraged to use
              the 'standard' names defined in the themes (without
              the <code>cm-</code> prefix). If that fails, it is also possible
              to come up with your own and write your own CSS theme file.<p>
          
              <p id="token_style_line">A typical token string would
              be <code>"variable"</code> or <code>"comment"</code>. Multiple
              styles can be returned (separated by spaces), for
              example <code>"string error"</code> for a thing that looks like a
              string but is invalid somehow (say, missing its closing quote).
              When a style is prefixed by <code>"line-"</code>
              or <code>"line-background-"</code>, the style will be applied to
              the whole line, analogous to what
              the <a href="#addLineClass"><code>addLineClass</code></a> method
              does—styling the <code>"text"</code> in the simple case, and
              the <code>"background"</code> element
              when <code>"line-background-"</code> is prefixed.</p>
          
              <p id="StringStream">The stream object that's passed
              to <code>token</code> encapsulates a line of code (tokens may
              never span lines) and our current position in that line. It has
              the following API:</p>
          
              <dl>
                <dt><code><strong>eol</strong>() → boolean</code></dt>
                <dd>Returns true only if the stream is at the end of the
                line.</dd>
                <dt><code><strong>sol</strong>() → boolean</code></dt>
                <dd>Returns true only if the stream is at the start of the
                line.</dd>
          
                <dt><code><strong>peek</strong>() → string</code></dt>
                <dd>Returns the next character in the stream without advancing
                it. Will return an <code>null</code> at the end of the
                line.</dd>
                <dt><code><strong>next</strong>() → string</code></dt>
                <dd>Returns the next character in the stream and advances it.
                Also returns <code>null</code> when no more characters are
                available.</dd>
          
                <dt><code><strong>eat</strong>(match: string|regexp|function(char: string) → boolean) → string</code></dt>
                <dd><code>match</code> can be a character, a regular expression,
                or a function that takes a character and returns a boolean. If
                the next character in the stream 'matches' the given argument,
                it is consumed and returned. Otherwise, <code>undefined</code>
                is returned.</dd>
                <dt><code><strong>eatWhile</strong>(match: string|regexp|function(char: string) → boolean) → boolean</code></dt>
                <dd>Repeatedly calls <code>eat</code> with the given argument,
                until it fails. Returns true if any characters were eaten.</dd>
                <dt><code><strong>eatSpace</strong>() → boolean</code></dt>
                <dd>Shortcut for <code>eatWhile</code> when matching
                white-space.</dd>
                <dt><code><strong>skipToEnd</strong>()</code></dt>
                <dd>Moves the position to the end of the line.</dd>
                <dt><code><strong>skipTo</strong>(ch: string) → boolean</code></dt>
                <dd>Skips to the next occurrence of the given character, if
                found on the current line (doesn't advance the stream if the
                character does not occur on the line). Returns true if the
                character was found.</dd>
                <dt><code><strong>match</strong>(pattern: string, ?consume: boolean, ?caseFold: boolean) → boolean</code></dt>
                <dt><code><strong>match</strong>(pattern: regexp, ?consume: boolean) → array&lt;string&gt;</code></dt>
                <dd>Act like a
                multi-character <code>eat</code>—if <code>consume</code> is true
                or not given—or a look-ahead that doesn't update the stream
                position—if it is false. <code>pattern</code> can be either a
                string or a regular expression starting with <code>^</code>.
                When it is a string, <code>caseFold</code> can be set to true to
                make the match case-insensitive. When successfully matching a
                regular expression, the returned value will be the array
                returned by <code>match</code>, in case you need to extract
                matched groups.</dd>
          
                <dt><code><strong>backUp</strong>(n: integer)</code></dt>
                <dd>Backs up the stream <code>n</code> characters. Backing it up
                further than the start of the current token will cause things to
                break, so be careful.</dd>
                <dt><code><strong>column</strong>() → integer</code></dt>
                <dd>Returns the column (taking into account tabs) at which the
                current token starts.</dd>
                <dt><code><strong>indentation</strong>() → integer</code></dt>
                <dd>Tells you how far the current line has been indented, in
                spaces. Corrects for tab characters.</dd>
          
                <dt><code><strong>current</strong>() → string</code></dt>
                <dd>Get the string between the start of the current token and
                the current stream position.</dd>
              </dl>
          
              <p id="blankLine">By default, blank lines are simply skipped when
              tokenizing a document. For languages that have significant blank
              lines, you can define
              a <code><strong>blankLine</strong>(state)</code> method on your
              mode that will get called whenever a blank line is passed over, so
              that it can update the parser state.</p>
          
              <p id="copyState">Because state object are mutated, and CodeMirror
              needs to keep valid versions of a state around so that it can
              restart a parse at any line, copies must be made of state objects.
              The default algorithm used is that a new state object is created,
              which gets all the properties of the old object. Any properties
              which hold arrays get a copy of these arrays (since arrays tend to
              be used as mutable stacks). When this is not correct, for example
              because a mode mutates non-array properties of its state object, a
              mode object should define
              a <code><strong>copyState</strong></code> method, which is given a
              state and should return a safe copy of that state.</p>
          
              <p id="indent">If you want your mode to provide smart indentation
              (through the <a href="#indentLine"><code>indentLine</code></a>
              method and the <code>indentAuto</code>
              and <code>newlineAndIndent</code> commands, to which keys can be
              <a href="#option_extraKeys">bound</a>), you must define
              an <code><strong>indent</strong>(state, textAfter)</code> method
              on your mode object.</p>
          
              <p>The indentation method should inspect the given state object,
              and optionally the <code>textAfter</code> string, which contains
              the text on the line that is being indented, and return an
              integer, the amount of spaces to indent. It should usually take
              the <a href="#option_indentUnit"><code>indentUnit</code></a>
              option into account. An indentation method may
              return <code>CodeMirror.Pass</code> to indicate that it
              could not come up with a precise indentation.</p>
          
              <p id="mode_comment">To work well with
              the <a href="#addon_comment">commenting addon</a>, a mode may
              define <code><strong>lineComment</strong></code> (string that
              starts a line
              comment), <code><strong>blockCommentStart</strong></code>, <code><strong>blockCommentEnd</strong></code>
              (strings that start and end block comments),
              and <code>blockCommentLead</code> (a string to put at the start of
              continued lines in a block comment). All of these are
              optional.</p>
          
              <p id="electricChars">Finally, a mode may define either
              an <code>electricChars</code> or an <code>electricInput</code>
              property, which are used to automatically reindent the line when
              certain patterns are typed and
              the <a href="#option_electricChars"><code>electricChars</code></a>
              option is enabled. <code>electricChars</code> may be a string, and
              will trigger a reindent whenever one of the characters in that
              string are typed. Often, it is more appropriate to
              use <code>electricInput</code>, which should hold a regular
              expression, and will trigger indentation when the part of the
              line <em>before</em> the cursor matches the expression. It should
              usually end with a <code>$</code> character, so that it only
              matches when the indentation-changing pattern was just typed, not when something was
              typed after the pattern.</p>
          
              <p>So, to summarize, a mode <em>must</em> provide
              a <code>token</code> method, and it <em>may</em>
              provide <code>startState</code>, <code>copyState</code>,
              and <code>indent</code> methods. For an example of a trivial mode,
              see the <a href="../mode/diff/diff.js">diff mode</a>, for a more
              involved example, see the <a href="../mode/clike/clike.js">C-like
              mode</a>.</p>
          
              <p>Sometimes, it is useful for modes to <em>nest</em>—to have one
              mode delegate work to another mode. An example of this kind of
              mode is the <a href="../mode/htmlmixed/htmlmixed.js">mixed-mode HTML
              mode</a>. To implement such nesting, it is usually necessary to
              create mode objects and copy states yourself. To create a mode
              object, there are <code>CodeMirror.getMode(options,
              parserConfig)</code>, where the first argument is a configuration
              object as passed to the mode constructor function, and the second
              argument is a mode specification as in
              the <a href="#option_mode"><code>mode</code></a> option. To copy a
              state object, call <code>CodeMirror.copyState(mode, state)</code>,
              where <code>mode</code> is the mode that created the given
              state.</p>
          
              <p id="innerMode">In a nested mode, it is recommended to add an
              extra method, <code><strong>innerMode</strong></code> which, given
              a state object, returns a <code>{state, mode}</code> object with
              the inner mode and its state for the current position. These are
              used by utility scripts such as the <a href="#addon_closetag">tag
              closer</a> to get context information. Use
              the <code>CodeMirror.innerMode</code> helper function to, starting
              from a mode and a state, recursively walk down to the innermost
              mode and state.</p>
          
              <p>To make indentation work properly in a nested parser, it is
              advisable to give the <code>startState</code> method of modes that
              are intended to be nested an optional argument that provides the
              base indentation for the block of code. The JavaScript and CSS
              parser do this, for example, to allow JavaScript and CSS code
              inside the mixed-mode HTML mode to be properly indented.</p>
          
              <p id="defineMIME">It is possible, and encouraged, to associate
              your mode, or a certain configuration of your mode, with
              a <a href="http://en.wikipedia.org/wiki/MIME">MIME</a> type. For
              example, the JavaScript mode associates itself
              with <code>text/javascript</code>, and its JSON variant
              with <code>application/json</code>. To do this,
              call <code><strong>CodeMirror.defineMIME</strong>(mime,
              modeSpec)</code>, where <code>modeSpec</code> can be a string or
              object specifying a mode, as in
              the <a href="#option_mode"><code>mode</code></a> option.</p>
          
              <p>If a mode specification wants to add some properties to the
              resulting mode object, typically for use
              with <a href="#getHelpers"><code>getHelpers</code></a>, it may
              contain a <code>modeProps</code> property, which holds an object.
              This object's properties will be copied to the actual mode
              object.</p>
          
              <p id="extendMode">Sometimes, it is useful to add or override mode
              object properties from external code.
              The <code><strong>CodeMirror.extendMode</strong></code> function
              can be used to add properties to mode objects produced for a
              specific mode. Its first argument is the name of the mode, its
              second an object that specifies the properties that should be
              added. This is mostly useful to add utilities that can later be
              looked up through <a href="#getMode"><code>getMode</code></a>.</p>
          </section>
          
          </article>
          
          <script>setTimeout(function(){CodeMirror.colorize();}, 20);</script>
          
        • realworld.html
          <!doctype html>
          
          <title>CodeMirror: Real-world Uses</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Real-world uses</a>
            </ul>
          </div>
          
          <article>
          
          <h2>CodeMirror real-world uses</h2>
          
              <p>Create a <a href="https://github.com/codemirror/codemirror">pull
              request</a> if you'd like your project to be added to this list.</p>
          
              <ul>
                <li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
                <li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>
                <li><a href="http://apachegui.ca/">Apache GUI</a></li>
                <li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>
                <li><a href="https://chrome.google.com/webstore/detail/better-text-viewer/lcaidopdffhfemoefoaadecppnjdknkc">Better Text Viewer</a> (plain text reader app for Chrome)</li>
                <li><a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a> (code hosting)</li>
                <li><a href="http://buzz.blogger.com/2013/04/improvements-to-blogger-template-html.html">Blogger's template editor</a></li>
                <li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>
                <li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>
                <li><a href="https://developers.google.com/chrome-developer-tools/">Chrome DevTools</a></li>
                <li><a href="http://clickhelp.co/">ClickHelp</a> (technical writing tool)</li>
                <li><a href="http://codeworld.info/">CodeWorld</a> (Haskell playground)</li>
                <li><a href="http://complete-ly.appspot.com/playground/code.playground.html">Complete.ly playground</a></li>
                <li><a href="https://codeanywhere.com/">Codeanywhere</a> (multi-platform cloud editor)</li>
                <li><a href="http://drupal.org/project/cpn">Code per Node</a> (Drupal module)</li>
                <li><a href="http://www.codebugapp.com/">Codebug</a> (PHP Xdebug front-end)</li>
                <li><a href="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</li>
                <li><a href="http://emmet.io/blog/codemirror-movie/">CodeMirror movie</a> (scripted editing demos)</li>
                <li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>
                <li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li>
                <li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>
                <li><a href="https://coderpad.io/">Coderpad</a> (interviewing tool)</li>
                <li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li>
                <li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li>
                <li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li>
                <li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
                <li><a href="http://www.codezample.com">CodeZample</a> (code snippet sharing)</li>
                <li><a href="http://codio.com">Codio</a> (Web IDE)</li>
                <li><a href="http://ot.substance.io/demo/">Collaborative CodeMirror demo</a> (CodeMirror + operational transforms)</li>
                <li><a href="http://www.communitycodecamp.com/">Community Code Camp</a> (code snippet sharing)</li>
                <li><a href="http://www.compilejava.net/">compilejava.net</a> (online Java sandbox)</li>
                <li><a href="http://www.ckwnc.com/">CKWNC</a> (UML editor)</li>
                <li><a href="http://www.crossui.com/">CrossUI</a> (cross-platform UI builder)</li>
                <li><a href="http://rsnous.com/cruncher/">Cruncher</a> (notepad with calculation features)</li>
                <li><a href="http://www.crudzilla.com/">Crudzilla</a> (self-hosted web IDE)</li>
                <li><a href="http://cssdeck.com/">CSSDeck</a> (CSS showcase)</li>
                <li><a href="http://ireneros.com/deck/deck.js-codemirror/introduction/#textarea-code">Deck.js integration</a> (slides with editors)</li>
                <li><a href="http://www.dbninja.com">DbNinja</a> (MySQL access interface)</li>
                <li><a href="https://chat.echoplex.us/">Echoplexus</a> (chat and collaborative coding)</li>
                <li><a href="http://www.ecsspert.com/">eCSSpert</a> (CSS demos and experiments)</li>
                <li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>
                <li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>
                <li><a href="http://emmet.io">Emmet</a> (fast XML editing)</li>
                <li><a href="https://github.com/espruino/EspruinoWebIDE">Espruino Web IDE</a> (Chrome App for writing code on Espruino devices)</li>
                <li><a href="http://www.fastfig.com/">Fastfig</a> (online computation/math tool)</li>
                <li><a href="https://metacpan.org/module/Farabi">Farabi</a> (modern Perl IDE)</li>
                <li><a href="http://blog.pamelafox.org/2012/02/interactive-html5-slides-with-fathomjs.html">FathomJS integration</a> (slides with editors, again)</li>
                <li><a href="https://phantomus.com/">Phantomus</a> (blogging platform)</li>
                <li><a href="http://fiddlesalad.com/">Fiddle Salad</a> (web development environment)</li>
                <li><a href="https://github.com/simogeo/Filemanager">Filemanager</a></li>
                <li><a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox Developer Tools</a></li>
                <li><a href="http://www.firepad.io">Firepad</a> (collaborative text editor)</li>
                <li><a href="https://code.google.com/p/gerrit/">Gerrit</a>'s diff view</li>
                <li><a href="https://github.com/maks/git-crx">Git Crx</a> (Chrome App for browsing local git repos)</li>
                <li><a href="http://tour.golang.org">Go language tour</a></li>
                <li><a href="https://github.com/github/android">GitHub's Android app</a></li>
                <li><a href="https://script.google.com/">Google Apps Script</a></li>
                <li><a href="http://web.uvic.ca/~siefkenj/graphit/graphit.html">Graphit</a> (function graphing)</li>
                <li><a href="http://www.handcraft.com/">Handcraft</a> (HTML prototyping)</li>
                <li><a href="http://hawkee.com/">Hawkee</a></li>
                <li><a href="http://try.haxe.org">Haxe</a> (Haxe Playground) </li>
                <li><a href="http://haxpad.com/">HaxPad</a> (editor for Win RT)</li>
                <li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>
                <li><a href="http://www.homegenie.it/docs/automation_getstarted.php">Homegenie</a> (home automation server)</li>
                <li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
                <li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li>
                <li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li>
                <li><a href="http://www.janvas.com/">Janvas</a> (vector graphics editor)</li>
                <li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>
                <li><a href="http://jqfundamentals.com/">jQuery fundamentals</a> (interactive tutorial)</li>
                <li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
                <li><a href="http://tool.jser.com/preprocessor">JSER preprocessor</a></li>
                <li><a href="https://github.com/kucherenko/jscpd">jscpd</a> (code duplication detector)</li>
                <li><a href="http://jsfiddle.com">jsfiddle.com</a> (another JS playground)</li>
                <li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
                <li><a href="http://jumpseller.com/">Jumpseller</a> (online store builder)</li>
                <li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
                <li><a href="http://kodtest.com/">Kodtest</a> (HTML/JS/CSS playground)</li>
                <li><a href="https://laborate.io/">Laborate</a> (collaborative coding)</li>
                <li><a href="http://lighttable.com/">Light Table</a> (experimental IDE)</li>
                <li><a href="http://liveweave.com/">Liveweave</a> (HTML/CSS/JS scratchpad)</li>
                <li><a href="http://marklighteditor.com/">Marklight editor</a> (lightweight markup editor)</li>
                <li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
                <li><a href="http://www.iunbug.com/mihtool">MIHTool</a> (iOS web-app debugging tool)</li>
                <li><a href="http://mongo-mapreduce-webbrowser.opensagres.cloudbees.net/">Mongo MapReduce WebBrowser</a></li>
                <li><a href="http://montagestudio.com/">Montage Studio</a> (web app creator suite)</li>
                <li><a href="http://mvcplayground.apphb.com/">MVC Playground</a></li>
                <li><a href="https://www.my2ndgeneration.com/">My2ndGeneration</a> (social coding)</li>
                <li><a href="http://www.navigatecms.com">Navigate CMS</a></li>
                <li><a href="https://github.com/soliton4/nodeMirror">nodeMirror</a> (IDE project)</li>
                <li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
                <li><a href="http://oakoutliner.com">Oak</a> (online outliner)</li>
                <li><a href="http://clrhome.org/asm/">ORG</a> (z80 assembly IDE)</li>
                <li><a href="https://github.com/mamacdon/orion-codemirror">Orion-CodeMirror integration</a> (running CodeMirror modes in Orion)</li>
                <li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
                <li><a href="http://prinbit.com/">PrinBit</a> (collaborative coding tool)</li>
                <li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>
                <li><a href="https://pypi.python.org/pypi/PubliForge/">PubliForge</a> (online publishing system)</li>
                <li><a href="http://www.puzzlescript.net/">Puzzlescript</a> (puzzle game engine)</li>
                <li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
                <li><a href="http://qyapp.com">QiYun web app platform</a></li>
                <li><a href="http://ariya.ofilabs.com/2011/09/hybrid-webnative-desktop-codemirror.html">Qt+Webkit integration</a> (building a desktop CodeMirror app)</li>
                <li><a href="http://www.quivive-file-manager.com">Quivive File Manager</a></li>
                <li><a href="http://rascalmicro.com/docs/basic-tutorial-getting-started.html">Rascal</a> (tiny computer)</li>
                <li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li>
                <li><a href="https://cloud.sagemath.com/">SageMathCloud</a> (interactive mathematical software environment)</li>
                <li><a href="https://chrome.google.com/webstore/detail/servephp/mnpikomdchjhkhbhmbboehfdjkobbfpo">ServePHP</a> (PHP code testing in Chrome dev tools)</li>
                <li><a href="https://www.shadertoy.com/">Shadertoy</a> (shader sharing)</li>
                <li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
                <li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li>
                <li><a href="http://snaptomato.appspot.com/editor.html">Snap Tomato</a> (HTML editing/testing page)</li>
                <li><a href="http://snippets.pro/">Snippets.pro</a> (code snippet sharing)</li>
                <li><a href="http://www.solidshops.com/">SolidShops</a> (hosted e-commerce platform)</li>
                <li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
                <li><a href="http://www.subte.org/page/programar-ta-te-ti-online/">SubTe</a> (AI bot programming environment)</li>
                <li><a href="http://xuanji.appspot.com/isicp/">Structure and Interpretation of Computer Programs</a>, Interactive Version</li>
                <li><a href="http://syframework.alwaysdata.net">SyBox</a> (PHP playground)</li>
                <li><a href="http://www.tagspaces.org/">TagSpaces</a> (personal data manager)</li>
                <li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
                <li><a href="http://www.mapbox.com/tilemill/">TileMill</a> (map design tool)</li>
                <li><a href="http://doc.tiki.org/Syntax+Highlighter">Tiki</a> (wiki CMS groupware)</li>
                <li><a href="http://www.toolsverse.com/products/data-explorer/">Toolsverse Data Explorer</a> (database management)</li>
                <li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>
                <li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li>
                <li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li>
                <li><a href="http://uicod.com/">uiCod</a> (animation demo gallery and sharing)</li>
                <li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li>
                <li><a href="https://upsource.jetbrains.com/#idea/view/923f30395f2603cd9f42a32bcafd13b6c28de0ff/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java">Upsource</a> (code viewer)</li>
                <li><a href="https://github.com/mgaitan/waliki">Waliki</a> (wiki engine)</li>
                <li><a href="http://wamer.net/">Wamer</a> (web application builder)</li>
                <li><a href="https://github.com/brettz9/webappfind">webappfind</a> (windows file bindings for webapps)</li>
                <li><a href="http://www.webglacademy.com/">WebGL academy</a> (learning WebGL)</li>
                <li><a href="http://webglplayground.net/">WebGL playground</a></li>
                <li><a href="https://www.webkit.org/blog/2518/state-of-web-inspector/#source-code">WebKit Web inspector</a></li>
                <li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
                <li><a href="https://github.com/b3log/wide">Wide</a> (golang web IDE)</li>
                <li><a href="http://wordpress.org/extend/plugins/codemirror-for-codeeditor/">WordPress plugin</a></li>
                <li><a href="https://www.writelatex.com">writeLaTeX</a> (Collaborative LaTeX Editor)</li>
                <li><a href="http://www.xosystem.org/home/applications_websites/xosystem_website/xoside_EN.php">XOSide</a> (online editor)</li>
                <li><a href="http://videlibri.sourceforge.net/cgi-bin/xidelcgi">XQuery tester</a></li>
                <li><a href="http://q42jaap.github.io/xsd2codemirror/">xsd2codemirror</a> (convert XSD to CM XML completion info)</li>
              </ul>
          
          </article>
          
          
        • releases.html
          <!doctype html>
          
          <title>CodeMirror: Release History</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active data-default="true" href="#v4">Version 4.x</a>
              <li><a href="#v3">Version 3.x</a>
              <li><a href="#v2">Version 2.x</a>
              <li><a href="#v1">Version 0.x</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Release notes and version history</h2>
          
          <section id=v4 class=first>
          
            <h2>Version 4.x</h2>
          
            <p class="rel">20-02-2015: <a href="http://codemirror.net/codemirror-5.0.zip">Version 5.0</a>:</p>
          
            <ul class="rel-note">
              <li>Experimental mobile support (tested on iOS, Android Chrome, stock Android browser)</li>
              <li>New option <a href="manual.html#option_inputStyle"><code>inputStyle</code></a> to switch between hidden textarea and contenteditable input.</li>
              <li>The <a href="manual.html#getInputField"><code>getInputField</code></a>
              method is no longer guaranteed to return a textarea.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.13.0...5.0.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-02-2015: <a href="http://codemirror.net/codemirror-4.13.zip">Version 4.13</a>:</p>
          
            <ul class="rel-note">
              <li>Fix the way the <a href="../demo/closetag.html"><code>closetag</code></a> demo handles the slash character.</li>
              <li>New modes: <a href="../mode/forth/index.html">Forth</a>, <a href="../mode/stylus/index.html">Stylus</a>.</li>
              <li>Make the <a href="../mode/css/index.html">CSS mode</a> understand some modern CSS extensions.</li>
              <li>Have the <a href="../mode/clike/index.html">Scala mode</a> handle symbols and triple-quoted strings.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.12.0...4.13.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-01-2015: <a href="http://codemirror.net/codemirror-4.12.zip">Version 4.12</a>:</p>
          
            <ul class="rel-note">
              <li>The <a href="manual.html#addon_closetag"><code>closetag</code></a>
              addon now defines a <code>"closeTag"</code> command.</li>
              <li>Adds a <code>findModeByFileName</code> to the <a href="manual.html#addon_meta">mode metadata</a>
              addon.</li>
              <li><a href="../demo/simplemode.html">Simple mode</a> rules can
              now contain a <code>sol</code> property to only match at the start
              of a line.</li>
              <li>New
              addon: <a href="manual.html#addon_selection-pointer"><code>selection-pointer</code></a>
              to style the mouse cursor over the selection.</li>
              <li>Improvements to the <a href="../mode/sass/index.html">Sass mode</a>'s indentation.</li>
              <li>The <a href="../demo/vim.html">Vim keymap</a>'s search functionality now
              supports <a href="manual.html#addon_matchesonscrollbar">scrollbar
              annotation</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.11.0...4.12.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">9-01-2015: <a href="http://codemirror.net/codemirror-4.11.zip">Version 4.11</a>:</p>
          
            <p class="rel-note">Unfortunately, 4.10 did not take care of the
            Firefox scrolling issue entirely. This release adds two more patches
            to address that.</p>
          
            <p class="rel">29-12-2014: <a href="http://codemirror.net/codemirror-4.10.zip">Version 4.10</a>:</p>
          
            <p class="rel-note">Emergency single-patch update to 4.9. Fixes
            Firefox-specific problem where the cursor could end up behind the
            horizontal scrollbar.</p>
          
            <p class="rel">23-12-2014: <a href="http://codemirror.net/codemirror-4.9.zip">Version 4.9</a>:</p>
          
            <ul class="rel-note">
              <li>Overhauled scroll bar handling.
              Add pluggable <a href="../demo/simplescrollbars.html">scrollbar
              implementations</a>.</li>
              <li>Tweaked behavior for
              the <a href="manual.html#addon_show-hint">completion addons</a> to
              not take text after cursor into account.</li>
              <li>Two new optional features in
              the <a href="manual.html#addon_merge">merge addon</a>: aligning
              editors, and folding unchanged text.</li>
              <li>New
              modes: <a href="../mode/dart/index.html">Dart</a>, <a href="../mode/ebnf/index.html">EBNF</a>, <a href="../mode/spreadsheet/index.html">spreadsheet</a>,
              and <a href="../mode/soy/index.html">Soy</a>.</li>
              <li>New <a href="../demo/panel.html">addon</a> to show persistent panels below/above an editor.</li>
              <li>New themes: <a href="../demo/theme.html?zenburn">zenburn</a>
              and <a href="../demo/theme.html?tomorrow-night-bright">tomorrow night
              bright</a>.</li>
              <li>Allow ctrl-click to clear existing cursors.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.8.0...4.9.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-11-2014: <a href="http://codemirror.net/codemirror-4.8.zip">Version 4.8</a>:</p>
          
            <ul class="rel-note">
              <li>Built-in support for <a href="manual.html#normalizeKeyMap">multi-stroke key bindings</a>.</li>
              <li>New method: <a href="manual.html#getLineTokens"><code>getLineTokens</code></a>.</li>
              <li>New modes: <a href="../mode/dockerfile/index.html">dockerfile</a>, <a href="../mode/idl/index.html">IDL</a>, <a href="../mode/clike/index.html">Objective C</a> (crude).</li>
              <li>Support styling of gutter backgrounds, allow <code>"gutter"</code> styles in <a href="manual.html#addLineClass"><code>addLineClass</code></a>.</li>
              <li>Many improvements to the <a href="../demo/vim.html">Vim mode</a>, rewritten visual mode.</li>
              <li>Improvements to modes: <a href="../mode/gfm/index.html">gfm</a> (strikethrough), <a href="../mode/sparql/index.html">SPARQL</a> (version 1.1 support), and <a href="../mode/stex/index.html">sTeX</a> (no more runaway math mode).
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.7.0...4.8.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-10-2014: <a href="http://codemirror.net/codemirror-4.7.zip">Version 4.7</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Incompatible</strong>:
              The <a href="../demo/lint.html">lint addon</a> now passes the
              editor's value as first argument to asynchronous lint functions,
              for consistency. The editor is still passed, as fourth
              argument.</li>
              <li>Improved handling of unicode identifiers in modes for
              languages that support them.</li>
              <li>More mode
              improvements: <a href="../mode/coffeescript/index.html">CoffeeScript</a>
              (indentation), <a href="../mode/verilog/index.html">Verilog</a>
              (indentation), <a href="../mode/clike/index.html">Scala</a>
              (indentation, triple-quoted strings),
              and <a href="../mode/php/index.html">PHP</a> (interpolated
              variables in heredoc strings).</li>
              <li>New modes: <a href="../mode/textile/index.html">Textile</a> and <a href="../mode/tornado/index.html">Tornado templates</a>.</li>
              <li>Experimental new <a href="../demo/simplemode.html">way to define modes</a>.</li>
              <li>Improvements to the <a href="../demo/vim.html">Vim
              bindings</a>: Arbitrary insert mode key mappings are now possible,
              and text objects are supported in visual mode.</li>
              <li>The mode <a href="../mode/meta.js">meta-information file</a>
              now includes information about file extensions,
              and <a href="manual.html#addon_meta">helper
              functions</a> <code>findModeByMIME</code>
              and <code>findModeByExtension</code>.</li>
              <li>New logo!</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.6.0...4.7.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2014: <a href="http://codemirror.net/codemirror-4.6.zip">Version 4.6</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/modelica/index.html">Modelica</a></li>
              <li>New method: <a href="manual.html#findWordAt"><code>findWordAt</code></a></li>
              <li>Make it easier to <a href="../demo/markselection.html">use text background styling</a></li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.5.0...4.6.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-08-2014: <a href="http://codemirror.net/codemirror-4.5.zip">Version 4.5</a>:</p>
          
            <ul class="rel-note">
              <li>Fix several serious bugs with horizontal scrolling</li>
              <li>New mode: <a href="../mode/slim/index.html">Slim</a></li>
              <li>New command: <a href="manual.html#command_goLineLeftSmart"><code>goLineLeftSmart</code></a></li>
              <li>More fixes and extensions for the <a href="../demo/vim.html">Vim</a> visual block mode</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.4.0...4.5.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-07-2014: <a href="http://codemirror.net/codemirror-4.4.zip">Version 4.4</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Note:</strong> Some events might now fire in slightly
              different order (<code>"change"</code> is still guaranteed to fire
              before <code>"cursorActivity"</code>)</li>
              <li>Nested operations in multiple editors are now synced (complete
              at same time, reducing DOM reflows)</li>
              <li>Visual block mode for <a href="../demo/vim.html">vim</a> (&lt;C-v>) is nearly complete</li>
              <li>New mode: <a href="../mode/kotlin/index.html">Kotlin</a></li>
              <li>Better multi-selection paste for text copied from multiple CodeMirror selections</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.3.0...4.4.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">23-06-2014: <a href="http://codemirror.net/codemirror-4.3.zip">Version 4.3</a>:</p>
          
            <ul class="rel-note">
              <li>Several <a href="../demo/vim.html">vim bindings</a>
              improvements: search and exCommand history, global flag
              for <code>:substitute</code>, <code>:global</code> command.
              <li>Allow hiding the cursor by
              setting <a href="manual.html#option_cursorBlinkRate"><code>cursorBlinkRate</code></a>
              to a negative value.</li>
              <li>Make gutter markers themeable, use this in foldgutter.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.2.0...4.3.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-05-2014: <a href="http://codemirror.net/codemirror-4.2.zip">Version 4.2</a>:</p>
          
            <ul class="rel-note">
              <li>Fix problem where some modes were broken by the fact that empty tokens were forbidden.</li>
              <li>Several fixes to context menu handling.</li>
              <li>On undo, scroll <em>change</em>, not cursor, into view.</li>
              <li>Rewritten <a href="../mode/jade/index.html">Jade</a> mode.</li>
              <li>Various improvements to <a href="../mode/shell/index.html">Shell</a> (support for more syntax) and <a href="../mode/python/index.html">Python</a> (better indentation) modes.</li>
              <li>New mode: <a href="../mode/cypher/index.html">Cypher</a>.</li>
              <li>New theme: <a href="../demo/theme.html?neo">Neo</a>.</li>
              <li>Support direct styling options (color, line style, width) in the <a href="manual.html#addon_rulers">rulers</a> addon.</li>
              <li>Recognize per-editor configuration for the <a href="manual.html#addon_show-hint">show-hint</a> and <a href="manual.html#addon_foldcode">foldcode</a> addons.</li>
              <li>More intelligent scanning for existing close tags in <a href="manual.html#addon_closetag">closetag</a> addon.</li>
              <li>In the <a href="../demo/vim.html">Vim bindings</a>: Fix bracket matching, support case conversion in visual mode, visual paste, append action.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.1.0...4.2.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-4.1.zip">Version 4.1</a>:</p>
          
            <ul class="rel-note">
              <li><em>Slightly incompatible</em>:
              The <a href="manual.html#event_cursorActivity"><code>"cursorActivity"</code></a>
              event now fires after all other events for the operation (and only
              for handlers that were actually registered at the time the
              activity happened).</li>
              <li>New command: <a href="manual.html#command_insertSoftTab"><code>insertSoftTab</code></a>.</li>
              <li>New mode: <a href="../mode/django/index.html">Django</a>.</li>
              <li>Improved modes: <a href="../mode/verilog/index.html">Verilog</a> (rewritten), <a href="../mode/jinja2/index.html">Jinja2</a>, <a href="../mode/haxe/index.html">Haxe</a>, <a href="../mode/php/index.html">PHP</a> (string interpolation highlighted), <a href="../mode/javascript/index.html">JavaScript</a> (indentation of trailing else, template strings), <a href="../mode/livescript/index.html">LiveScript</a> (multi-line strings).</li>
              <li>Many small issues from the 3.x→4.x transition were found and fixed.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.0.3...4.1.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-4.0.zip">Version 4.0</a>:</p>
          
            <p class="rel-note">This is a new major version of CodeMirror. There
            are a few <strong>incompatible</strong> changes in the API. Upgrade
            with care, and read the <a href="upgrade_v4.html">upgrading
            guide</a>.</p>
          
            <ul class="rel-note">
              <li>Multiple selections (ctrl-click, alt-drag, <a href="manual.html#setSelections">API</a>).</li>
              <li>Sublime Text <a href="../demo/sublime.html">bindings</a>.</li>
              <li><a href="manual.html#modloader">Module loader shims</a> wrapped around all modules.</li>
              <li>Selection <a href="manual.html#command_undoSelection">undo</a>/<a href="manual.html#command_redoSelection">redo</a>.</li>
              <li>Improved character measuring (faster, handles wrapped lines more robustly).</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.23.0...4.0.3">list of patches</a>.</li>
            </ul>
          
          </section>
          
          <section id=v3>
          
            <h2>Version 3.x</h2>
          
            <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-3.24.zip">Version 3.24</a>:</p>
          
            <p class="rel-note">Merges the improvements from 4.1 that could
            easily be applied to the 3.x code. Also improves the way the editor
            size is updated when line widgets change.</p>
          
            <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-3.23.zip">Version 3.23</a>:</p>
          
            <ul class="rel-note">
              <li>In the <a href="../mode/xml/index.html">XML mode</a>,
              add <code>brackets</code> style to angle brackets, fix
              case-sensitivity of tags for HTML.</li>
              <li>New mode: <a href="../mode/dylan/index.html">Dylan</a>.</li>
              <li>Many improvements to the <a href="../demo/vim.html">Vim bindings</a>.</li>
            </ul>
          
            <p class="rel">21-02-2014: <a href="http://codemirror.net/codemirror-3.22.zip">Version 3.22</a>:</p>
          
            <ul class="rel-note">
              <li>Adds the <a href="manual.html#findMarks"><code>findMarks</code></a> method.</li>
              <li>New addons: <a href="manual.html#addon_rulers">rulers</a>, markdown-fold, yaml-lint.</li>
              <li>New theme: <a href="../demo/theme.html?mdn-like">mdn-like</a>.</li>
              <li>New mode: <a href="../mode/solr/index.html">Solr</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.21.0...3.22.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">16-01-2014: <a href="http://codemirror.net/codemirror-3.21.zip">Version 3.21</a>:</p>
          
            <ul class="rel-note">
              <li>Auto-indenting a block will no longer add trailing whitespace to blank lines.</a>
              <li>Marking text has a new option <a href="manual.html#markText"><code>clearWhenEmpty</code></a> to control auto-removal.</li>
              <li>Several bugfixes in the handling of bidirectional text.</li>
              <li>The <a href="../mode/xml/index.html">XML</a> and <a href="../mode/css/index.html">CSS</a> modes were largely rewritten. <a href="../mode/css/less.html">LESS</a> support was added to the CSS mode.</li>
              <li>The OCaml mode was moved to an <a href="../mode/mllike/index.html">mllike</a> mode, F# support added.</li>
              <li>Make it possible to fetch multiple applicable helper values with <a href="manual.html#getHelpers"><code>getHelpers</code></a>, and to register helpers matched on predicates with <a href="manual.html#registerGlobalHelper"><code>registerGlobalHelper</code></a>.</li>
              <li>New theme <a href="../demo/theme.html?pastel-on-dark">pastel-on-dark</a>.</li>
              <li>Better ECMAScript 6 support in <a href="../mode/javascript/index.html">JavaScript</a> mode.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.20.0...3.21.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-11-2013: <a href="http://codemirror.net/codemirror-3.20.zip">Version 3.20</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/julia/index.html">Julia</a> and <a href="../mode/pegjs/index.html">PEG.js</a>.</li>
              <li>Support ECMAScript 6 in the <a href="../mode/javascript/index.html">JavaScript mode</a>.</li>
              <li>Improved indentation for the <a href="../mode/coffeescript/index.html">CoffeeScript mode</a>.</li>
              <li>Make non-printable-character representation <a href="manual.html#option_specialChars">configurable</a>.</li>
              <li>Add ‘notification’ functionality to <a href="manual.html#addon_dialog">dialog</a> addon.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.19.0...3.20.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-10-2013: <a href="http://codemirror.net/codemirror-3.19.zip">Version 3.19</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/eiffel/index.html">Eiffel</a>, <a href="../mode/gherkin/index.html">Gherkin</a>, <a href="../mode/sql/?mime=text/x-mssql">MSSQL dialect</a>.</li>
              <li>New addons: <a href="manual.html#addon_hardwrap">hardwrap</a>, <a href="manual.html#addon_sql-hint">sql-hint</a>.</li>
              <li>New theme: <a href="../demo/theme.html?mbo">MBO</a>.</li>
              <li>Add <a href="manual.html#token_style_line">support</a> for line-level styling from mode tokenizers.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.18.0...3.19.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">23-09-2013: <a href="http://codemirror.net/codemirror-3.18.zip">Version 3.18</a>:</p>
          
            <p class="rel-note">Emergency release to fix a problem in 3.17
            where <code>.setOption("lineNumbers", false)</code> would raise an
            error.</p>
          
            <p class="rel">23-09-2013: <a href="http://codemirror.net/codemirror-3.17.zip">Version 3.17</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/fortran/index.html">Fortran</a>, <a href="../mode/octave/index.html">Octave</a> (Matlab), <a href="../mode/toml/index.html">TOML</a>, and <a href="../mode/dtd/index.html">DTD</a>.</li>
              <li>New addons: <a href="../addon/lint/css-lint.js"><code>css-lint</code></a>, <a href="manual.html#addon_css-hint"><code>css-hint</code></a>.</li>
              <li>Improve resilience to CSS 'frameworks' that globally mess up <code>box-sizing</code>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.16.0...3.17.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-08-2013: <a href="http://codemirror.net/codemirror-3.16.zip">Version 3.16</a>:</p>
          
            <ul class="rel-note">
              <li>The whole codebase is now under a single <a href="../LICENSE">license</a> file.</li>
              <li>The project page was overhauled and redesigned.</li>
              <li>New themes: <a href="../demo/theme.html?paraiso-dark">Paraiso</a> (<a href="../demo/theme.html?paraiso-light">light</a>), <a href="../demo/theme.html?the-matrix">The Matrix</a>.</li>
              <li>Improved interaction between themes and <a href="manual.html#addon_active-line">active-line</a>/<a href="manual.html#addon_matchbrackets">matchbrackets</a> addons.</li>
              <li>New <a href="manual.html#addon_foldcode">folding</a> function <code>CodeMirror.fold.comment</code>.</li>
              <li>Added <a href="manual.html#addon_fullscreen">fullscreen</a> addon.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.15.0...3.16.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">29-07-2013: <a href="http://codemirror.net/codemirror-3.15.zip">Version 3.15</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/jade/index.html">Jade</a>, <a href="../mode/nginx/index.html">Nginx</a>.</li>
              <li>New addons: <a href="../demo/tern.html">Tern</a>, <a href="manual.html#addon_matchtags">matchtags</a>, and <a href="manual.html#addon_foldgutter">foldgutter</a>.</li>
              <li>Introduced <a href="manual.html#getHelper"><em>helper</em></a> concept (<a href="https://groups.google.com/forum/#!msg/codemirror/cOc0xvUUEUU/nLrX1-qnidgJ">context</a>).</li>
              <li>New method: <a href="manual.html#getModeAt"><code>getModeAt</code></a>.</li>
              <li>New themes: base16 <a href="../demo/theme.html?base16-dark">dark</a>/<a href="../demo/theme.html?base16-light">light</a>, 3024 <a href="../demo/theme.html?3024-night">dark</a>/<a href="../demo/theme.html?3024-day">light</a>, <a href="../demo/theme.html?tomorrow-night-eighties">tomorrow-night</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.14.0...3.15.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-06-2013: <a href="http://codemirror.net/codemirror-3.14.zip">Version 3.14</a>:</p>
          
            <ul class="rel-note">
              <li>New
              addons: <a href="manual.html#addon_trailingspace">trailing
              space highlight</a>, <a href="manual.html#addon_xml-hint">XML
              completion</a> (rewritten),
              and <a href="manual.html#addon_merge">diff merging</a>.</li>
              <li><a href="manual.html#markText"><code>markText</code></a>
              and <a href="manual.html#addLineWidget"><code>addLineWidget</code></a>
              now take a <code>handleMouseEvents</code> option.</li>
              <li>New methods: <a href="manual.html#lineAtHeight"><code>lineAtHeight</code></a>,
              <a href="manual.html#getTokenTypeAt"><code>getTokenTypeAt</code></a>.</li>
              <li>More precise cleanness-tracking
              using <a href="manual.html#changeGeneration"><code>changeGeneration</code></a>
              and <a href="manual.html#isClean"><code>isClean</code></a>.</li>
              <li>Many extensions to <a href="../demo/emacs.html">Emacs</a> mode
              (prefixes, more navigation units, and more).</li>
              <li>New
              events <a href="manual.html#event_keyHandled"><code>"keyHandled"</code></a>
              and <a href="manual.html#event_inputRead"><code>"inputRead"</code></a>.</li>
              <li>Various improvements to <a href="../mode/ruby/index.html">Ruby</a>,
              <a href="../mode/smarty/index.html">Smarty</a>, <a href="../mode/sql/index.html">SQL</a>,
              and <a href="../demo/vim.html">Vim</a> modes.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.13.0...3.14.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-05-2013: <a href="http://codemirror.net/codemirror-3.13.zip">Version 3.13</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/cobol/index.html">COBOL</a> and <a href="../mode/haml/index.html">HAML</a>.</li>
              <li>New options: <a href="manual.html#option_cursorScrollMargin"><code>cursorScrollMargin</code></a> and <a href="manual.html#option_coverGutterNextToScrollbar"><code>coverGutterNextToScrollbar</code></a>.</li>
              <li>New addon: <a href="manual.html#addon_comment">commenting</a>.</li>
              <li>More features added to the <a href="../demo/vim.html">Vim keymap</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.12...3.13.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-04-2013: <a href="http://codemirror.net/codemirror-3.12.zip">Version 3.12</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/gas/index.html">GNU assembler</a>.</li>
              <li>New
              options: <a href="manual.html#option_maxHighlightLength"><code>maxHighlightLength</code></a>
              and <a href="manual.html#option_historyEventDelay"><code>historyEventDelay</code></a>.</li>
              <li>Added <a href="manual.html#mark_addToHistory"><code>addToHistory</code></a>
              option for <code>markText</code>.</li>
              <li>Various fixes to JavaScript tokenization and indentation corner cases.</li>
              <li>Further improvements to the vim mode.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.11...v3.12">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-03-2013: <a href="http://codemirror.net/codemirror-3.11.zip">Version 3.11</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Removed code:</strong> <code>collapserange</code>,
              <code>formatting</code>, and <code>simple-hint</code>
              addons. <code>plsql</code> and <code>mysql</code> modes
              (use <a href="../mode/sql/index.html"><code>sql</code></a> mode).</li>
              <li><strong>Moved code:</strong> the range-finding functions for folding now have <a href="../addon/fold/">their own files</a>.</li>
              <li><strong>Changed interface:</strong>
              the <a href="manual.html#addon_continuecomment"><code>continuecomment</code></a>
              addon now exposes an option, rather than a command.</li>
              <li>New
              modes: <a href="../mode/css/scss.html">SCSS</a>, <a href="../mode/tcl/index.html">Tcl</a>, <a href="../mode/livescript/index.html">LiveScript</a>,
              and <a href="../mode/mirc/index.html">mIRC</a>.</li>
              <li>New addons: <a href="../demo/placeholder.html"><code>placeholder</code></a>, <a href="../demo/html5complete.html">HTML completion</a>.</li>
              <li>New
              methods: <a href="manual.html#hasFocus"><code>hasFocus</code></a>, <a href="manual.html#defaultCharWidth"><code>defaultCharWidth</code></a>.</li>
              <li>New events: <a href="manual.html#event_beforeCursorEnter"><code>beforeCursorEnter</code></a>, <a href="manual.html#event_renderLine"><code>renderLine</code></a>.</li>
              <li>Many improvements to the <a href="manual.html#addon_show-hint"><code>show-hint</code></a> completion
              dialog addon.</li>
              <li>Tweak behavior of by-word cursor motion.</li>
              <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.1...v3.11">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-02-2013: <a href="http://codemirror.net/codemirror-3.1.zip">Version 3.1</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Incompatible:</strong> key handlers may
              now <em>return</em>, rather
              than <em>throw</em> <code>CodeMirror.Pass</code> to signal they
              didn't handle the key.</li>
              <li>Make documents a <a href="manual.html#api_doc">first-class
              construct</a>, support split views and subviews.</li>
              <li>Add a <a href="manual.html#addon_show-hint">new module</a>
              for showing completion hints.
              Deprecate <code>simple-hint.js</code>.</li>
              <li>Extend <a href="../mode/htmlmixed/index.html">htmlmixed mode</a>
              to allow custom handling of script types.</li>
              <li>Support an <code>insertLeft</code> option
              to <a href="manual.html#setBookmark"><code>setBookmark</code></a>.</li>
              <li>Add an <a href="manual.html#eachLine"><code>eachLine</code></a>
              method to iterate over a document.</li>
              <li>New addon modules: <a href="../demo/markselection.html">selection
              marking</a>, <a href="../demo/lint.html">linting</a>,
              and <a href="../demo/closebrackets.html">automatic bracket
              closing</a>.</li>
              <li>Add <a href="manual.html#event_beforeChange"><code>"beforeChange"</code></a>
              and <a href="manual.html#event_beforeSelectionChange"><code>"beforeSelectionChange"</code></a>
              events.</li>
              <li>Add <a href="manual.html#event_hide"><code>"hide"</code></a>
              and <a href="manual.html#event_unhide"><code>"unhide"</code></a>
              events to marked ranges.</li>
              <li>Fix <a href="manual.html#coordsChar"><code>coordsChar</code></a>'s
              interpretation of its argument to match the documentation.</li>
              <li>New modes: <a href="../mode/turtle/index.html">Turtle</a>
              and <a href="../mode/q/index.html">Q</a>.</li>
              <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.01...v3.1">list of patches</a>.</li>
            </ul>
            
          
            <p class="rel">25-01-2013: <a href="http://codemirror.net/codemirror-3.02.zip">Version 3.02</a>:</p>
          
            <p class="rel-note">Single-bugfix release. Fixes a problem that
            prevents CodeMirror instances from being garbage-collected after
            they become unused.</p>
          
            <p class="rel">21-01-2013: <a href="http://codemirror.net/codemirror-3.01.zip">Version 3.01</a>:</p>
          
            <ul class="rel-note">
              <li>Move all add-ons into an organized directory structure
              under <a href="../addon/"><code>/addon</code></a>. <strong>You might have to adjust your
              paths.</strong></li>
              <li>New
              modes: <a href="../mode/d/index.html">D</a>, <a href="../mode/sass/index.html">Sass</a>, <a href="../mode/apl/index.html">APL</a>, <a href="../mode/sql/index.html">SQL</a>
              (configurable), and <a href="../mode/asterisk/index.html">Asterisk</a>.</li>
              <li>Several bugfixes in right-to-left text support.</li>
              <li>Add <a href="manual.html#option_rtlMoveVisually"><code>rtlMoveVisually</code></a> option.</li>
              <li>Improvements to vim keymap.</li>
              <li>Add built-in (lightweight) <a href="manual.html#addOverlay">overlay mode</a> support.</li>
              <li>Support <code>showIfHidden</code> option for <a href="manual.html#addLineWidget">line widgets</a>.</li>
              <li>Add simple <a href="manual.html#addon_python-hint">Python hinter</a>.</li>
              <li>Bring back the <a href="manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0...v3.01">list of patches</a>.</li>
            </ul>
          
            <p class="rel">10-12-2012: <a href="http://codemirror.net/codemirror-3.0.zip">Version 3.0</a>:</p>
          
            <p class="rel-note"><strong>New major version</strong>. Only
            partially backwards-compatible. See
            the <a href="upgrade_v3.html">upgrading guide</a> for more
            information. Changes since release candidate 2:</p>
          
            <ul class="rel-note">
              <li>Rewritten VIM mode.</li>
              <li>Fix a few minor scrolling and sizing issues.</li>
              <li>Work around Safari segfault when dragging.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc2...v3.0">list of patches</a>.</li>
            </ul>
            
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc2.zip">Version 3.0, release candidate 2</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/http/index.html">HTTP</a>.</li>
              <li>Improved handling of selection anchor position.</li>
              <li>Improve IE performance on longer lines.</li>
              <li>Reduce gutter glitches during horiz. scrolling.</li>
              <li>Add <a href="manual.html#addKeyMap"><code>addKeyMap</code></a> and <a href="manual.html#removeKeyMap"><code>removeKeyMap</code></a> methods.</li>
              <li>Rewrite <code>formatting</code> and <code>closetag</code> add-ons.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc1...v3.0rc2">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>
          
            <ul class="rel-note">
              <li>New theme: <a href="../demo/theme.html?solarized%20light">Solarized</a>.</li>
              <li>Introduce <a href="manual.html#addLineClass"><code>addLineClass</code></a>
              and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
              drop <code>setLineClass</code>.</li>
              <li>Add a <em>lot</em> of
              new <a href="manual.html#markText">options for marked text</a>
              (read-only, atomic, collapsed, widget replacement).</li>
              <li>Remove the old code folding interface in favour of these new ranges.</li>
              <li>Add <a href="manual.html#isClean"><code>isClean</code></a>/<a href="manual.html#markClean"><code>markClean</code></a> methods.</li>
              <li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>
              <li>Improve scrolling performance smoothness.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-3.0beta2.zip">Version 3.0, beta 2</a>:</p>
          
            <ul class="rel-note">
              <li>Fix page-based coordinate computation.</li>
              <li>Fix firing of <a href="manual.html#event_gutterClick"><code>gutterClick</code></a> event.</li>
              <li>Add <a href="manual.html#option_cursorHeight"><code>cursorHeight</code></a> option.</li>
              <li>Fix bi-directional text regression.</li>
              <li>Add <a href="manual.html#option_viewportMargin"><code>viewportMargin</code></a> option.</li>
              <li>Directly handle mousewheel events (again, hopefully better).</li>
              <li>Make vertical cursor movement more robust (through widgets, big line gaps).</li>
              <li>Add <a href="manual.html#option_flattenSpans"><code>flattenSpans</code></a> option.</li>
              <li>Many optimizations. Poor responsiveness should be fixed.</li>
              <li>Initialization in hidden state works again.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta1...v3.0beta2">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-3.0beta1.zip">Version 3.0, beta 1</a>:</p>
          
            <ul class="rel-note">
              <li>Bi-directional text support.</li>
              <li>More powerful gutter model.</li>
              <li>Support for arbitrary text/widget height.</li>
              <li>In-line widgets.</li>
              <li>Generalized event handling.</li>
            </ul>
          
          </section>
          
          <section id=v2>
          
            <h2>Version 2.x</h2>
          
            <p class="rel">21-01-2013: <a href="http://codemirror.net/codemirror-2.38.zip">Version 2.38</a>:</p>
          
            <p class="rel-note">Integrate some bugfixes, enhancements to the vim keymap, and new
            modes
            (<a href="../mode/d/index.html">D</a>, <a href="../mode/sass/index.html">Sass</a>, <a href="../mode/apl/index.html">APL</a>)
            from the v3 branch.</p>
          
            <p class="rel">20-12-2012: <a href="http://codemirror.net/codemirror-2.37.zip">Version 2.37</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/sql/index.html">SQL</a> (will replace <a href="../mode/plsql/index.html">plsql</a> and <a href="../mode/mysql/index.html">mysql</a> modes).</li>
              <li>Further work on the new VIM mode.</li>
              <li>Fix Cmd/Ctrl keys on recent Operas on OS X.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.36...v2.37">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-2.36.zip">Version 2.36</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/z80/index.html">Z80 assembly</a>.</li>
              <li>New theme: <a href="../demo/theme.html?twilight">Twilight</a>.</li>
              <li>Add command-line compression helper.</li>
              <li>Make <a href="manual.html#scrollIntoView"><code>scrollIntoView</code></a> public.</li>
              <li>Add <a href="manual.html#defaultTextHeight"><code>defaultTextHeight</code></a> method.</li>
              <li>Various extensions to the vim keymap.</li>
              <li>Make <a href="../mode/php/index.html">PHP mode</a> build on <a href="../mode/htmlmixed/index.html">mixed HTML mode</a>.</li>
              <li>Add <a href="manual.html#addon_continuecomment">comment-continuing</a> add-on.</li>
              <li>Full <a href="../https://github.com/codemirror/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>
          
            <ul class="rel-note">
              <li>New (sub) mode: <a href="../mode/javascript/typescript.html">TypeScript</a>.</li>
              <li>Don't overwrite (insert key) when pasting.</li>
              <li>Fix several bugs in <a href="manual.html#markText"><code>markText</code></a>/undo interaction.</li>
              <li>Better indentation of JavaScript code without semicolons.</li>
              <li>Add <a href="manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-2.34.zip">Version 2.34</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/commonlisp/index.html">Common Lisp</a>.</li>
              <li>Fix right-click select-all on most browsers.</li>
              <li>Change the way highlighting happens:<br>&nbsp; Saves memory and CPU cycles.<br>&nbsp; <code>compareStates</code> is no longer needed.<br>&nbsp; <code>onHighlightComplete</code> no longer works.</li>
              <li>Integrate mode (Markdown, XQuery, CSS, sTex) tests in central testsuite.</li>
              <li>Add a <a href="manual.html#version"><code>CodeMirror.version</code></a> property.</li>
              <li>More robust handling of nested modes in <a href="../demo/formatting.html">formatting</a> and <a href="../demo/closetag.html">closetag</a> plug-ins.</li>
              <li>Un/redo now preserves <a href="manual.html#markText">marked text</a> and bookmarks.</li>
              <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.33...v2.34">Full list</a> of patches.</li>
            </ul>
          
            <p class="rel">23-08-2012: <a href="http://codemirror.net/codemirror-2.33.zip">Version 2.33</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/sieve/index.html">Sieve</a>.</li>
              <li>New <a href="manual.html#getViewport"><code>getViewPort</code></a> and <a href="manual.html#option_onViewportChange"><code>onViewportChange</code></a> API.</li>
              <li><a href="manual.html#option_cursorBlinkRate">Configurable</a> cursor blink rate.</li>
              <li>Make binding a key to <code>false</code> disabling handling (again).</li>
              <li>Show non-printing characters as red dots.</li>
              <li>More tweaks to the scrolling model.</li>
              <li>Expanded testsuite. Basic linter added.</li>
              <li>Remove most uses of <code>innerHTML</code>. Remove <code>CodeMirror.htmlEscape</code>.</li>
              <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.32...v2.33">Full list</a> of patches.</li>
            </ul>
          
            <p class="rel">23-07-2012: <a href="http://codemirror.net/codemirror-2.32.zip">Version 2.32</a>:</p>
          
            <p class="rel-note">Emergency fix for a bug where an editor with
            line wrapping on IE will break when there is <em>no</em>
            scrollbar.</p>
          
            <p class="rel">20-07-2012: <a href="http://codemirror.net/codemirror-2.31.zip">Version 2.31</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/ocaml/index.html">OCaml</a>, <a href="../mode/haxe/index.html">Haxe</a>, and <a href="../mode/vb/index.html">VB.NET</a>.</li>
              <li>Several fixes to the new scrolling model.</li>
              <li>Add a <a href="manual.html#setSize"><code>setSize</code></a> method for programmatic resizing.</li>
              <li>Add <a href="manual.html#getHistory"><code>getHistory</code></a> and <a href="manual.html#setHistory"><code>setHistory</code></a> methods.</li>
              <li>Allow custom line separator string in <a href="manual.html#getValue"><code>getValue</code></a> and <a href="manual.html#getRange"><code>getRange</code></a>.</li>
              <li>Support double- and triple-click drag, double-clicking whitespace.</li>
              <li>And more... <a href="https://github.com/codemirror/CodeMirror/compare/v2.3...v2.31">(all patches)</a></li>
            </ul>
          
            <p class="rel">22-06-2012: <a href="http://codemirror.net/codemirror-2.3.zip">Version 2.3</a>:</p>
          
            <ul class="rel-note">
              <li><strong>New scrollbar implementation</strong>. Should flicker less. Changes DOM structure of the editor.</li>
              <li>New theme: <a href="../demo/theme.html?vibrant-ink">vibrant-ink</a>.</li>
              <li>Many extensions to the VIM keymap (including text objects).</li>
              <li>Add <a href="../demo/multiplex.html">mode-multiplexing</a> utility script.</li>
              <li>Fix bug where right-click paste works in read-only mode.</li>
              <li>Add a <a href="manual.html#getScrollInfo"><code>getScrollInfo</code></a> method.</li>
              <li>Lots of other <a href="https://github.com/codemirror/CodeMirror/compare/v2.25...v2.3">fixes</a>.</li>
            </ul>
          
            <p class="rel">23-05-2012: <a href="http://codemirror.net/codemirror-2.25.zip">Version 2.25</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/erlang/index.html">Erlang</a>.</li>
              <li><strong>Remove xmlpure mode</strong> (use <a href="../mode/xml/index.html">xml.js</a>).</li>
              <li>Fix line-wrapping in Opera.</li>
              <li>Fix X Windows middle-click paste in Chrome.</li>
              <li>Fix bug that broke pasting of huge documents.</li>
              <li>Fix backspace and tab key repeat in Opera.</li>
            </ul>
          
            <p class="rel">23-04-2012: <a href="http://codemirror.net/codemirror-2.24.zip">Version 2.24</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Drop support for Internet Explorer 6</strong>.</li>
              <li>New
              modes: <a href="../mode/shell/index.html">Shell</a>, <a href="../mode/tiki/index.html">Tiki
              wiki</a>, <a href="../mode/pig/index.html">Pig Latin</a>.</li>
              <li>New themes: <a href="../demo/theme.html?ambiance">Ambiance</a>, <a href="../demo/theme.html?blackboard">Blackboard</a>.</li>
              <li>More control over drag/drop
              with <a href="manual.html#option_dragDrop"><code>dragDrop</code></a>
              and <a href="manual.html#option_onDragEvent"><code>onDragEvent</code></a>
              options.</li>
              <li>Make HTML mode a bit less pedantic.</li>
              <li>Add <a href="manual.html#compoundChange"><code>compoundChange</code></a> API method.</li>
              <li>Several fixes in undo history and line hiding.</li>
              <li>Remove (broken) support for <code>catchall</code> in key maps,
              add <code>nofallthrough</code> boolean field instead.</li>
            </ul>
          
            <p class="rel">26-03-2012: <a href="http://codemirror.net/codemirror-2.23.zip">Version 2.23</a>:</p>
          
            <ul class="rel-note">
              <li>Change <strong>default binding for tab</strong> <a href="javascript:void(document.getElementById('tabbinding').style.display='')">[more]</a>
                <div style="display: none" id=tabbinding>
                  Starting in 2.23, these bindings are default:
                  <ul><li>Tab: Insert tab character</li>
                    <li>Shift-tab: Reset line indentation to default</li>
                    <li>Ctrl/Cmd-[: Reduce line indentation (old tab behaviour)</li>
                    <li>Ctrl/Cmd-]: Increase line indentation (old shift-tab behaviour)</li>
                  </ul>
                </div>
              </li>
              <li>New modes: <a href="../mode/xquery/index.html">XQuery</a> and <a href="../mode/vbscript/index.html">VBScript</a>.</li>
              <li>Two new themes: <a href="../mode/less/index.html">lesser-dark</a> and <a href="../mode/xquery/index.html">xq-dark</a>.</li>
              <li>Differentiate between background and text styles in <a href="manual.html#setLineClass"><code>setLineClass</code></a>.</li>
              <li>Fix drag-and-drop in IE9+.</li>
              <li>Extend <a href="manual.html#charCoords"><code>charCoords</code></a>
              and <a href="manual.html#cursorCoords"><code>cursorCoords</code></a> with a <code>mode</code> argument.</li>
              <li>Add <a href="manual.html#option_autofocus"><code>autofocus</code></a> option.</li>
              <li>Add <a href="manual.html#findMarksAt"><code>findMarksAt</code></a> method.</li>
            </ul>
          
            <p class="rel">27-02-2012: <a href="http://codemirror.net/codemirror-2.22.zip">Version 2.22</a>:</p>
          
            <ul class="rel-note">
              <li>Allow <a href="manual.html#keymaps">key handlers</a> to pass up events, allow binding characters.</li>
              <li>Add <a href="manual.html#option_autoClearEmptyLines"><code>autoClearEmptyLines</code></a> option.</li>
              <li>Properly use tab stops when rendering tabs.</li>
              <li>Make PHP mode more robust.</li>
              <li>Support indentation blocks in <a href="manual.html#addon_foldcode">code folder</a>.</li>
              <li>Add a script for <a href="manual.html#addon_match-highlighter">highlighting instances of the selection</a>.</li>
              <li>New <a href="../mode/properties/index.html">.properties</a> mode.</li>
              <li>Fix many bugs.</li>
            </ul>
          
            <p class="rel">27-01-2012: <a href="http://codemirror.net/codemirror-2.21.zip">Version 2.21</a>:</p>
          
            <ul class="rel-note">
              <li>Added <a href="../mode/less/index.html">LESS</a>, <a href="../mode/mysql/index.html">MySQL</a>,
              <a href="../mode/go/index.html">Go</a>, and <a href="../mode/verilog/index.html">Verilog</a> modes.</li>
              <li>Add <a href="manual.html#option_smartIndent"><code>smartIndent</code></a>
              option.</li>
              <li>Support a cursor in <a href="manual.html#option_readOnly"><code>readOnly</code></a>-mode.</li>
              <li>Support assigning multiple styles to a token.</li>
              <li>Use a new approach to drawing the selection.</li>
              <li>Add <a href="manual.html#scrollTo"><code>scrollTo</code></a> method.</li>
              <li>Allow undo/redo events to span non-adjacent lines.</li>
              <li>Lots and lots of bugfixes.</li>
            </ul>
          
            <p class="rel">20-12-2011: <a href="http://codemirror.net/codemirror-2.2.zip">Version 2.2</a>:</p>
          
            <ul class="rel-note">
              <li>Slightly incompatible API changes. Read <a href="upgrade_v2.2.html">this</a>.</li>
              <li>New approach
              to <a href="manual.html#option_extraKeys">binding</a> keys,
              support for <a href="manual.html#option_keyMap">custom
              bindings</a>.</li>
              <li>Support for overwrite (insert).</li>
              <li><a href="manual.html#option_tabSize">Custom-width</a>
              and <a href="../demo/visibletabs.html">stylable</a> tabs.</li>
              <li>Moved more code into <a href="manual.html#addons">add-on scripts</a>.</li>
              <li>Support for sane vertical cursor movement in wrapped lines.</li>
              <li>More reliable handling of
              editing <a href="manual.html#markText">marked text</a>.</li>
              <li>Add minimal <a href="../demo/emacs.html">emacs</a>
              and <a href="../demo/vim.html">vim</a> bindings.</li>
              <li>Rename <code>coordsFromIndex</code>
              to <a href="manual.html#posFromIndex"><code>posFromIndex</code></a>,
              add <a href="manual.html#indexFromPos"><code>indexFromPos</code></a>
              method.</li>
            </ul>
          
            <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.18.zip">Version 2.18</a>:</p>
            <p class="rel-note">Fixes <code>TextMarker.clear</code>, which is broken in 2.17.</p>
          
            <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.17.zip">Version 2.17</a>:</p>
            <ul class="rel-note">
              <li>Add support for <a href="manual.html#option_lineWrapping">line
              wrapping</a> and <a href="manual.html#hideLine">code
              folding</a>.</li>
              <li>Add <a href="../mode/gfm/index.html">Github-style Markdown</a> mode.</li>
              <li>Add <a href="../theme/monokai.css">Monokai</a>
              and <a href="../theme/rubyblue.css">Rubyblue</a> themes.</li>
              <li>Add <a href="manual.html#setBookmark"><code>setBookmark</code></a> method.</li>
              <li>Move some of the demo code into reusable components
              under <a href="../addon/"><code>lib/util</code></a>.</li>
              <li>Make screen-coord-finding code faster and more reliable.</li>
              <li>Fix drag-and-drop in Firefox.</li>
              <li>Improve support for IME.</li>
              <li>Speed up content rendering.</li>
              <li>Fix browser's built-in search in Webkit.</li>
              <li>Make double- and triple-click work in IE.</li>
              <li>Various fixes to modes.</li>
            </ul>
          
            <p class="rel">27-10-2011: <a href="http://codemirror.net/codemirror-2.16.zip">Version 2.16</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/perl/index.html">Perl</a>, <a href="../mode/rust/index.html">Rust</a>, <a href="../mode/tiddlywiki/index.html">TiddlyWiki</a>, and <a href="../mode/groovy/index.html">Groovy</a> modes.</li>
              <li>Dragging text inside the editor now moves, rather than copies.</li>
              <li>Add a <a href="manual.html#coordsFromIndex"><code>coordsFromIndex</code></a> method.</li>
              <li><strong>API change</strong>: <code>setValue</code> now no longer clears history. Use <a href="manual.html#clearHistory"><code>clearHistory</code></a> for that.</li>
              <li><strong>API change</strong>: <a href="manual.html#markText"><code>markText</code></a> now
              returns an object with <code>clear</code> and <code>find</code>
              methods. Marked text is now more robust when edited.</li>
              <li>Fix editing code with tabs in Internet Explorer.</li>
            </ul>
          
            <p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.15.zip">Version 2.15</a>:</p>
            <p class="rel-note">Fix bug that snuck into 2.14: Clicking the
            character that currently has the cursor didn't re-focus the
            editor.</p>
          
            <p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.14.zip">Version 2.14</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/clojure/index.html">Clojure</a>, <a href="../mode/pascal/index.html">Pascal</a>, <a href="../mode/ntriples/index.html">NTriples</a>, <a href="../mode/jinja2/index.html">Jinja2</a>, and <a href="../mode/markdown/index.html">Markdown</a> modes.</li>
              <li>Add <a href="../theme/cobalt.css">Cobalt</a> and <a href="../theme/eclipse.css">Eclipse</a> themes.</li>
              <li>Add a <a href="manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>
              <li>Fix bug with <code>setValue</code> breaking cursor movement.</li>
              <li>Make gutter updates much more efficient.</li>
              <li>Allow dragging of text out of the editor (on modern browsers).</li>
            </ul>
          
          
            <p class="rel">23-08-2011: <a href="http://codemirror.net/codemirror-2.13.zip">Version 2.13</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/ruby/index.html">Ruby</a>, <a href="../mode/r/index.html">R</a>, <a href="../mode/coffeescript/index.html">CoffeeScript</a>, and <a href="../mode/velocity/index.html">Velocity</a> modes.</li>
              <li>Add <a href="manual.html#getGutterElement"><code>getGutterElement</code></a> to API.</li>
              <li>Several fixes to scrolling and positioning.</li>
              <li>Add <a href="manual.html#option_smartHome"><code>smartHome</code></a> option.</li>
              <li>Add an experimental <a href="../mode/xmlpure/index.html">pure XML</a> mode.</li>
            </ul>
          
            <p class="rel">25-07-2011: <a href="http://codemirror.net/codemirror-2.12.zip">Version 2.12</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/sparql/index.html">SPARQL</a> mode.</li>
              <li>Fix bug with cursor jumping around in an unfocused editor in IE.</li>
              <li>Allow key and mouse events to bubble out of the editor. Ignore widget clicks.</li>
              <li>Solve cursor flakiness after undo/redo.</li>
              <li>Fix block-reindent ignoring the last few lines.</li>
              <li>Fix parsing of multi-line attrs in XML mode.</li>
              <li>Use <code>innerHTML</code> for HTML-escaping.</li>
              <li>Some fixes to indentation in C-like mode.</li>
              <li>Shrink horiz scrollbars when long lines removed.</li>
              <li>Fix width feedback loop bug that caused the width of an inner DIV to shrink.</li>
            </ul>
          
            <p class="rel">04-07-2011: <a href="http://codemirror.net/codemirror-2.11.zip">Version 2.11</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/scheme/index.html">Scheme mode</a>.</li>
              <li>Add a <code>replace</code> method to search cursors, for cursor-preserving replacements.</li>
              <li>Make the <a href="../mode/clike/index.html">C-like mode</a> mode more customizable.</li>
              <li>Update XML mode to spot mismatched tags.</li>
              <li>Add <code>getStateAfter</code> API and <code>compareState</code> mode API methods for finer-grained mode magic.</li>
              <li>Add a <code>getScrollerElement</code> API method to manipulate the scrolling DIV.</li>
              <li>Fix drag-and-drop for Firefox.</li>
              <li>Add a C# configuration for the <a href="../mode/clike/index.html">C-like mode</a>.</li>
              <li>Add <a href="../demo/fullscreen.html">full-screen editing</a> and <a href="../demo/changemode.html">mode-changing</a> demos.</li>
            </ul>
          
            <p class="rel">07-06-2011: <a href="http://codemirror.net/codemirror-2.1.zip">Version 2.1</a>:</p>
            <p class="rel-note">Add
            a <a href="manual.html#option_theme">theme</a> system
            (<a href="../demo/theme.html">demo</a>). Note that this is not
            backwards-compatible—you'll have to update your styles and
            modes!</p>
          
            <p class="rel">07-06-2011: <a href="http://codemirror.net/codemirror-2.02.zip">Version 2.02</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/lua/index.html">Lua mode</a>.</li>
              <li>Fix reverse-searching for a regexp.</li>
              <li>Empty lines can no longer break highlighting.</li>
              <li>Rework scrolling model (the outer wrapper no longer does the scrolling).</li>
              <li>Solve horizontal jittering on long lines.</li>
              <li>Add <a href="../demo/runmode.html">runmode.js</a>.</li>
              <li>Immediately re-highlight text when typing.</li>
              <li>Fix problem with 'sticking' horizontal scrollbar.</li>
            </ul>
          
            <p class="rel">26-05-2011: <a href="http://codemirror.net/codemirror-2.01.zip">Version 2.01</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/smalltalk/index.html">Smalltalk mode</a>.</li>
              <li>Add a <a href="../mode/rst/index.html">reStructuredText mode</a>.</li>
              <li>Add a <a href="../mode/python/index.html">Python mode</a>.</li>
              <li>Add a <a href="../mode/plsql/index.html">PL/SQL mode</a>.</li>
              <li><code>coordsChar</code> now works</li>
              <li>Fix a problem where <code>onCursorActivity</code> interfered with <code>onChange</code>.</li>
              <li>Fix a number of scrolling and mouse-click-position glitches.</li>
              <li>Pass information about the changed lines to <code>onChange</code>.</li>
              <li>Support cmd-up/down on OS X.</li>
              <li>Add triple-click line selection.</li>
              <li>Don't handle shift when changing the selection through the API.</li>
              <li>Support <code>"nocursor"</code> mode for <code>readOnly</code> option.</li>
              <li>Add an <code>onHighlightComplete</code> option.</li>
              <li>Fix the context menu for Firefox.</li>
            </ul>
          
            <p class="rel">28-03-2011: <a href="http://codemirror.net/codemirror-2.0.zip">Version 2.0</a>:</p>
            <p class="rel-note">CodeMirror 2 is a complete rewrite that's
            faster, smaller, simpler to use, and less dependent on browser
            quirks. See <a href="internals.html">this</a>
            and <a href="http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580">this</a>
            for more information.</p>
          
            <p class="rel">22-02-2011: <a href="https://github.com/codemirror/codemirror/tree/beta2">Version 2.0 beta 2</a>:</p>
            <p class="rel-note">Somewhat more mature API, lots of bugs shaken out.</p>
          
            <p class="rel">17-02-2011: <a href="http://codemirror.net/codemirror-0.94.zip">Version 0.94</a>:</p>
            <ul class="rel-note">
              <li><code>tabMode: "spaces"</code> was modified slightly (now indents when something is selected).</li>
              <li>Fixes a bug that would cause the selection code to break on some IE versions.</li>
              <li>Disabling spell-check on WebKit browsers now works.</li>
            </ul>
          
            <p class="rel">08-02-2011: <a href="http://codemirror.net/">Version 2.0 beta 1</a>:</p>
            <p class="rel-note">CodeMirror 2 is a complete rewrite of
            CodeMirror, no longer depending on an editable frame.</p>
          
            <p class="rel">19-01-2011: <a href="http://codemirror.net/codemirror-0.93.zip">Version 0.93</a>:</p>
            <ul class="rel-note">
              <li>Added a <a href="contrib/regex/index.html">Regular Expression</a> parser.</li>
              <li>Fixes to the PHP parser.</li>
              <li>Support for regular expression in search/replace.</li>
              <li>Add <code>save</code> method to instances created with <code>fromTextArea</code>.</li>
              <li>Add support for MS T-SQL in the SQL parser.</li>
              <li>Support use of CSS classes for highlighting brackets.</li>
              <li>Fix yet another hang with line-numbering in hidden editors.</li>
            </ul>
          </section>
          
          <section id=v1>
          
            <h2>Version 0.x</h2>
          
            <p class="rel">28-03-2011: <a href="http://codemirror.net/codemirror-1.0.zip">Version 1.0</a>:</p>
            <ul class="rel-note">
              <li>Fix error when debug history overflows.</li>
              <li>Refine handling of C# verbatim strings.</li>
              <li>Fix some issues with JavaScript indentation.</li>
            </ul>
          
            <p class="rel">17-12-2010: <a href="http://codemirror.net/codemirror-0.92.zip">Version 0.92</a>:</p>
            <ul class="rel-note">
              <li>Make CodeMirror work in XHTML documents.</li>
              <li>Fix bug in handling of backslashes in Python strings.</li>
              <li>The <code>styleNumbers</code> option is now officially
              supported and documented.</li>
              <li><code>onLineNumberClick</code> option added.</li>
              <li>More consistent names <code>onLoad</code> and
              <code>onCursorActivity</code> callbacks. Old names still work, but
              are deprecated.</li>
              <li>Add a <a href="contrib/freemarker/index.html">Freemarker</a> mode.</li>
            </ul>
          
            <p class="rel">11-11-2010: <a
            href="http://codemirror.net/codemirror-0.91.zip">Version 0.91</a>:</p>
            <ul class="rel-note">
              <li>Adds support for <a href="contrib/java">Java</a>.</li>
              <li>Small additions to the <a href="contrib/php">PHP</a> and <a href="contrib/sql">SQL</a> parsers.</li>
              <li>Work around various <a href="https://bugs.webkit.org/show_bug.cgi?id=47806">Webkit</a> <a href="https://bugs.webkit.org/show_bug.cgi?id=23474">issues</a>.</li>
              <li>Fix <code>toTextArea</code> to update the code in the textarea.</li>
              <li>Add a <code>noScriptCaching</code> option (hack to ease development).</li>
              <li>Make sub-modes of <a href="mixedtest.html">HTML mixed</a> mode configurable.</li>
            </ul>
          
            <p class="rel">02-10-2010: <a
            href="http://codemirror.net/codemirror-0.9.zip">Version 0.9</a>:</p>
            <ul class="rel-note">
              <li>Add support for searching backwards.</li>
              <li>There are now parsers for <a href="contrib/scheme/index.html">Scheme</a>, <a href="contrib/xquery/index.html">XQuery</a>, and <a href="contrib/ometa/index.html">OmetaJS</a>.</li>
              <li>Makes <code>height: "dynamic"</code> more robust.</li>
              <li>Fixes bug where paste did not work on OS X.</li>
              <li>Add a <code>enterMode</code> and <code>electricChars</code> options to make indentation even more customizable.</li>
              <li>Add <code>firstLineNumber</code> option.</li>
              <li>Fix bad handling of <code>@media</code> rules by the CSS parser.</li>
              <li>Take a new, more robust approach to working around the invisible-last-line bug in WebKit.</li>
            </ul>
          
            <p class="rel">22-07-2010: <a
            href="http://codemirror.net/codemirror-0.8.zip">Version 0.8</a>:</p>
            <ul class="rel-note">
              <li>Add a <code>cursorCoords</code> method to find the screen
              coordinates of the cursor.</li>
              <li>A number of fixes and support for more syntax in the PHP parser.</li>
              <li>Fix indentation problem with JSON-mode JS parser in Webkit.</li>
              <li>Add a <a href="compress.html">minification</a> UI.</li>
              <li>Support a <code>height: dynamic</code> mode, where the editor's
              height will adjust to the size of its content.</li>
              <li>Better support for IME input mode.</li>
              <li>Fix JavaScript parser getting confused when seeing a no-argument
              function call.</li>
              <li>Have CSS parser see the difference between selectors and other
              identifiers.</li>
              <li>Fix scrolling bug when pasting in a horizontally-scrolled
              editor.</li>
              <li>Support <code>toTextArea</code> method in instances created with
              <code>fromTextArea</code>.</li>
              <li>Work around new Opera cursor bug that causes the cursor to jump
              when pressing backspace at the end of a line.</li>
            </ul>
          
            <p class="rel">27-04-2010: <a
            href="http://codemirror.net/codemirror-0.67.zip">Version
            0.67</a>:</p>
            <p class="rel-note">More consistent page-up/page-down behaviour
            across browsers. Fix some issues with hidden editors looping forever
            when line-numbers were enabled. Make PHP parser parse
            <code>"\\"</code> correctly. Have <code>jumpToLine</code> work on
            line handles, and add <code>cursorLine</code> function to fetch the
            line handle where the cursor currently is. Add new
            <code>setStylesheet</code> function to switch style-sheets in a
            running editor.</p>
          
            <p class="rel">01-03-2010: <a
            href="http://codemirror.net/codemirror-0.66.zip">Version
            0.66</a>:</p>
            <p class="rel-note">Adds <code>removeLine</code> method to API.
            Introduces the <a href="contrib/plsql/index.html">PLSQL parser</a>.
            Marks XML errors by adding (rather than replacing) a CSS class, so
            that they can be disabled by modifying their style. Fixes several
            selection bugs, and a number of small glitches.</p>
          
            <p class="rel">12-11-2009: <a
            href="http://codemirror.net/codemirror-0.65.zip">Version
            0.65</a>:</p>
            <p class="rel-note">Add support for having both line-wrapping and
            line-numbers turned on, make paren-highlighting style customisable
            (<code>markParen</code> and <code>unmarkParen</code> config
            options), work around a selection bug that Opera
            <em>re</em>introduced in version 10.</p>
          
            <p class="rel">23-10-2009: <a
            href="http://codemirror.net/codemirror-0.64.zip">Version
            0.64</a>:</p>
            <p class="rel-note">Solves some issues introduced by the
            paste-handling changes from the previous release. Adds
            <code>setSpellcheck</code>, <code>setTextWrapping</code>,
            <code>setIndentUnit</code>, <code>setUndoDepth</code>,
            <code>setTabMode</code>, and <code>setLineNumbers</code> to
            customise a running editor. Introduces an <a
            href="contrib/sql/index.html">SQL</a> parser. Fixes a few small
            problems in the <a href="contrib/python/index.html">Python</a>
            parser. And, as usual, add workarounds for various newly discovered
            browser incompatibilities.</p>
          
            <p class="rel"><em>31-08-2009</em>: <a href="http://codemirror.net/codemirror-0.63.zip">Version 0.63</a>:</p>
            <p class="rel-note"> Overhaul of paste-handling (less fragile), fixes for several
            serious IE8 issues (cursor jumping, end-of-document bugs) and a number
            of small problems.</p>
          
            <p class="rel"><em>30-05-2009</em>: <a href="http://codemirror.net/codemirror-0.62.zip">Version 0.62</a>:</p>
            <p class="rel-note">Introduces <a href="contrib/python/index.html">Python</a>
            and <a href="contrib/lua/index.html">Lua</a> parsers. Add
            <code>setParser</code> (on-the-fly mode changing) and
            <code>clearHistory</code> methods. Make parsing passes time-based
            instead of lines-based (see the <code>passTime</code> option).</p>
          
          </section>
          </article>
          
        • reporting.html
          <!doctype html>
          
          <title>CodeMirror: Reporting Bugs</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Reporting bugs</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Reporting bugs effectively</h2>
          
          <div class="left">
          
          <p>So you found a problem in CodeMirror. By all means, report it! Bug
          reports from users are the main drive behind improvements to
          CodeMirror. But first, please read over these points:</p>
          
          <ol>
            <li>CodeMirror is maintained by volunteers. They don't owe you
            anything, so be polite. Reports with an indignant or belligerent
            tone tend to be moved to the bottom of the pile.</li>
          
            <li>Include information about <strong>the browser in which the
            problem occurred</strong>. Even if you tested several browsers, and
            the problem occurred in all of them, mention this fact in the bug
            report. Also include browser version numbers and the operating
            system that you're on.</li>
          
            <li>Mention which release of CodeMirror you're using. Preferably,
            try also with the current development snapshot, to ensure the
            problem has not already been fixed.</li>
          
            <li>Mention very precisely what went wrong. "X is broken" is not a
            good bug report. What did you expect to happen? What happened
            instead? Describe the exact steps a maintainer has to take to make
            the problem occur. We can not fix something that we can not
            observe.</li>
          
            <li>If the problem can not be reproduced in any of the demos
            included in the CodeMirror distribution, please provide an HTML
            document that demonstrates the problem. The best way to do this is
            to go to <a href="http://jsbin.com/ihunin/1/edit">jsbin.com</a>, enter
            it there, press save, and include the resulting link in your bug
            report.</li>
          </ol>
          
          </div>
          
          </article>
          
        • upgrade_v2.2.html
          <!doctype html>
          
          <title>CodeMirror: Version 2.2 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">2.2 upgrade guide</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Upgrading to v2.2</h2>
          
          <p>There are a few things in the 2.2 release that require some care
          when upgrading.</p>
          
          <h3>No more default.css</h3>
          
          <p>The default theme is now included
          in <a href="../lib/codemirror.css"><code>codemirror.css</code></a>, so
          you do not have to included it separately anymore. (It was tiny, so
          even if you're not using it, the extra data overhead is negligible.)
          
          <h3>Different key customization</h3>
          
          <p>CodeMirror has moved to a system
          where <a href="manual.html#option_keyMap">keymaps</a> are used to
          bind behavior to keys. This means <a href="../demo/emacs.html">custom
          bindings</a> are now possible.</p>
          
          <p>Three options that influenced key
          behavior, <code>tabMode</code>, <code>enterMode</code>,
          and <code>smartHome</code>, are no longer supported. Instead, you can
          provide custom bindings to influence the way these keys act. This is
          done through the
          new <a href="manual.html#option_extraKeys"><code>extraKeys</code></a>
          option, which can hold an object mapping key names to functionality. A
          simple example would be:</p>
          
          <pre>  extraKeys: {
              "Ctrl-S": function(instance) { saveText(instance.getValue()); },
              "Ctrl-/": "undo"
            }</pre>
          
          <p>Keys can be mapped either to functions, which will be given the
          editor instance as argument, or to strings, which are mapped through
          functions through the <code>CodeMirror.commands</code> table, which
          contains all the built-in editing commands, and can be inspected and
          extended by external code.</p>
          
          <p>By default, the <code>Home</code> key is bound to
          the <code>"goLineStartSmart"</code> command, which moves the cursor to
          the first non-whitespace character on the line. You can set do this to
          make it always go to the very start instead:</p>
          
          <pre>  extraKeys: {"Home": "goLineStart"}</pre>
          
          <p>Similarly, <code>Enter</code> is bound
          to <code>"newlineAndIndent"</code> by default. You can bind it to
          something else to get different behavior. To disable special handling
          completely and only get a newline character inserted, you can bind it
          to <code>false</code>:</p>
          
          <pre>  extraKeys: {"Enter": false}</pre>
          
          <p>The same works for <code>Tab</code>. If you don't want CodeMirror
          to handle it, bind it to <code>false</code>. The default behaviour is
          to indent the current line more (<code>"indentMore"</code> command),
          and indent it less when shift is held (<code>"indentLess"</code>).
          There are also <code>"indentAuto"</code> (smart indent)
          and <code>"insertTab"</code> commands provided for alternate
          behaviors. Or you can write your own handler function to do something
          different altogether.</p>
          
          <h3>Tabs</h3>
          
          <p>Handling of tabs changed completely. The display width of tabs can
          now be set with the <code>tabSize</code> option, and tabs can
          be <a href="../demo/visibletabs.html">styled</a> by setting CSS rules
          for the <code>cm-tab</code> class.</p>
          
          <p>The default width for tabs is now 4, as opposed to the 8 that is
          hard-wired into browsers. If you are relying on 8-space tabs, make
          sure you explicitly set <code>tabSize: 8</code> in your options.</p>
          
          </article>
          
        • upgrade_v3.html
          <!doctype html>
          
          <title>CodeMirror: Version 3 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="../lib/codemirror.js"></script>
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../addon/runmode/runmode.js"></script>
          <script src="../addon/runmode/colorize.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#upgrade">Upgrade guide</a>
              <li><a href="#dom">DOM structure</a></li>
              <li><a href="#gutters">Gutter model</a></li>
              <li><a href="#events">Event handling</a></li>
              <li><a href="#marktext">markText method arguments</a></li>
              <li><a href="#folding">Line folding</a></li>
              <li><a href="#lineclass">Line CSS classes</a></li>
              <li><a href="#positions">Position properties</a></li>
              <li><a href="#matchbrackets">Bracket matching</a></li>
              <li><a href="#modes">Mode management</a></li>
              <li><a href="#new">New features</a></li>
            </ul>
          </div>
          
          <article>
          
          <h2 id=upgrade>Upgrading to version 3</h2>
          
          <p>Version 3 does not depart too much from 2.x API, and sites that use
          CodeMirror in a very simple way might be able to upgrade without
          trouble. But it does introduce a number of incompatibilities. Please
          at least skim this text before upgrading.</p>
          
          <p>Note that <strong>version 3 drops full support for Internet
          Explorer 7</strong>. The editor will mostly work on that browser, but
          it'll be significantly glitchy.</p>
          
          <section id=dom>
            <h2>DOM structure</h2>
          
          <p>This one is the most likely to cause problems. The internal
          structure of the editor has changed quite a lot, mostly to implement a
          new scrolling model.</p>
          
          <p>Editor height is now set on the outer wrapper element (CSS
          class <code>CodeMirror</code>), not on the scroller element
          (<code>CodeMirror-scroll</code>).</p>
          
          <p>Other nodes were moved, dropped, and added. If you have any code
          that makes assumptions about the internal DOM structure of the editor,
          you'll have to re-test it and probably update it to work with v3.</p>
          
          <p>See the <a href="manual.html#styling">styling section</a> of the
          manual for more information.</p>
          </section>
          <section id=gutters>
            <h2>Gutter model</h2>
          
          <p>In CodeMirror 2.x, there was a single gutter, and line markers
          created with <code>setMarker</code> would have to somehow coexist with
          the line numbers (if present). Version 3 allows you to specify an
          array of gutters, <a href="manual.html#option_gutters">by class
          name</a>,
          use <a href="manual.html#setGutterMarker"><code>setGutterMarker</code></a>
          to add or remove markers in individual gutters, and clear whole
          gutters
          with <a href="manual.html#clearGutter"><code>clearGutter</code></a>.
          Gutter markers are now specified as DOM nodes, rather than HTML
          snippets.</p>
          
          <p>The gutters no longer horizontally scrolls along with the content.
          The <code>fixedGutter</code> option was removed (since it is now the
          only behavior).</p>
          
          <pre data-lang="text/html">
          &lt;style>
            /* Define a gutter style */
            .note-gutter { width: 3em; background: cyan; }
          &lt;/style>
          &lt;script>
            // Create an instance with two gutters -- line numbers and notes
            var cm = new CodeMirror(document.body, {
              gutters: ["note-gutter", "CodeMirror-linenumbers"],
              lineNumbers: true
            });
            // Add a note to line 0
            cm.setGutterMarker(0, "note-gutter", document.createTextNode("hi"));
          &lt;/script>
          </pre>
          </section>
          <section id=events>
            <h2>Event handling</h2>
          
          <p>Most of the <code>onXYZ</code> options have been removed. The same
          effect is now obtained by calling
          the <a href="manual.html#on"><code>on</code></a> method with a string
          identifying the event type. Multiple handlers can now be registered
          (and individually unregistered) for an event, and objects such as line
          handlers now also expose events. See <a href="manual.html#events">the
          full list here</a>.</p>
          
          <p>(The <code>onKeyEvent</code> and <code>onDragEvent</code> options,
          which act more as hooks than as event handlers, are still there in
          their old form.)</p>
          
          <pre data-lang="javascript">
          cm.on("change", function(cm, change) {
            console.log("something changed! (" + change.origin + ")");
          });
          </pre>
          </section>
          <section id=marktext>
            <h2>markText method arguments</h2>
          
          <p>The <a href="manual.html#markText"><code>markText</code></a> method
          (which has gained some interesting new features, such as creating
          atomic and read-only spans, or replacing spans with widgets) no longer
          takes the CSS class name as a separate argument, but makes it an
          optional field in the options object instead.</p>
          
          <pre data-lang="javascript">
          // Style first ten lines, and forbid the cursor from entering them
          cm.markText({line: 0, ch: 0}, {line: 10, ch: 0}, {
            className: "magic-text",
            inclusiveLeft: true,
            atomic: true
          });
          </pre>
          </section>
          <section id=folding>
            <h2>Line folding</h2>
          
          <p>The interface for hiding lines has been
          removed. <a href="manual.html#markText"><code>markText</code></a> can
          now be used to do the same in a more flexible and powerful way.</p>
          
          <p>The <a href="../demo/folding.html">folding script</a> has been
          updated to use the new interface, and should now be more robust.</p>
          
          <pre data-lang="javascript">
          // Fold a range, replacing it with the text "??"
          var range = cm.markText({line: 4, ch: 2}, {line: 8, ch: 1}, {
            replacedWith: document.createTextNode("??"),
            // Auto-unfold when cursor moves into the range
            clearOnEnter: true
          });
          // Get notified when auto-unfolding
          CodeMirror.on(range, "clear", function() {
            console.log("boom");
          });
          </pre>
          </section>
          <section id=lineclass>
            <h2>Line CSS classes</h2>
          
          <p>The <code>setLineClass</code> method has been replaced
          by <a href="manual.html#addLineClass"><code>addLineClass</code></a>
          and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
          which allow more modular control over the classes attached to a line.</p>
          
          <pre data-lang="javascript">
          var marked = cm.addLineClass(10, "background", "highlighted-line");
          setTimeout(function() {
            cm.removeLineClass(marked, "background", "highlighted-line");
          });
          </pre>
          </section>
          <section id=positions>
            <h2>Position properties</h2>
          
          <p>All methods that take or return objects that represent screen
          positions now use <code>{left, top, bottom, right}</code> properties
          (not always all of them) instead of the <code>{x, y, yBot}</code> used
          by some methods in v2.x.</p>
          
          <p>Affected methods
          are <a href="manual.html#cursorCoords"><code>cursorCoords</code></a>, <a href="manual.html#charCoords"><code>charCoords</code></a>, <a href="manual.html#coordsChar"><code>coordsChar</code></a>,
          and <a href="manual.html#getScrollInfo"><code>getScrollInfo</code></a>.</p>
          </section>
          <section id=matchbrackets>
            <h2>Bracket matching no longer in core</h2>
          
          <p>The <a href="manual.html#addon_matchbrackets"><code>matchBrackets</code></a>
          option is no longer defined in the core editor.
          Load <code>addon/edit/matchbrackets.js</code> to enable it.</p>
          </section>
          <section id=modes>
            <h2>Mode management</h2>
          
          <p>The <code>CodeMirror.listModes</code>
          and <code>CodeMirror.listMIMEs</code> functions, used for listing
          defined modes, are gone. You are now encouraged to simply
          inspect <code>CodeMirror.modes</code> (mapping mode names to mode
          constructors) and <code>CodeMirror.mimeModes</code> (mapping MIME
          strings to mode specs).</p>
          </section>
          <section id=new>
            <h2>New features</h2>
          
          <p>Some more reasons to upgrade to version 3.</p>
          
          <ul>
            <li>Bi-directional text support. CodeMirror will now mostly do the
            right thing when editing Arabic or Hebrew text.</li>
            <li>Arbitrary line heights. Using fonts with different heights
            inside the editor (whether off by one pixel or fifty) is now
            supported and handled gracefully.</li>
            <li>In-line widgets. See <a href="../demo/widget.html">the demo</a>
            and <a href="manual.html#addLineWidget">the docs</a>.</li>
            <li>Defining custom options
            with <a href="manual.html#defineOption"><code>CodeMirror.defineOption</code></a>.</li>
          </ul>
          </section>
          </article>
          
          <script>setTimeout(function(){CodeMirror.colorize();}, 20);</script>
          
        • upgrade_v4.html
          <!doctype html>
          
          <title>CodeMirror: Version 4 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#upgrade">Upgrade guide</a>
              <li><a href="#multisel">Multiple selections</a>
              <li><a href="#beforeSelectionChange">The beforeSelectionChange event</a>
              <li><a href="#replaceSelection">replaceSelection and collapsing</a>
              <li><a href="#changeEvent">change event data</a>
              <li><a href="#showIfHidden">showIfHidden option to line widgets</a>
              <li><a href="#module">Module loaders</a>
              <li><a href="#shareddata">Mutating shared data structures</a></li>
              <li><a href="#deprecated">Deprecated interfaces dropped</a>
            </ul>
          </div>
          
          <article>
          
          <h2 id=upgrade>Upgrading to version 4</h2>
          
          <p>CodeMirror 4's interface is <em>very</em> close version 3, but it
          does fix a few awkward details in a backwards-incompatible ways. At
          least skim the text below before upgrading.</p>
          
          <section id=multisel><h2>Multiple selections</h2>
          
          <p>The main new feature in version 4 is multiple selections. The
          single-selection variants of methods are still there, but now
          typically act only on the <em>primary</em> selection (usually the last
          one added).</p>
          
          <p>The exception to this
          is <a href="manual.html#getSelection"><strong><code>getSelection</code></strong></a>,
          which will now return the content of <em>all</em> selections
          (separated by newlines, or whatever <code>lineSep</code> parameter you passed
          it).</p>
          
          </section>
          
          <section id=beforeSelectionChange><h2>The beforeSelectionChange event</h2>
          
          <p>This event still exists, but the object it is passed has
          a <a href="manual.html#event_beforeSelectionChange">completely new
          interface</a>, because such changes now concern multiple
          selections.</p>
          
          </section>
          
          <section id=replaceSelection><h2>replaceSelection's collapsing behavior</h2>
          
          <p>By
          default, <a href="manual.html#replaceSelection"><code>replaceSelection</code></a>
          would leave the newly inserted text selected. This is only rarely what
          you want, and also (slightly) more expensive in the new model, so the
          default was changed to <code>"end"</code>, meaning the old behavior
          must be explicitly specified by passing a second argument
          of <code>"around"</code>.</p>
          
          </section>
          
          <section id=changeEvent><h2>change event data</h2>
          
          <p>Rather than forcing client code to follow <code>next</code>
          pointers from one change object to the next, the library will now
          simply fire
          multiple <a href="manual.html#event_change"><code>"change"</code></a>
          events. Existing code will probably continue to work unmodified.</p>
          
          </section>
          
          <section id=showIfHidden><h2>showIfHidden option to line widgets</h2>
          
          <p>This option, which conceptually caused line widgets to be visible
          even if their line was hidden, was never really well-defined, and was
          buggy from the start. It would be a rather expensive feature, both in
          code complexity and run-time performance, to implement properly. It
          has been dropped entirely in 4.0.</p>
          
          </section>
          
          <section id=module><h2>Module loaders</h2>
          
          <p>All modules in the CodeMirror distribution are now wrapped in a
          shim function to make them compatible with both AMD
          (<a href="http://requirejs.org">requirejs</a>) and CommonJS (as used
          by <a href="http://nodejs.org/">node</a>
          and <a href="http://browserify.org/">browserify</a>) module loaders.
          When neither of these is present, they fall back to simply using the
          global <code>CodeMirror</code> variable.</p>
          
          <p>If you have a module loader present in your environment, CodeMirror
          will attempt to use it, and you might need to change the way you load
          CodeMirror modules.</p>
          
          </section>
          
          <section id=shareddata><h2>Mutating shared data structures</h2>
          
          <p>Data structures produced by the library should not be mutated
          unless explicitly allowed, in general. This is slightly more strict in
          4.0 than it was in earlier versions, which copied the position objects
          returned by <a href="manual.html#getCursor"><code>getCursor</code></a>
          for nebulous, historic reasons. In 4.0, mutating these
          objects <em>will</em> corrupt your editor's selection.</p>
          
          </section>
          
          <section id=deprecated><h2>Deprecated interfaces dropped</h2>
          
          <p>A few properties and methods that have been deprecated for a while
          are now gone. Most notably, the <code>onKeyEvent</code>
          and <code>onDragEvent</code> options (use the
          corresponding <a href="manual.html#event_dom">events</a> instead).</p>
          
          <p>Two silly methods, which were mostly there to stay close to the 0.x
          API, <code>setLine</code> and <code>removeLine</code> are now gone.
          Use the more
          flexible <a href="manual.html#replaceRange"><code>replaceRange</code></a>
          method instead.</p>
          
          <p>The long names for folding and completing functions
          (<code>CodeMirror.braceRangeFinder</code>, <code>CodeMirror.javascriptHint</code>,
          etc) are also gone
          (use <code>CodeMirror.fold.brace</code>, <code>CodeMirror.hint.javascript</code>).</p>
          
          <p>The <code>className</code> property in the return value
          of <a href="manual.html#getTokenAt"><code>getTokenAt</code></a>, which
          has been superseded by the <code>type</code> property, is also no
          longer present.</p>
          
          </section>
          </article>
          
        • yinyang.png
          �PNG
          
          
          IHDRxx9d6�bKGD�������	pHYsMt�ItIME�
          A�tEXtCommentCreated with GIMPW��IDATx���]lו��C1b�X"iI�m�"�x�����x��Zî4Z�/b�ٷED���"_�5b
          (ڠ(@�m�J�H?y͑��b�Xs��N��5d,K�E�CɦJ����e���)��%K��~s>���R�Ԓ̱,�4�aQ
          ��
          b1hi���z����q#�P�1��p��I:�<�!������v�$@KӨ��_���Qo6#�q��-�b��b���\��V�	Z������0h���R�K �H�$1Dz��n��-MCc6Ck����`�eM1�F�������,�$C!"�B��l��n��n�&,�9s,�x0����t���Z���\���D"@�N�ۍF���bQ�%A"�
          ���==��lB�b^�K��XO	76���gɃ+W�����2��_~I� �\!cg�����CR�.%�N����0��z��y��x��a0�@ͱ,�E"X��]��wwt����Z��$fL�|�3`t���tR[�Dgx��\��:�3��CCe�o}SL.Zzz$��E,&<,��0��h���٨-8��d��E���w��b"�[.����J���۝�~%s:��X���_В���ȵs�`hjB�˅�T�JZ�l_�z<�?�	�m6��pAҼZ2��'�Lݸ�G��ln��dʛM�}��χ1��08T���x������‚b��==����,f[�p`oŵYU����g_�:��ϐU\Ĩ͆l2)���d��(�����:��DHUjp:!���˹|,�Ql�gwG,~�l����n<70�����S>���)�$��}�ee���Dp�nG�˅��x�cgΐ/>��ss�&�r6��(�@k���
          Y�
          7'���].�}2�
          bY�\�i�M&O)
          p6�<5v����_�n^�F���!O�C�B�сQ�mX1&:�L�=yrxv|���j��tI�<�X����D1�e����������K���9r% �e��Μ�9�y|���u
          ��Adx��Id|���|���5�����7����k8
          ���~")���On��~UT�����`(����(���i��P=��?P��_�`W�N��m�v�)
          �&��n��*%o�®�^�J��)�O���p��ۍ[�pE5���^2���BH$$���4���hd��]��0Dz��zq���Yl-��TJ���N42ڼ^Jt��`�|r�,���K�5�tx>�P��L P1�r��y��<���/E���ܐ��&��>y�
          I���iXYv�
          t�N'�F"�St4E,�cYEh��b��1�K\|���Z-)�C�06	�N���`
          :]Mc_!��paC�w]=���.I�T^^�84tt������`^$ߩ$?����/rܺ�z]
          �������C��?w��<�M���p�M�#��Z�8�vo(OW�����~
          2?/����z�����+������F<D��Iɀc�����{h;:;���-�/^�PV��
          �
          \�N��$%q)R]t�Wk ���(p>���<f�a�i����'i`�-���I�ws<������m9�]P�։--Kg�V��O��粜>X�ѭG)�x&ؘgx����'Y:bQ�|SL���@�L,�����X�Y�	��@x�H��ΧR�S�"��ࠨui�D;X�F�&�S>��MOT��]�����l�5��x6,�}>�XD��
          �e��Dp����X�ZU�ӑI>x �Bc�f�z��##���}������jE�N�d0HV����e=�Y�"N'�����|4�O��E]��������~��-<��_+f����MC��}��r��(u�����<Iܹ���ΧR�O�F���B<�vz�Ja���i~v}ĮkWJ4v����
          ��bE�b˭@�<�tBo�C�ף��1�q�
          �P�`E�����V�|��jq"@��!��
          �H�-X
          h���W:Ǭ&iq:�m@L��%5�,u��UXk�bzl����r=W��2����ᐽ'����j-T�T���aJ��&������dC9~8�G�rMeJ��!��S__UW���R�����Ik{;���cU|�d6#�S�����6�"1���h-�T���٦�7�o���S�J�ɓ�
          ��j6&�F�6YΞE��@M�L9
          ��-V�����د���bZ�m���=IJU��������
          ���[�{��j�x�������"Mtft�&���8�����
          (j�W1���=G��D������@0�g�VѴo%-�S��K&z���Co���n�Ď^��b͖S���f�s��EW�ղht:`�pw�q��R�������J���J��_�ުbm��l��D>��49�ߏ�����s�f{;��$����;�P���<�qhv:sAVK{�6\�!��W�!YA@�^�Z���m�5T
          4����?��)��y�
          4;v���|>�8�U��J^w._F��FQ��E�j���ap(�ʵ�tex����8��j`?���W���6�sE1�
          �9q��s]��j�Ia��U���F]ccU�bZ�f����� Q�i�+�S���V[������㗪�T߹|Z��ZX�“
          �z��W��#���#?>�&Y,TsV�����^��8�q���Z���Wp/��BI��'����P����,���:�z��==����=6c�0�%���7�Q5�䴚�8^�ko&<�|�5��2������R�?�閍.tth�V*SE%�Jh��  �r�3�w���b1pN'�[���6c�ټl������*
          XĞ��(��r�7!��["=-G�P��R�2���^��|�Q���y�i�c�����,��{*l	CCO<��;��駫���=/�b)�=n��9�L���DB��ZW��o�	ꩧ����\��
          ;9�L�|h^a'�	�-N��;�@�F��X�ʜ�WxPd�M&1���]��b��N��2,�Ɏ�Tjձ����@���o`Y��}��oCU��i�E��ij``E��*�&��2>�%��=�A�v��pu:�l6jÀ`����
          �w�}��������
          ��f���yAU5H��=\Rn~̆���<Z\.jӀ����L��"�����a�����SRs���&`��J���-����ͪXum)�%�~ԛL��޼�{9e����G�(nP��#����2�u����Q-�Z�I�d׭V���u�{>Xc�P��}j��Mi�����8IJ�e2�Vxij�E��w��Acg��p7�}}T���5�����B�ojڴ枈F%����0��~����6��>�o	�R�/�Dݷ��q"ų����ىC,��Xg�I�\.tz��j3;w�������U���)P�|�wqd�����Z��d�ɄF������֮��Xjn��f����N� ��ޭ�@-�F-.ǔBV�q���Q��ڨ��8�L��[[�����U�/KNyp�J���������B��`����+�O�bH��էT��d7��6
          �$�����ރV=�U:�}�Aը͆枞5ˑ���b{�ur���=���K����	��`�T����^�L�����Skt:�K<^��Z*��W�v�Ӊt$�c�hY�5eO�;���Q�o~SVs�I�����+j�cp�lW��)�(��_�����MV��PSU:̻�4����h��L:TQ�j��⡏>����~Qk�R��l2�Q�)��Vp���We5יT
          �Ӊl��1�܅X�6�M&Q��
          ��'����2M���qe�C��B!�M���+:\Q���$���O��=���굛�q0���-@)�Nz�����Nj##%1d䎤�8}�lB"!K�����
          �-#� ����� ��`(�%F0%��.��J�~�k��Ӳ��L*�+���)gBpo`�Z����GF�J­�K2$���vh��h�>��9��dB��D0���K ��)����b18Կ��w�<}z�]b�8��of3&$��0�J���s��ׇ�3���8<2BIWR
          .��p��9ww�^�#����.�nwE4:�J��χ��SP���_��W���`e\z��?��k�d��4���/�ʩeg��M�|���@i4��с���,`�q�S�.�F����6�Z%�NG�X�9��g|�GL���x�0��?����-���w���˗�ZV�+���D�Y����jAaz�U�~����H�s�L�B���_����!�(Z�
          O=��7߄����t�S3��=O
           11�K;�^_�V�L&���n^{
          �C��xY����
          A��իH�̀�h*��75���IA@s{;t�����be�-x%�Ns���b��E�Ejf-F#f����������L �,��B��Ӹ���h�3'N�����0�<6\����������r�2�q�7���8���B��$1���Ȑ���n-IEND�B`�
      • keymap
        • emacs.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../lib/codemirror"));
            else if (typeof define == "function" && define.amd) // AMD
              define(["../lib/codemirror"], mod);
            else // Plain browser env
              mod(CodeMirror);
          })(function(CodeMirror) {
            "use strict";
          
            var Pos = CodeMirror.Pos;
            function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
          
            // Kill 'ring'
          
            var killRing = [];
            function addToRing(str) {
              killRing.push(str);
              if (killRing.length > 50) killRing.shift();
            }
            function growRingTop(str) {
              if (!killRing.length) return addToRing(str);
              killRing[killRing.length - 1] += str;
            }
            function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; }
            function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }
          
            var lastKill = null;
          
            function kill(cm, from, to, mayGrow, text) {
              if (text == null) text = cm.getRange(from, to);
          
              if (mayGrow && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen))
                growRingTop(text);
              else
                addToRing(text);
              cm.replaceRange("", from, to, "+delete");
          
              if (mayGrow) lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()};
              else lastKill = null;
            }
          
            // Boundaries of various units
          
            function byChar(cm, pos, dir) {
              return cm.findPosH(pos, dir, "char", true);
            }
          
            function byWord(cm, pos, dir) {
              return cm.findPosH(pos, dir, "word", true);
            }
          
            function byLine(cm, pos, dir) {
              return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn);
            }
          
            function byPage(cm, pos, dir) {
              return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn);
            }
          
            function byParagraph(cm, pos, dir) {
              var no = pos.line, line = cm.getLine(no);
              var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch));
              var fst = cm.firstLine(), lst = cm.lastLine();
              for (;;) {
                no += dir;
                if (no < fst || no > lst)
                  return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null));
                line = cm.getLine(no);
                var hasText = /\S/.test(line);
                if (hasText) sawText = true;
                else if (sawText) return Pos(no, 0);
              }
            }
          
            function bySentence(cm, pos, dir) {
              var line = pos.line, ch = pos.ch;
              var text = cm.getLine(pos.line), sawWord = false;
              for (;;) {
                var next = text.charAt(ch + (dir < 0 ? -1 : 0));
                if (!next) { // End/beginning of line reached
                  if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch);
                  text = cm.getLine(line + dir);
                  if (!/\S/.test(text)) return Pos(line, ch);
                  line += dir;
                  ch = dir < 0 ? text.length : 0;
                  continue;
                }
                if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0));
                if (!sawWord) sawWord = /\w/.test(next);
                ch += dir;
              }
            }
          
            function byExpr(cm, pos, dir) {
              var wrap;
              if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, true))
                  && wrap.match && (wrap.forward ? 1 : -1) == dir)
                return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to;
          
              for (var first = true;; first = false) {
                var token = cm.getTokenAt(pos);
                var after = Pos(pos.line, dir < 0 ? token.start : token.end);
                if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) {
                  var newPos = cm.findPosH(after, dir, "char");
                  if (posEq(after, newPos)) return pos;
                  else pos = newPos;
                } else {
                  return after;
                }
              }
            }
          
            // Prefixes (only crudely supported)
          
            function getPrefix(cm, precise) {
              var digits = cm.state.emacsPrefix;
              if (!digits) return precise ? null : 1;
              clearPrefix(cm);
              return digits == "-" ? -1 : Number(digits);
            }
          
            function repeated(cmd) {
              var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd;
              return function(cm) {
                var prefix = getPrefix(cm);
                f(cm);
                for (var i = 1; i < prefix; ++i) f(cm);
              };
            }
          
            function findEnd(cm, pos, by, dir) {
              var prefix = getPrefix(cm);
              if (prefix < 0) { dir = -dir; prefix = -prefix; }
              for (var i = 0; i < prefix; ++i) {
                var newPos = by(cm, pos, dir);
                if (posEq(newPos, pos)) break;
                pos = newPos;
              }
              return pos;
            }
          
            function move(by, dir) {
              var f = function(cm) {
                cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir));
              };
              f.motion = true;
              return f;
            }
          
            function killTo(cm, by, dir) {
              var selections = cm.listSelections(), cursor;
              var i = selections.length;
              while (i--) {
                cursor = selections[i].head;
                kill(cm, cursor, findEnd(cm, cursor, by, dir), true);
              }
            }
          
            function killRegion(cm) {
              if (cm.somethingSelected()) {
                var selections = cm.listSelections(), selection;
                var i = selections.length;
                while (i--) {
                  selection = selections[i];
                  kill(cm, selection.anchor, selection.head);
                }
                return true;
              }
            }
          
            function addPrefix(cm, digit) {
              if (cm.state.emacsPrefix) {
                if (digit != "-") cm.state.emacsPrefix += digit;
                return;
              }
              // Not active yet
              cm.state.emacsPrefix = digit;
              cm.on("keyHandled", maybeClearPrefix);
              cm.on("inputRead", maybeDuplicateInput);
            }
          
            var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true};
          
            function maybeClearPrefix(cm, arg) {
              if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg))
                clearPrefix(cm);
            }
          
            function clearPrefix(cm) {
              cm.state.emacsPrefix = null;
              cm.off("keyHandled", maybeClearPrefix);
              cm.off("inputRead", maybeDuplicateInput);
            }
          
            function maybeDuplicateInput(cm, event) {
              var dup = getPrefix(cm);
              if (dup > 1 && event.origin == "+input") {
                var one = event.text.join("\n"), txt = "";
                for (var i = 1; i < dup; ++i) txt += one;
                cm.replaceSelection(txt);
              }
            }
          
            function addPrefixMap(cm) {
              cm.state.emacsPrefixMap = true;
              cm.addKeyMap(prefixMap);
              cm.on("keyHandled", maybeRemovePrefixMap);
              cm.on("inputRead", maybeRemovePrefixMap);
            }
          
            function maybeRemovePrefixMap(cm, arg) {
              if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return;
              cm.removeKeyMap(prefixMap);
              cm.state.emacsPrefixMap = false;
              cm.off("keyHandled", maybeRemovePrefixMap);
              cm.off("inputRead", maybeRemovePrefixMap);
            }
          
            // Utilities
          
            function setMark(cm) {
              cm.setCursor(cm.getCursor());
              cm.setExtending(!cm.getExtending());
              cm.on("change", function() { cm.setExtending(false); });
            }
          
            function clearMark(cm) {
              cm.setExtending(false);
              cm.setCursor(cm.getCursor());
            }
          
            function getInput(cm, msg, f) {
              if (cm.openDialog)
                cm.openDialog(msg + ": <input type=\"text\" style=\"width: 10em\"/>", f, {bottom: true});
              else
                f(prompt(msg, ""));
            }
          
            function operateOnWord(cm, op) {
              var start = cm.getCursor(), end = cm.findPosH(start, 1, "word");
              cm.replaceRange(op(cm.getRange(start, end)), start, end);
              cm.setCursor(end);
            }
          
            function toEnclosingExpr(cm) {
              var pos = cm.getCursor(), line = pos.line, ch = pos.ch;
              var stack = [];
              while (line >= cm.firstLine()) {
                var text = cm.getLine(line);
                for (var i = ch == null ? text.length : ch; i > 0;) {
                  var ch = text.charAt(--i);
                  if (ch == ")")
                    stack.push("(");
                  else if (ch == "]")
                    stack.push("[");
                  else if (ch == "}")
                    stack.push("{");
                  else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch))
                    return cm.extendSelection(Pos(line, i));
                }
                --line; ch = null;
              }
            }
          
            function quit(cm) {
              cm.execCommand("clearSearch");
              clearMark(cm);
            }
          
            // Actual keymap
          
            var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({
              "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
              "Ctrl-K": repeated(function(cm) {
                var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
                var text = cm.getRange(start, end);
                if (!/\S/.test(text)) {
                  text += "\n";
                  end = Pos(start.line + 1, 0);
                }
                kill(cm, start, end, true, text);
              }),
              "Alt-W": function(cm) {
                addToRing(cm.getSelection());
                clearMark(cm);
              },
              "Ctrl-Y": function(cm) {
                var start = cm.getCursor();
                cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste");
                cm.setSelection(start, cm.getCursor());
              },
              "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");},
          
              "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark,
          
              "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
              "Right": move(byChar, 1), "Left": move(byChar, -1),
              "Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
              "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); },
              "Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
              "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); },
          
              "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
              "Alt-D": function(cm) { killTo(cm, byWord, 1); },
              "Alt-Backspace": function(cm) { killTo(cm, byWord, -1); },
          
              "Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1),
              "Down": move(byLine, 1), "Up": move(byLine, -1),
              "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
              "End": "goLineEnd", "Home": "goLineStart",
          
              "Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1),
              "PageUp": move(byPage, -1), "PageDown": move(byPage, 1),
          
              "Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1),
          
              "Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1),
              "Alt-K": function(cm) { killTo(cm, bySentence, 1); },
          
              "Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1); },
              "Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1); },
              "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
          
              "Shift-Ctrl-Alt-2": function(cm) {
                var cursor = cm.getCursor();
                cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor);
              },
              "Ctrl-Alt-T": function(cm) {
                var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);
                var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1);
                cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) +
                                cm.getRange(leftStart, leftEnd), leftStart, rightEnd);
              },
              "Ctrl-Alt-U": repeated(toEnclosingExpr),
          
              "Alt-Space": function(cm) {
                var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line);
                while (from && /\s/.test(text.charAt(from - 1))) --from;
                while (to < text.length && /\s/.test(text.charAt(to))) ++to;
                cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to));
              },
              "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }),
              "Ctrl-T": repeated(function(cm) {
                cm.execCommand("transposeChars");
              }),
          
              "Alt-C": repeated(function(cm) {
                operateOnWord(cm, function(w) {
                  var letter = w.search(/\w/);
                  if (letter == -1) return w;
                  return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase();
                });
              }),
              "Alt-U": repeated(function(cm) {
                operateOnWord(cm, function(w) { return w.toUpperCase(); });
              }),
              "Alt-L": repeated(function(cm) {
                operateOnWord(cm, function(w) { return w.toLowerCase(); });
              }),
          
              "Alt-;": "toggleComment",
          
              "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"),
              "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"),
              "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
              "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace",
              "Alt-/": "autocomplete",
              "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
          
              "Alt-G G": function(cm) {
                var prefix = getPrefix(cm, true);
                if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
          
                getInput(cm, "Goto line", function(str) {
                  var num;
                  if (str && !isNaN(num = Number(str)) && num == num|0 && num > 0)
                    cm.setCursor(num - 1);
                });
              },
          
              "Ctrl-X Tab": function(cm) {
                cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
              },
              "Ctrl-X Ctrl-X": function(cm) {
                cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
              },
              "Ctrl-X Ctrl-S": "save",
              "Ctrl-X Ctrl-W": "save",
              "Ctrl-X S": "saveAll",
              "Ctrl-X F": "open",
              "Ctrl-X U": repeated("undo"),
              "Ctrl-X K": "close",
              "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
              "Ctrl-X H": "selectAll",
          
              "Ctrl-Q Tab": repeated("insertTab"),
              "Ctrl-U": addPrefixMap
            });
          
            var prefixMap = {"Ctrl-G": clearPrefix};
            function regPrefix(d) {
              prefixMap[d] = function(cm) { addPrefix(cm, d); };
              keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); };
              prefixPreservingKeys["Ctrl-" + d] = true;
            }
            for (var i = 0; i < 10; ++i) regPrefix(String(i));
            regPrefix("-");
          });
          
        • sublime.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          // A rough approximation of Sublime Text's keybindings
          // Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets"));
            else if (typeof define == "function" && define.amd) // AMD
              define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);
            else // Plain browser env
              mod(CodeMirror);
          })(function(CodeMirror) {
            "use strict";
          
            var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};
            var cmds = CodeMirror.commands;
            var Pos = CodeMirror.Pos;
            var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
            var ctrl = mac ? "Cmd-" : "Ctrl-";
          
            // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
            function findPosSubword(doc, start, dir) {
              if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
              var line = doc.getLine(start.line);
              if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
              var state = "start", type;
              for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {
                var next = line.charAt(dir < 0 ? pos - 1 : pos);
                var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
                if (cat == "w" && next.toUpperCase() == next) cat = "W";
                if (state == "start") {
                  if (cat != "o") { state = "in"; type = cat; }
                } else if (state == "in") {
                  if (type != cat) {
                    if (type == "w" && cat == "W" && dir < 0) pos--;
                    if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; }
                    break;
                  }
                }
              }
              return Pos(start.line, pos);
            }
          
            function moveSubword(cm, dir) {
              cm.extendSelectionsBy(function(range) {
                if (cm.display.shift || cm.doc.extend || range.empty())
                  return findPosSubword(cm.doc, range.head, dir);
                else
                  return dir < 0 ? range.from() : range.to();
              });
            }
          
            cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
            cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };
          
            cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) {
              var info = cm.getScrollInfo();
              if (!cm.somethingSelected()) {
                var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
                if (cm.getCursor().line >= visibleBottomLine)
                  cm.execCommand("goLineUp");
              }
              cm.scrollTo(null, info.top - cm.defaultTextHeight());
            };
            cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) {
              var info = cm.getScrollInfo();
              if (!cm.somethingSelected()) {
                var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
                if (cm.getCursor().line <= visibleTopLine)
                  cm.execCommand("goLineDown");
              }
              cm.scrollTo(null, info.top + cm.defaultTextHeight());
            };
          
            cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) {
              var ranges = cm.listSelections(), lineRanges = [];
              for (var i = 0; i < ranges.length; i++) {
                var from = ranges[i].from(), to = ranges[i].to();
                for (var line = from.line; line <= to.line; ++line)
                  if (!(to.line > from.line && line == to.line && to.ch == 0))
                    lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),
                                     head: line == to.line ? to : Pos(line)});
              }
              cm.setSelections(lineRanges, 0);
            };
          
            map["Shift-Tab"] = "indentLess";
          
            cmds[map["Esc"] = "singleSelectionTop"] = function(cm) {
              var range = cm.listSelections()[0];
              cm.setSelection(range.anchor, range.head, {scroll: false});
            };
          
            cmds[map[ctrl + "L"] = "selectLine"] = function(cm) {
              var ranges = cm.listSelections(), extended = [];
              for (var i = 0; i < ranges.length; i++) {
                var range = ranges[i];
                extended.push({anchor: Pos(range.from().line, 0),
                               head: Pos(range.to().line + 1, 0)});
              }
              cm.setSelections(extended);
            };
          
            map["Shift-" + ctrl + "K"] = "deleteLine";
          
            function insertLine(cm, above) {
              cm.operation(function() {
                var len = cm.listSelections().length, newSelection = [], last = -1;
                for (var i = 0; i < len; i++) {
                  var head = cm.listSelections()[i].head;
                  if (head.line <= last) continue;
                  var at = Pos(head.line + (above ? 0 : 1), 0);
                  cm.replaceRange("\n", at, null, "+insertLine");
                  cm.indentLine(at.line, null, true);
                  newSelection.push({head: at, anchor: at});
                  last = head.line + 1;
                }
                cm.setSelections(newSelection);
              });
            }
          
            cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); };
          
            cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); };
          
            function wordAt(cm, pos) {
              var start = pos.ch, end = start, line = cm.getLine(pos.line);
              while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;
              while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;
              return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};
            }
          
            cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) {
              var from = cm.getCursor("from"), to = cm.getCursor("to");
              var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;
              if (CodeMirror.cmpPos(from, to) == 0) {
                var word = wordAt(cm, from);
                if (!word.word) return;
                cm.setSelection(word.from, word.to);
                fullWord = true;
              } else {
                var text = cm.getRange(from, to);
                var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
                var cur = cm.getSearchCursor(query, to);
                if (cur.findNext()) {
                  cm.addSelection(cur.from(), cur.to());
                } else {
                  cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
                  if (cur.findNext())
                    cm.addSelection(cur.from(), cur.to());
                }
              }
              if (fullWord)
                cm.state.sublimeFindFullWord = cm.doc.sel;
            };
          
            var mirror = "(){}[]";
            function selectBetweenBrackets(cm) {
              var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1);
              if (!opening) return;
              for (;;) {
                var closing = cm.scanForBracket(pos, 1);
                if (!closing) return;
                if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {
                  cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false);
                  return true;
                }
                pos = Pos(closing.pos.line, closing.pos.ch + 1);
              }
            }
          
            cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) {
              selectBetweenBrackets(cm) || cm.execCommand("selectAll");
            };
            cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) {
              if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
            };
          
            cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) {
              cm.extendSelectionsBy(function(range) {
                var next = cm.scanForBracket(range.head, 1);
                if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;
                var prev = cm.scanForBracket(range.head, -1);
                return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
              });
            };
          
            var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";
          
            cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {
              var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
              for (var i = 0; i < ranges.length; i++) {
                var range = ranges[i], from = range.from().line - 1, to = range.to().line;
                newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),
                              head: Pos(range.head.line - 1, range.head.ch)});
                if (range.to().ch == 0 && !range.empty()) --to;
                if (from > at) linesToMove.push(from, to);
                else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
                at = to;
              }
              cm.operation(function() {
                for (var i = 0; i < linesToMove.length; i += 2) {
                  var from = linesToMove[i], to = linesToMove[i + 1];
                  var line = cm.getLine(from);
                  cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
                  if (to > cm.lastLine())
                    cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine");
                  else
                    cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
                }
                cm.setSelections(newSels);
                cm.scrollIntoView();
              });
            };
          
            cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {
              var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
              for (var i = ranges.length - 1; i >= 0; i--) {
                var range = ranges[i], from = range.to().line + 1, to = range.from().line;
                if (range.to().ch == 0 && !range.empty()) from--;
                if (from < at) linesToMove.push(from, to);
                else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
                at = to;
              }
              cm.operation(function() {
                for (var i = linesToMove.length - 2; i >= 0; i -= 2) {
                  var from = linesToMove[i], to = linesToMove[i + 1];
                  var line = cm.getLine(from);
                  if (from == cm.lastLine())
                    cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");
                  else
                    cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
                  cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
                }
                cm.scrollIntoView();
              });
            };
          
            map[ctrl + "/"] = "toggleComment";
          
            cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {
              var ranges = cm.listSelections(), joined = [];
              for (var i = 0; i < ranges.length; i++) {
                var range = ranges[i], from = range.from();
                var start = from.line, end = range.to().line;
                while (i < ranges.length - 1 && ranges[i + 1].from().line == end)
                  end = ranges[++i].to().line;
                joined.push({start: start, end: end, anchor: !range.empty() && from});
              }
              cm.operation(function() {
                var offset = 0, ranges = [];
                for (var i = 0; i < joined.length; i++) {
                  var obj = joined[i];
                  var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;
                  for (var line = obj.start; line <= obj.end; line++) {
                    var actual = line - offset;
                    if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);
                    if (actual < cm.lastLine()) {
                      cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length));
                      ++offset;
                    }
                  }
                  ranges.push({anchor: anchor || head, head: head});
                }
                cm.setSelections(ranges, 0);
              });
            };
          
            cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) {
              cm.operation(function() {
                var rangeCount = cm.listSelections().length;
                for (var i = 0; i < rangeCount; i++) {
                  var range = cm.listSelections()[i];
                  if (range.empty())
                    cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0));
                  else
                    cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());
                }
                cm.scrollIntoView();
              });
            };
          
            map[ctrl + "T"] = "transposeChars";
          
            function sortLines(cm, caseSensitive) {
              var ranges = cm.listSelections(), toSort = [], selected;
              for (var i = 0; i < ranges.length; i++) {
                var range = ranges[i];
                if (range.empty()) continue;
                var from = range.from().line, to = range.to().line;
                while (i < ranges.length - 1 && ranges[i + 1].from().line == to)
                  to = range[++i].to().line;
                toSort.push(from, to);
              }
              if (toSort.length) selected = true;
              else toSort.push(cm.firstLine(), cm.lastLine());
          
              cm.operation(function() {
                var ranges = [];
                for (var i = 0; i < toSort.length; i += 2) {
                  var from = toSort[i], to = toSort[i + 1];
                  var start = Pos(from, 0), end = Pos(to);
                  var lines = cm.getRange(start, end, false);
                  if (caseSensitive)
                    lines.sort();
                  else
                    lines.sort(function(a, b) {
                      var au = a.toUpperCase(), bu = b.toUpperCase();
                      if (au != bu) { a = au; b = bu; }
                      return a < b ? -1 : a == b ? 0 : 1;
                    });
                  cm.replaceRange(lines, start, end);
                  if (selected) ranges.push({anchor: start, head: end});
                }
                if (selected) cm.setSelections(ranges, 0);
              });
            }
          
            cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); };
            cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); };
          
            cmds[map["F2"] = "nextBookmark"] = function(cm) {
              var marks = cm.state.sublimeBookmarks;
              if (marks) while (marks.length) {
                var current = marks.shift();
                var found = current.find();
                if (found) {
                  marks.push(current);
                  return cm.setSelection(found.from, found.to);
                }
              }
            };
          
            cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) {
              var marks = cm.state.sublimeBookmarks;
              if (marks) while (marks.length) {
                marks.unshift(marks.pop());
                var found = marks[marks.length - 1].find();
                if (!found)
                  marks.pop();
                else
                  return cm.setSelection(found.from, found.to);
              }
            };
          
            cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) {
              var ranges = cm.listSelections();
              var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);
              for (var i = 0; i < ranges.length; i++) {
                var from = ranges[i].from(), to = ranges[i].to();
                var found = cm.findMarks(from, to);
                for (var j = 0; j < found.length; j++) {
                  if (found[j].sublimeBookmark) {
                    found[j].clear();
                    for (var k = 0; k < marks.length; k++)
                      if (marks[k] == found[j])
                        marks.splice(k--, 1);
                    break;
                  }
                }
                if (j == found.length)
                  marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));
              }
            };
          
            cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) {
              var marks = cm.state.sublimeBookmarks;
              if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();
              marks.length = 0;
            };
          
            cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) {
              var marks = cm.state.sublimeBookmarks, ranges = [];
              if (marks) for (var i = 0; i < marks.length; i++) {
                var found = marks[i].find();
                if (!found)
                  marks.splice(i--, 0);
                else
                  ranges.push({anchor: found.from, head: found.to});
              }
              if (ranges.length)
                cm.setSelections(ranges, 0);
            };
          
            map["Alt-Q"] = "wrapLines";
          
            var cK = ctrl + "K ";
          
            function modifyWordOrSelection(cm, mod) {
              cm.operation(function() {
                var ranges = cm.listSelections(), indices = [], replacements = [];
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (range.empty()) { indices.push(i); replacements.push(""); }
                  else replacements.push(mod(cm.getRange(range.from(), range.to())));
                }
                cm.replaceSelections(replacements, "around", "case");
                for (var i = indices.length - 1, at; i >= 0; i--) {
                  var range = ranges[indices[i]];
                  if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;
                  var word = wordAt(cm, range.head);
                  at = word.from;
                  cm.replaceRange(mod(word.word), word.from, word.to);
                }
              });
            }
          
            map[cK + ctrl + "Backspace"] = "delLineLeft";
          
            cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
              cm.operation(function() {
                var ranges = cm.listSelections();
                for (var i = ranges.length - 1; i >= 0; i--)
                  cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");
                cm.scrollIntoView();
              });
            };
          
            cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
              modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
            };
            cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
              modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
            };
          
            cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {
              if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
              cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
            };
            cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
              var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
              if (found) cm.setSelection(cm.getCursor(), found);
            };
            cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
              var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
              if (found) {
                var from = cm.getCursor(), to = found;
                if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }
                cm.state.sublimeKilled = cm.getRange(from, to);
                cm.replaceRange("", from, to);
              }
            };
            cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
              var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
              if (found) {
                cm.state.sublimeMark.clear();
                cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
                cm.setCursor(found);
              }
            };
            cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {
              if (cm.state.sublimeKilled != null)
                cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
            };
          
            map[cK + ctrl + "G"] = "clearBookmarks";
            cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {
              var pos = cm.cursorCoords(null, "local");
              cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
            };
          
            cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) {
              cm.operation(function() {
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (range.head.line > cm.firstLine())
                    cm.addSelection(Pos(range.head.line - 1, range.head.ch));
                }
              });
            };
            cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) {
              cm.operation(function() {
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (range.head.line < cm.lastLine())
                    cm.addSelection(Pos(range.head.line + 1, range.head.ch));
                }
              });
            };
          
            function getTarget(cm) {
              var from = cm.getCursor("from"), to = cm.getCursor("to");
              if (CodeMirror.cmpPos(from, to) == 0) {
                var word = wordAt(cm, from);
                if (!word.word) return;
                from = word.from;
                to = word.to;
              }
              return {from: from, to: to, query: cm.getRange(from, to), word: word};
            }
          
            function findAndGoTo(cm, forward) {
              var target = getTarget(cm);
              if (!target) return;
              var query = target.query;
              var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
          
              if (forward ? cur.findNext() : cur.findPrevious()) {
                cm.setSelection(cur.from(), cur.to());
              } else {
                cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)
                                                        : cm.clipPos(Pos(cm.lastLine())));
                if (forward ? cur.findNext() : cur.findPrevious())
                  cm.setSelection(cur.from(), cur.to());
                else if (target.word)
                  cm.setSelection(target.from, target.to);
              }
            };
            cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); };
            cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); };
            cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) {
              var target = getTarget(cm);
              if (!target) return;
              var cur = cm.getSearchCursor(target.query);
              var matches = [];
              var primaryIndex = -1;
              while (cur.findNext()) {
                matches.push({anchor: cur.from(), head: cur.to()});
                if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
                  primaryIndex++;
              }
              cm.setSelections(matches, primaryIndex);
            };
          
            map["Shift-" + ctrl + "["] = "fold";
            map["Shift-" + ctrl + "]"] = "unfold";
            map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";
          
            map[ctrl + "I"] = "findIncremental";
            map["Shift-" + ctrl + "I"] = "findIncrementalReverse";
            map[ctrl + "H"] = "replace";
            map["F3"] = "findNext";
            map["Shift-F3"] = "findPrev";
          
            CodeMirror.normalizeKeyMap(map);
          });
          
        • vim.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          /**
           * Supported keybindings:
           *
           *   Motion:
           *   h, j, k, l
           *   gj, gk
           *   e, E, w, W, b, B, ge, gE
           *   f<character>, F<character>, t<character>, T<character>
           *   $, ^, 0, -, +, _
           *   gg, G
           *   %
           *   '<character>, `<character>
           *
           *   Operator:
           *   d, y, c
           *   dd, yy, cc
           *   g~, g~g~
           *   >, <, >>, <<
           *
           *   Operator-Motion:
           *   x, X, D, Y, C, ~
           *
           *   Action:
           *   a, i, s, A, I, S, o, O
           *   zz, z., z<CR>, zt, zb, z-
           *   J
           *   u, Ctrl-r
           *   m<character>
           *   r<character>
           *
           *   Modes:
           *   ESC - leave insert mode, visual mode, and clear input state.
           *   Ctrl-[, Ctrl-c - same as ESC.
           *
           * Registers: unnamed, -, a-z, A-Z, 0-9
           *   (Does not respect the special case for number registers when delete
           *    operator is made with these commands: %, (, ),  , /, ?, n, N, {, } )
           *   TODO: Implement the remaining registers.
           * Marks: a-z, A-Z, and 0-9
           *   TODO: Implement the remaining special marks. They have more complex
           *       behavior.
           *
           * Events:
           *  'vim-mode-change' - raised on the editor anytime the current mode changes,
           *                      Event object: {mode: "visual", subMode: "linewise"}
           *
           * Code structure:
           *  1. Default keymap
           *  2. Variable declarations and short basic helpers
           *  3. Instance (External API) implementation
           *  4. Internal state tracking objects (input state, counter) implementation
           *     and instanstiation
           *  5. Key handler (the main command dispatcher) implementation
           *  6. Motion, operator, and action implementations
           *  7. Helper functions for the key handler, motions, operators, and actions
           *  8. Set up Vim to work as a keymap for CodeMirror.
           */
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/dialog/dialog"), require("../addon/edit/matchbrackets.js"));
            else if (typeof define == "function" && define.amd) // AMD
              define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod);
            else // Plain browser env
              mod(CodeMirror);
          })(function(CodeMirror) {
            'use strict';
          
            var defaultKeymap = [
              // Key to key mapping. This goes first to make it possible to override
              // existing mappings.
              { keys: '<Left>', type: 'keyToKey', toKeys: 'h' },
              { keys: '<Right>', type: 'keyToKey', toKeys: 'l' },
              { keys: '<Up>', type: 'keyToKey', toKeys: 'k' },
              { keys: '<Down>', type: 'keyToKey', toKeys: 'j' },
              { keys: '<Space>', type: 'keyToKey', toKeys: 'l' },
              { keys: '<BS>', type: 'keyToKey', toKeys: 'h', context: 'normal'},
              { keys: '<C-Space>', type: 'keyToKey', toKeys: 'W' },
              { keys: '<C-BS>', type: 'keyToKey', toKeys: 'B', context: 'normal' },
              { keys: '<S-Space>', type: 'keyToKey', toKeys: 'w' },
              { keys: '<S-BS>', type: 'keyToKey', toKeys: 'b', context: 'normal' },
              { keys: '<C-n>', type: 'keyToKey', toKeys: 'j' },
              { keys: '<C-p>', type: 'keyToKey', toKeys: 'k' },
              { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>' },
              { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>' },
              { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
              { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
              { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' },
              { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'},
              { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },
              { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' },
              { keys: '<Home>', type: 'keyToKey', toKeys: '0' },
              { keys: '<End>', type: 'keyToKey', toKeys: '$' },
              { keys: '<PageUp>', type: 'keyToKey', toKeys: '<C-b>' },
              { keys: '<PageDown>', type: 'keyToKey', toKeys: '<C-f>' },
              { keys: '<CR>', type: 'keyToKey', toKeys: 'j^', context: 'normal' },
              // Motions
              { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }},
              { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }},
              { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }},
              { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }},
              { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }},
              { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }},
              { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }},
              { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }},
              { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }},
              { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }},
              { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }},
              { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }},
              { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }},
              { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }},
              { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }},
              { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }},
              { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},
              { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }},
              { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }},
              { keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }},
              { keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }},
              { keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }},
              { keys: '<C-u>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }},
              { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }},
              { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }},
              { keys: '0', type: 'motion', motion: 'moveToStartOfLine' },
              { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' },
              { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }},
              { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }},
              { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }},
              { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }},
              { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }},
              { keys: 'f<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }},
              { keys: 'F<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }},
              { keys: 't<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }},
              { keys: 'T<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }},
              { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }},
              { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }},
              { keys: '\'<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}},
              { keys: '`<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}},
              { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } },
              { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } },
              { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } },
              { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } },
              // the next two aren't motions but must come before more general motion declarations
              { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}},
              { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}},
              { keys: ']<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}},
              { keys: '[<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}},
              { keys: '|', type: 'motion', motion: 'moveToColumn'},
              { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'},
              { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'},
              // Operators
              { keys: 'd', type: 'operator', operator: 'delete' },
              { keys: 'y', type: 'operator', operator: 'yank' },
              { keys: 'c', type: 'operator', operator: 'change' },
              { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }},
              { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }},
              { keys: 'g~', type: 'operator', operator: 'changeCase' },
              { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true },
              { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true },
              { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }},
              { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }},
              // Operator-Motion dual commands
              { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }},
              { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
              { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
              { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'},
              { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
              { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'},
              { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
              { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'},
              { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'},
              { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'},
              { keys: '<C-w>', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' },
              // Actions
              { keys: '<C-i>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }},
              { keys: '<C-o>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }},
              { keys: '<C-e>', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }},
              { keys: '<C-y>', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }},
              { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' },
              { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' },
              { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' },
              { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' },
              { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' },
              { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' },
              { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' },
              { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' },
              { keys: 'v', type: 'action', action: 'toggleVisualMode' },
              { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }},
              { keys: '<C-v>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
              { keys: 'gv', type: 'action', action: 'reselectLastSelection' },
              { keys: 'J', type: 'action', action: 'joinLines', isEdit: true },
              { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }},
              { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }},
              { keys: 'r<character>', type: 'action', action: 'replace', isEdit: true },
              { keys: '@<character>', type: 'action', action: 'replayMacro' },
              { keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' },
              // Handle Replace-mode as a special case of insert mode.
              { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }},
              { keys: 'u', type: 'action', action: 'undo', context: 'normal' },
              { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true },
              { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true },
              { keys: '<C-r>', type: 'action', action: 'redo' },
              { keys: 'm<character>', type: 'action', action: 'setMark' },
              { keys: '"<character>', type: 'action', action: 'setRegister' },
              { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }},
              { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
              { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }},
              { keys: 'z<CR>', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
              { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }},
              { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
              { keys: '.', type: 'action', action: 'repeatLastEdit' },
              { keys: '<C-a>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}},
              { keys: '<C-x>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}},
              // Text object motions
              { keys: 'a<character>', type: 'motion', motion: 'textObjectManipulation' },
              { keys: 'i<character>', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }},
              // Search
              { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }},
              { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }},
              { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
              { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
              { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }},
              { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }},
              // Ex command
              { keys: ':', type: 'ex' }
            ];
          
            var Pos = CodeMirror.Pos;
          
            var Vim = function() {
              function enterVimMode(cm) {
                cm.setOption('disableInput', true);
                cm.setOption('showCursorWhenSelecting', false);
                CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
                cm.on('cursorActivity', onCursorActivity);
                maybeInitVimState(cm);
                CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm));
              }
          
              function leaveVimMode(cm) {
                cm.setOption('disableInput', false);
                cm.off('cursorActivity', onCursorActivity);
                CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm));
                cm.state.vim = null;
              }
          
              function detachVimMap(cm, next) {
                if (this == CodeMirror.keyMap.vim)
                  CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor");
          
                if (!next || next.attach != attachVimMap)
                  leaveVimMode(cm, false);
              }
              function attachVimMap(cm, prev) {
                if (this == CodeMirror.keyMap.vim)
                  CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor");
          
                if (!prev || prev.attach != attachVimMap)
                  enterVimMode(cm);
              }
          
              // Deprecated, simply setting the keymap works again.
              CodeMirror.defineOption('vimMode', false, function(cm, val, prev) {
                if (val && cm.getOption("keyMap") != "vim")
                  cm.setOption("keyMap", "vim");
                else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap")))
                  cm.setOption("keyMap", "default");
              });
          
              function cmKey(key, cm) {
                if (!cm) { return undefined; }
                var vimKey = cmKeyToVimKey(key);
                if (!vimKey) {
                  return false;
                }
                var cmd = CodeMirror.Vim.findKey(cm, vimKey);
                if (typeof cmd == 'function') {
                  CodeMirror.signal(cm, 'vim-keypress', vimKey);
                }
                return cmd;
              }
          
              var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'};
              var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'};
              function cmKeyToVimKey(key) {
                if (key.charAt(0) == '\'') {
                  // Keypress character binding of format "'a'"
                  return key.charAt(1);
                }
                var pieces = key.split('-');
                if (/-$/.test(key)) {
                  // If the - key was typed, split will result in 2 extra empty strings
                  // in the array. Replace them with 1 '-'.
                  pieces.splice(-2, 2, '-');
                }
                var lastPiece = pieces[pieces.length - 1];
                if (pieces.length == 1 && pieces[0].length == 1) {
                  // No-modifier bindings use literal character bindings above. Skip.
                  return false;
                } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) {
                  // Ignore Shift+char bindings as they should be handled by literal character.
                  return false;
                }
                var hasCharacter = false;
                for (var i = 0; i < pieces.length; i++) {
                  var piece = pieces[i];
                  if (piece in modifiers) { pieces[i] = modifiers[piece]; }
                  else { hasCharacter = true; }
                  if (piece in specialKeys) { pieces[i] = specialKeys[piece]; }
                }
                if (!hasCharacter) {
                  // Vim does not support modifier only keys.
                  return false;
                }
                // TODO: Current bindings expect the character to be lower case, but
                // it looks like vim key notation uses upper case.
                if (isUpperCase(lastPiece)) {
                  pieces[pieces.length - 1] = lastPiece.toLowerCase();
                }
                return '<' + pieces.join('-') + '>';
              }
          
              function getOnPasteFn(cm) {
                var vim = cm.state.vim;
                if (!vim.onPasteFn) {
                  vim.onPasteFn = function() {
                    if (!vim.insertMode) {
                      cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
                      actions.enterInsertMode(cm, {}, vim);
                    }
                  };
                }
                return vim.onPasteFn;
              }
          
              var numberRegex = /[\d]/;
              var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)];
              function makeKeyRange(start, size) {
                var keys = [];
                for (var i = start; i < start + size; i++) {
                  keys.push(String.fromCharCode(i));
                }
                return keys;
              }
              var upperCaseAlphabet = makeKeyRange(65, 26);
              var lowerCaseAlphabet = makeKeyRange(97, 26);
              var numbers = makeKeyRange(48, 10);
              var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']);
              var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']);
          
              function isLine(cm, line) {
                return line >= cm.firstLine() && line <= cm.lastLine();
              }
              function isLowerCase(k) {
                return (/^[a-z]$/).test(k);
              }
              function isMatchableSymbol(k) {
                return '()[]{}'.indexOf(k) != -1;
              }
              function isNumber(k) {
                return numberRegex.test(k);
              }
              function isUpperCase(k) {
                return (/^[A-Z]$/).test(k);
              }
              function isWhiteSpaceString(k) {
                return (/^\s*$/).test(k);
              }
              function inArray(val, arr) {
                for (var i = 0; i < arr.length; i++) {
                  if (arr[i] == val) {
                    return true;
                  }
                }
                return false;
              }
          
              var options = {};
              function defineOption(name, defaultValue, type) {
                if (defaultValue === undefined) { throw Error('defaultValue is required'); }
                if (!type) { type = 'string'; }
                options[name] = {
                  type: type,
                  defaultValue: defaultValue
                };
                setOption(name, defaultValue);
              }
          
              function setOption(name, value) {
                var option = options[name];
                if (!option) {
                  throw Error('Unknown option: ' + name);
                }
                if (option.type == 'boolean') {
                  if (value && value !== true) {
                    throw Error('Invalid argument: ' + name + '=' + value);
                  } else if (value !== false) {
                    // Boolean options are set to true if value is not defined.
                    value = true;
                  }
                }
                option.value = option.type == 'boolean' ? !!value : value;
              }
          
              function getOption(name) {
                var option = options[name];
                if (!option) {
                  throw Error('Unknown option: ' + name);
                }
                return option.value;
              }
          
              var createCircularJumpList = function() {
                var size = 100;
                var pointer = -1;
                var head = 0;
                var tail = 0;
                var buffer = new Array(size);
                function add(cm, oldCur, newCur) {
                  var current = pointer % size;
                  var curMark = buffer[current];
                  function useNextSlot(cursor) {
                    var next = ++pointer % size;
                    var trashMark = buffer[next];
                    if (trashMark) {
                      trashMark.clear();
                    }
                    buffer[next] = cm.setBookmark(cursor);
                  }
                  if (curMark) {
                    var markPos = curMark.find();
                    // avoid recording redundant cursor position
                    if (markPos && !cursorEqual(markPos, oldCur)) {
                      useNextSlot(oldCur);
                    }
                  } else {
                    useNextSlot(oldCur);
                  }
                  useNextSlot(newCur);
                  head = pointer;
                  tail = pointer - size + 1;
                  if (tail < 0) {
                    tail = 0;
                  }
                }
                function move(cm, offset) {
                  pointer += offset;
                  if (pointer > head) {
                    pointer = head;
                  } else if (pointer < tail) {
                    pointer = tail;
                  }
                  var mark = buffer[(size + pointer) % size];
                  // skip marks that are temporarily removed from text buffer
                  if (mark && !mark.find()) {
                    var inc = offset > 0 ? 1 : -1;
                    var newCur;
                    var oldCur = cm.getCursor();
                    do {
                      pointer += inc;
                      mark = buffer[(size + pointer) % size];
                      // skip marks that are the same as current position
                      if (mark &&
                          (newCur = mark.find()) &&
                          !cursorEqual(oldCur, newCur)) {
                        break;
                      }
                    } while (pointer < head && pointer > tail);
                  }
                  return mark;
                }
                return {
                  cachedCursor: undefined, //used for # and * jumps
                  add: add,
                  move: move
                };
              };
          
              // Returns an object to track the changes associated insert mode.  It
              // clones the object that is passed in, or creates an empty object one if
              // none is provided.
              var createInsertModeChanges = function(c) {
                if (c) {
                  // Copy construction
                  return {
                    changes: c.changes,
                    expectCursorActivityForChange: c.expectCursorActivityForChange
                  };
                }
                return {
                  // Change list
                  changes: [],
                  // Set to true on change, false on cursorActivity.
                  expectCursorActivityForChange: false
                };
              };
          
              function MacroModeState() {
                this.latestRegister = undefined;
                this.isPlaying = false;
                this.isRecording = false;
                this.replaySearchQueries = [];
                this.onRecordingDone = undefined;
                this.lastInsertModeChanges = createInsertModeChanges();
              }
              MacroModeState.prototype = {
                exitMacroRecordMode: function() {
                  var macroModeState = vimGlobalState.macroModeState;
                  if (macroModeState.onRecordingDone) {
                    macroModeState.onRecordingDone(); // close dialog
                  }
                  macroModeState.onRecordingDone = undefined;
                  macroModeState.isRecording = false;
                },
                enterMacroRecordMode: function(cm, registerName) {
                  var register =
                      vimGlobalState.registerController.getRegister(registerName);
                  if (register) {
                    register.clear();
                    this.latestRegister = registerName;
                    if (cm.openDialog) {
                      this.onRecordingDone = cm.openDialog(
                          '(recording)['+registerName+']', null, {bottom:true});
                    }
                    this.isRecording = true;
                  }
                }
              };
          
              function maybeInitVimState(cm) {
                if (!cm.state.vim) {
                  // Store instance state in the CodeMirror object.
                  cm.state.vim = {
                    inputState: new InputState(),
                    // Vim's input state that triggered the last edit, used to repeat
                    // motions and operators with '.'.
                    lastEditInputState: undefined,
                    // Vim's action command before the last edit, used to repeat actions
                    // with '.' and insert mode repeat.
                    lastEditActionCommand: undefined,
                    // When using jk for navigation, if you move from a longer line to a
                    // shorter line, the cursor may clip to the end of the shorter line.
                    // If j is pressed again and cursor goes to the next line, the
                    // cursor should go back to its horizontal position on the longer
                    // line if it can. This is to keep track of the horizontal position.
                    lastHPos: -1,
                    // Doing the same with screen-position for gj/gk
                    lastHSPos: -1,
                    // The last motion command run. Cleared if a non-motion command gets
                    // executed in between.
                    lastMotion: null,
                    marks: {},
                    // Mark for rendering fake cursor for visual mode.
                    fakeCursor: null,
                    insertMode: false,
                    // Repeat count for changes made in insert mode, triggered by key
                    // sequences like 3,i. Only exists when insertMode is true.
                    insertModeRepeat: undefined,
                    visualMode: false,
                    // If we are in visual line mode. No effect if visualMode is false.
                    visualLine: false,
                    visualBlock: false,
                    lastSelection: null,
                    lastPastedText: null,
                    sel: {
                    }
                  };
                }
                return cm.state.vim;
              }
              var vimGlobalState;
              function resetVimGlobalState() {
                vimGlobalState = {
                  // The current search query.
                  searchQuery: null,
                  // Whether we are searching backwards.
                  searchIsReversed: false,
                  // Replace part of the last substituted pattern
                  lastSubstituteReplacePart: undefined,
                  jumpList: createCircularJumpList(),
                  macroModeState: new MacroModeState,
                  // Recording latest f, t, F or T motion command.
                  lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''},
                  registerController: new RegisterController({}),
                  // search history buffer
                  searchHistoryController: new HistoryController({}),
                  // ex Command history buffer
                  exCommandHistoryController : new HistoryController({})
                };
                for (var optionName in options) {
                  var option = options[optionName];
                  option.value = option.defaultValue;
                }
              }
          
              var lastInsertModeKeyTimer;
              var vimApi= {
                buildKeyMap: function() {
                  // TODO: Convert keymap into dictionary format for fast lookup.
                },
                // Testing hook, though it might be useful to expose the register
                // controller anyways.
                getRegisterController: function() {
                  return vimGlobalState.registerController;
                },
                // Testing hook.
                resetVimGlobalState_: resetVimGlobalState,
          
                // Testing hook.
                getVimGlobalState_: function() {
                  return vimGlobalState;
                },
          
                // Testing hook.
                maybeInitVimState_: maybeInitVimState,
          
                suppressErrorLogging: false,
          
                InsertModeKey: InsertModeKey,
                map: function(lhs, rhs, ctx) {
                  // Add user defined key bindings.
                  exCommandDispatcher.map(lhs, rhs, ctx);
                },
                setOption: setOption,
                getOption: getOption,
                defineOption: defineOption,
                defineEx: function(name, prefix, func){
                  if (name.indexOf(prefix) !== 0) {
                    throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered');
                  }
                  exCommands[name]=func;
                  exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};
                },
                handleKey: function (cm, key, origin) {
                  var command = this.findKey(cm, key, origin);
                  if (typeof command === 'function') {
                    return command();
                  }
                },
                /**
                 * This is the outermost function called by CodeMirror, after keys have
                 * been mapped to their Vim equivalents.
                 *
                 * Finds a command based on the key (and cached keys if there is a
                 * multi-key sequence). Returns `undefined` if no key is matched, a noop
                 * function if a partial match is found (multi-key), and a function to
                 * execute the bound command if a a key is matched. The function always
                 * returns true.
                 */
                findKey: function(cm, key, origin) {
                  var vim = maybeInitVimState(cm);
                  function handleMacroRecording() {
                    var macroModeState = vimGlobalState.macroModeState;
                    if (macroModeState.isRecording) {
                      if (key == 'q') {
                        macroModeState.exitMacroRecordMode();
                        clearInputState(cm);
                        return true;
                      }
                      if (origin != 'mapping') {
                        logKey(macroModeState, key);
                      }
                    }
                  }
                  function handleEsc() {
                    if (key == '<Esc>') {
                      // Clear input state and get back to normal mode.
                      clearInputState(cm);
                      if (vim.visualMode) {
                        exitVisualMode(cm);
                      } else if (vim.insertMode) {
                        exitInsertMode(cm);
                      }
                      return true;
                    }
                  }
                  function doKeyToKey(keys) {
                    // TODO: prevent infinite recursion.
                    var match;
                    while (keys) {
                      // Pull off one command key, which is either a single character
                      // or a special sequence wrapped in '<' and '>', e.g. '<Space>'.
                      match = (/<\w+-.+?>|<\w+>|./).exec(keys);
                      key = match[0];
                      keys = keys.substring(match.index + key.length);
                      CodeMirror.Vim.handleKey(cm, key, 'mapping');
                    }
                  }
          
                  function handleKeyInsertMode() {
                    if (handleEsc()) { return true; }
                    var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
                    var keysAreChars = key.length == 1;
                    var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
                    // Need to check all key substrings in insert mode.
                    while (keys.length > 1 && match.type != 'full') {
                      var keys = vim.inputState.keyBuffer = keys.slice(1);
                      var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
                      if (thisMatch.type != 'none') { match = thisMatch; }
                    }
                    if (match.type == 'none') { clearInputState(cm); return false; }
                    else if (match.type == 'partial') {
                      if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
                      lastInsertModeKeyTimer = window.setTimeout(
                        function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } },
                        getOption('insertModeEscKeysTimeout'));
                      return !keysAreChars;
                    }
          
                    if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
                    if (keysAreChars) {
                      var here = cm.getCursor();
                      cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input');
                    }
                    clearInputState(cm);
                    return match.command;
                  }
          
                  function handleKeyNonInsertMode() {
                    if (handleMacroRecording() || handleEsc()) { return true; };
          
                    var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
                    if (/^[1-9]\d*$/.test(keys)) { return true; }
          
                    var keysMatcher = /^(\d*)(.*)$/.exec(keys);
                    if (!keysMatcher) { clearInputState(cm); return false; }
                    var context = vim.visualMode ? 'visual' :
                                                   'normal';
                    var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context);
                    if (match.type == 'none') { clearInputState(cm); return false; }
                    else if (match.type == 'partial') { return true; }
          
                    vim.inputState.keyBuffer = '';
                    var keysMatcher = /^(\d*)(.*)$/.exec(keys);
                    if (keysMatcher[1] && keysMatcher[1] != '0') {
                      vim.inputState.pushRepeatDigit(keysMatcher[1]);
                    }
                    return match.command;
                  }
          
                  var command;
                  if (vim.insertMode) { command = handleKeyInsertMode(); }
                  else { command = handleKeyNonInsertMode(); }
                  if (command === false) {
                    return undefined;
                  } else if (command === true) {
                    // TODO: Look into using CodeMirror's multi-key handling.
                    // Return no-op since we are caching the key. Counts as handled, but
                    // don't want act on it just yet.
                    return function() {};
                  } else {
                    return function() {
                      return cm.operation(function() {
                        cm.curOp.isVimOp = true;
                        try {
                          if (command.type == 'keyToKey') {
                            doKeyToKey(command.toKeys);
                          } else {
                            commandDispatcher.processCommand(cm, vim, command);
                          }
                        } catch (e) {
                          // clear VIM state in case it's in a bad state.
                          cm.state.vim = undefined;
                          maybeInitVimState(cm);
                          if (!CodeMirror.Vim.suppressErrorLogging) {
                            console['log'](e);
                          }
                          throw e;
                        }
                        return true;
                      });
                    };
                  }
                },
                handleEx: function(cm, input) {
                  exCommandDispatcher.processCommand(cm, input);
                },
          
                defineMotion: defineMotion,
                defineAction: defineAction,
                defineOperator: defineOperator,
                mapCommand: mapCommand,
                _mapCommand: _mapCommand,
          
                exitVisualMode: exitVisualMode,
                exitInsertMode: exitInsertMode
              };
          
              // Represents the current input state.
              function InputState() {
                this.prefixRepeat = [];
                this.motionRepeat = [];
          
                this.operator = null;
                this.operatorArgs = null;
                this.motion = null;
                this.motionArgs = null;
                this.keyBuffer = []; // For matching multi-key commands.
                this.registerName = null; // Defaults to the unnamed register.
              }
              InputState.prototype.pushRepeatDigit = function(n) {
                if (!this.operator) {
                  this.prefixRepeat = this.prefixRepeat.concat(n);
                } else {
                  this.motionRepeat = this.motionRepeat.concat(n);
                }
              };
              InputState.prototype.getRepeat = function() {
                var repeat = 0;
                if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) {
                  repeat = 1;
                  if (this.prefixRepeat.length > 0) {
                    repeat *= parseInt(this.prefixRepeat.join(''), 10);
                  }
                  if (this.motionRepeat.length > 0) {
                    repeat *= parseInt(this.motionRepeat.join(''), 10);
                  }
                }
                return repeat;
              };
          
              function clearInputState(cm, reason) {
                cm.state.vim.inputState = new InputState();
                CodeMirror.signal(cm, 'vim-command-done', reason);
              }
          
              /*
               * Register stores information about copy and paste registers.  Besides
               * text, a register must store whether it is linewise (i.e., when it is
               * pasted, should it insert itself into a new line, or should the text be
               * inserted at the cursor position.)
               */
              function Register(text, linewise, blockwise) {
                this.clear();
                this.keyBuffer = [text || ''];
                this.insertModeChanges = [];
                this.searchQueries = [];
                this.linewise = !!linewise;
                this.blockwise = !!blockwise;
              }
              Register.prototype = {
                setText: function(text, linewise, blockwise) {
                  this.keyBuffer = [text || ''];
                  this.linewise = !!linewise;
                  this.blockwise = !!blockwise;
                },
                pushText: function(text, linewise) {
                  // if this register has ever been set to linewise, use linewise.
                  if (linewise) {
                    if (!this.linewise) {
                      this.keyBuffer.push('\n');
                    }
                    this.linewise = true;
                  }
                  this.keyBuffer.push(text);
                },
                pushInsertModeChanges: function(changes) {
                  this.insertModeChanges.push(createInsertModeChanges(changes));
                },
                pushSearchQuery: function(query) {
                  this.searchQueries.push(query);
                },
                clear: function() {
                  this.keyBuffer = [];
                  this.insertModeChanges = [];
                  this.searchQueries = [];
                  this.linewise = false;
                },
                toString: function() {
                  return this.keyBuffer.join('');
                }
              };
          
              /*
               * vim registers allow you to keep many independent copy and paste buffers.
               * See http://usevim.com/2012/04/13/registers/ for an introduction.
               *
               * RegisterController keeps the state of all the registers.  An initial
               * state may be passed in.  The unnamed register '"' will always be
               * overridden.
               */
              function RegisterController(registers) {
                this.registers = registers;
                this.unnamedRegister = registers['"'] = new Register();
                registers['.'] = new Register();
                registers[':'] = new Register();
                registers['/'] = new Register();
              }
              RegisterController.prototype = {
                pushText: function(registerName, operator, text, linewise, blockwise) {
                  if (linewise && text.charAt(0) == '\n') {
                    text = text.slice(1) + '\n';
                  }
                  if (linewise && text.charAt(text.length - 1) !== '\n'){
                    text += '\n';
                  }
                  // Lowercase and uppercase registers refer to the same register.
                  // Uppercase just means append.
                  var register = this.isValidRegister(registerName) ?
                      this.getRegister(registerName) : null;
                  // if no register/an invalid register was specified, things go to the
                  // default registers
                  if (!register) {
                    switch (operator) {
                      case 'yank':
                        // The 0 register contains the text from the most recent yank.
                        this.registers['0'] = new Register(text, linewise, blockwise);
                        break;
                      case 'delete':
                      case 'change':
                        if (text.indexOf('\n') == -1) {
                          // Delete less than 1 line. Update the small delete register.
                          this.registers['-'] = new Register(text, linewise);
                        } else {
                          // Shift down the contents of the numbered registers and put the
                          // deleted text into register 1.
                          this.shiftNumericRegisters_();
                          this.registers['1'] = new Register(text, linewise);
                        }
                        break;
                    }
                    // Make sure the unnamed register is set to what just happened
                    this.unnamedRegister.setText(text, linewise, blockwise);
                    return;
                  }
          
                  // If we've gotten to this point, we've actually specified a register
                  var append = isUpperCase(registerName);
                  if (append) {
                    register.pushText(text, linewise);
                  } else {
                    register.setText(text, linewise, blockwise);
                  }
                  // The unnamed register always has the same value as the last used
                  // register.
                  this.unnamedRegister.setText(register.toString(), linewise);
                },
                // Gets the register named @name.  If one of @name doesn't already exist,
                // create it.  If @name is invalid, return the unnamedRegister.
                getRegister: function(name) {
                  if (!this.isValidRegister(name)) {
                    return this.unnamedRegister;
                  }
                  name = name.toLowerCase();
                  if (!this.registers[name]) {
                    this.registers[name] = new Register();
                  }
                  return this.registers[name];
                },
                isValidRegister: function(name) {
                  return name && inArray(name, validRegisters);
                },
                shiftNumericRegisters_: function() {
                  for (var i = 9; i >= 2; i--) {
                    this.registers[i] = this.getRegister('' + (i - 1));
                  }
                }
              };
              function HistoryController() {
                  this.historyBuffer = [];
                  this.iterator;
                  this.initialPrefix = null;
              }
              HistoryController.prototype = {
                // the input argument here acts a user entered prefix for a small time
                // until we start autocompletion in which case it is the autocompleted.
                nextMatch: function (input, up) {
                  var historyBuffer = this.historyBuffer;
                  var dir = up ? -1 : 1;
                  if (this.initialPrefix === null) this.initialPrefix = input;
                  for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) {
                    var element = historyBuffer[i];
                    for (var j = 0; j <= element.length; j++) {
                      if (this.initialPrefix == element.substring(0, j)) {
                        this.iterator = i;
                        return element;
                      }
                    }
                  }
                  // should return the user input in case we reach the end of buffer.
                  if (i >= historyBuffer.length) {
                    this.iterator = historyBuffer.length;
                    return this.initialPrefix;
                  }
                  // return the last autocompleted query or exCommand as it is.
                  if (i < 0 ) return input;
                },
                pushInput: function(input) {
                  var index = this.historyBuffer.indexOf(input);
                  if (index > -1) this.historyBuffer.splice(index, 1);
                  if (input.length) this.historyBuffer.push(input);
                },
                reset: function() {
                  this.initialPrefix = null;
                  this.iterator = this.historyBuffer.length;
                }
              };
              var commandDispatcher = {
                matchCommand: function(keys, keyMap, inputState, context) {
                  var matches = commandMatches(keys, keyMap, context, inputState);
                  if (!matches.full && !matches.partial) {
                    return {type: 'none'};
                  } else if (!matches.full && matches.partial) {
                    return {type: 'partial'};
                  }
          
                  var bestMatch;
                  for (var i = 0; i < matches.full.length; i++) {
                    var match = matches.full[i];
                    if (!bestMatch) {
                      bestMatch = match;
                    }
                  }
                  if (bestMatch.keys.slice(-11) == '<character>') {
                    inputState.selectedCharacter = lastChar(keys);
                  }
                  return {type: 'full', command: bestMatch};
                },
                processCommand: function(cm, vim, command) {
                  vim.inputState.repeatOverride = command.repeatOverride;
                  switch (command.type) {
                    case 'motion':
                      this.processMotion(cm, vim, command);
                      break;
                    case 'operator':
                      this.processOperator(cm, vim, command);
                      break;
                    case 'operatorMotion':
                      this.processOperatorMotion(cm, vim, command);
                      break;
                    case 'action':
                      this.processAction(cm, vim, command);
                      break;
                    case 'search':
                      this.processSearch(cm, vim, command);
                      clearInputState(cm);
                      break;
                    case 'ex':
                    case 'keyToEx':
                      this.processEx(cm, vim, command);
                      clearInputState(cm);
                      break;
                    default:
                      break;
                  }
                },
                processMotion: function(cm, vim, command) {
                  vim.inputState.motion = command.motion;
                  vim.inputState.motionArgs = copyArgs(command.motionArgs);
                  this.evalInput(cm, vim);
                },
                processOperator: function(cm, vim, command) {
                  var inputState = vim.inputState;
                  if (inputState.operator) {
                    if (inputState.operator == command.operator) {
                      // Typing an operator twice like 'dd' makes the operator operate
                      // linewise
                      inputState.motion = 'expandToLine';
                      inputState.motionArgs = { linewise: true };
                      this.evalInput(cm, vim);
                      return;
                    } else {
                      // 2 different operators in a row doesn't make sense.
                      clearInputState(cm);
                    }
                  }
                  inputState.operator = command.operator;
                  inputState.operatorArgs = copyArgs(command.operatorArgs);
                  if (vim.visualMode) {
                    // Operating on a selection in visual mode. We don't need a motion.
                    this.evalInput(cm, vim);
                  }
                },
                processOperatorMotion: function(cm, vim, command) {
                  var visualMode = vim.visualMode;
                  var operatorMotionArgs = copyArgs(command.operatorMotionArgs);
                  if (operatorMotionArgs) {
                    // Operator motions may have special behavior in visual mode.
                    if (visualMode && operatorMotionArgs.visualLine) {
                      vim.visualLine = true;
                    }
                  }
                  this.processOperator(cm, vim, command);
                  if (!visualMode) {
                    this.processMotion(cm, vim, command);
                  }
                },
                processAction: function(cm, vim, command) {
                  var inputState = vim.inputState;
                  var repeat = inputState.getRepeat();
                  var repeatIsExplicit = !!repeat;
                  var actionArgs = copyArgs(command.actionArgs) || {};
                  if (inputState.selectedCharacter) {
                    actionArgs.selectedCharacter = inputState.selectedCharacter;
                  }
                  // Actions may or may not have motions and operators. Do these first.
                  if (command.operator) {
                    this.processOperator(cm, vim, command);
                  }
                  if (command.motion) {
                    this.processMotion(cm, vim, command);
                  }
                  if (command.motion || command.operator) {
                    this.evalInput(cm, vim);
                  }
                  actionArgs.repeat = repeat || 1;
                  actionArgs.repeatIsExplicit = repeatIsExplicit;
                  actionArgs.registerName = inputState.registerName;
                  clearInputState(cm);
                  vim.lastMotion = null;
                  if (command.isEdit) {
                    this.recordLastEdit(vim, inputState, command);
                  }
                  actions[command.action](cm, actionArgs, vim);
                },
                processSearch: function(cm, vim, command) {
                  if (!cm.getSearchCursor) {
                    // Search depends on SearchCursor.
                    return;
                  }
                  var forward = command.searchArgs.forward;
                  var wholeWordOnly = command.searchArgs.wholeWordOnly;
                  getSearchState(cm).setReversed(!forward);
                  var promptPrefix = (forward) ? '/' : '?';
                  var originalQuery = getSearchState(cm).getQuery();
                  var originalScrollPos = cm.getScrollInfo();
                  function handleQuery(query, ignoreCase, smartCase) {
                    vimGlobalState.searchHistoryController.pushInput(query);
                    vimGlobalState.searchHistoryController.reset();
                    try {
                      updateSearchQuery(cm, query, ignoreCase, smartCase);
                    } catch (e) {
                      showConfirm(cm, 'Invalid regex: ' + query);
                      return;
                    }
                    commandDispatcher.processMotion(cm, vim, {
                      type: 'motion',
                      motion: 'findNext',
                      motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist }
                    });
                  }
                  function onPromptClose(query) {
                    cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
                    handleQuery(query, true /** ignoreCase */, true /** smartCase */);
                    var macroModeState = vimGlobalState.macroModeState;
                    if (macroModeState.isRecording) {
                      logSearchQuery(macroModeState, query);
                    }
                  }
                  function onPromptKeyUp(e, query, close) {
                    var keyName = CodeMirror.keyName(e), up;
                    if (keyName == 'Up' || keyName == 'Down') {
                      up = keyName == 'Up' ? true : false;
                      query = vimGlobalState.searchHistoryController.nextMatch(query, up) || '';
                      close(query);
                    } else {
                      if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
                        vimGlobalState.searchHistoryController.reset();
                    }
                    var parsedQuery;
                    try {
                      parsedQuery = updateSearchQuery(cm, query,
                          true /** ignoreCase */, true /** smartCase */);
                    } catch (e) {
                      // Swallow bad regexes for incremental search.
                    }
                    if (parsedQuery) {
                      cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30);
                    } else {
                      clearSearchHighlight(cm);
                      cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
                    }
                  }
                  function onPromptKeyDown(e, query, close) {
                    var keyName = CodeMirror.keyName(e);
                    if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
                      vimGlobalState.searchHistoryController.pushInput(query);
                      vimGlobalState.searchHistoryController.reset();
                      updateSearchQuery(cm, originalQuery);
                      clearSearchHighlight(cm);
                      cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
                      CodeMirror.e_stop(e);
                      close();
                      cm.focus();
                    }
                  }
                  switch (command.searchArgs.querySrc) {
                    case 'prompt':
                      var macroModeState = vimGlobalState.macroModeState;
                      if (macroModeState.isPlaying) {
                        var query = macroModeState.replaySearchQueries.shift();
                        handleQuery(query, true /** ignoreCase */, false /** smartCase */);
                      } else {
                        showPrompt(cm, {
                            onClose: onPromptClose,
                            prefix: promptPrefix,
                            desc: searchPromptDesc,
                            onKeyUp: onPromptKeyUp,
                            onKeyDown: onPromptKeyDown
                        });
                      }
                      break;
                    case 'wordUnderCursor':
                      var word = expandWordUnderCursor(cm, false /** inclusive */,
                          true /** forward */, false /** bigWord */,
                          true /** noSymbol */);
                      var isKeyword = true;
                      if (!word) {
                        word = expandWordUnderCursor(cm, false /** inclusive */,
                            true /** forward */, false /** bigWord */,
                            false /** noSymbol */);
                        isKeyword = false;
                      }
                      if (!word) {
                        return;
                      }
                      var query = cm.getLine(word.start.line).substring(word.start.ch,
                          word.end.ch);
                      if (isKeyword && wholeWordOnly) {
                          query = '\\b' + query + '\\b';
                      } else {
                        query = escapeRegex(query);
                      }
          
                      // cachedCursor is used to save the old position of the cursor
                      // when * or # causes vim to seek for the nearest word and shift
                      // the cursor before entering the motion.
                      vimGlobalState.jumpList.cachedCursor = cm.getCursor();
                      cm.setCursor(word.start);
          
                      handleQuery(query, true /** ignoreCase */, false /** smartCase */);
                      break;
                  }
                },
                processEx: function(cm, vim, command) {
                  function onPromptClose(input) {
                    // Give the prompt some time to close so that if processCommand shows
                    // an error, the elements don't overlap.
                    vimGlobalState.exCommandHistoryController.pushInput(input);
                    vimGlobalState.exCommandHistoryController.reset();
                    exCommandDispatcher.processCommand(cm, input);
                  }
                  function onPromptKeyDown(e, input, close) {
                    var keyName = CodeMirror.keyName(e), up;
                    if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
                      vimGlobalState.exCommandHistoryController.pushInput(input);
                      vimGlobalState.exCommandHistoryController.reset();
                      CodeMirror.e_stop(e);
                      close();
                      cm.focus();
                    }
                    if (keyName == 'Up' || keyName == 'Down') {
                      up = keyName == 'Up' ? true : false;
                      input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
                      close(input);
                    } else {
                      if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
                        vimGlobalState.exCommandHistoryController.reset();
                    }
                  }
                  if (command.type == 'keyToEx') {
                    // Handle user defined Ex to Ex mappings
                    exCommandDispatcher.processCommand(cm, command.exArgs.input);
                  } else {
                    if (vim.visualMode) {
                      showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
                          onKeyDown: onPromptKeyDown});
                    } else {
                      showPrompt(cm, { onClose: onPromptClose, prefix: ':',
                          onKeyDown: onPromptKeyDown});
                    }
                  }
                },
                evalInput: function(cm, vim) {
                  // If the motion comand is set, execute both the operator and motion.
                  // Otherwise return.
                  var inputState = vim.inputState;
                  var motion = inputState.motion;
                  var motionArgs = inputState.motionArgs || {};
                  var operator = inputState.operator;
                  var operatorArgs = inputState.operatorArgs || {};
                  var registerName = inputState.registerName;
                  var sel = vim.sel;
                  // TODO: Make sure cm and vim selections are identical outside visual mode.
                  var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head'));
                  var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor'));
                  var oldHead = copyCursor(origHead);
                  var oldAnchor = copyCursor(origAnchor);
                  var newHead, newAnchor;
                  var repeat;
                  if (operator) {
                    this.recordLastEdit(vim, inputState);
                  }
                  if (inputState.repeatOverride !== undefined) {
                    // If repeatOverride is specified, that takes precedence over the
                    // input state's repeat. Used by Ex mode and can be user defined.
                    repeat = inputState.repeatOverride;
                  } else {
                    repeat = inputState.getRepeat();
                  }
                  if (repeat > 0 && motionArgs.explicitRepeat) {
                    motionArgs.repeatIsExplicit = true;
                  } else if (motionArgs.noRepeat ||
                      (!motionArgs.explicitRepeat && repeat === 0)) {
                    repeat = 1;
                    motionArgs.repeatIsExplicit = false;
                  }
                  if (inputState.selectedCharacter) {
                    // If there is a character input, stick it in all of the arg arrays.
                    motionArgs.selectedCharacter = operatorArgs.selectedCharacter =
                        inputState.selectedCharacter;
                  }
                  motionArgs.repeat = repeat;
                  clearInputState(cm);
                  if (motion) {
                    var motionResult = motions[motion](cm, origHead, motionArgs, vim);
                    vim.lastMotion = motions[motion];
                    if (!motionResult) {
                      return;
                    }
                    if (motionArgs.toJumplist) {
                      var jumpList = vimGlobalState.jumpList;
                      // if the current motion is # or *, use cachedCursor
                      var cachedCursor = jumpList.cachedCursor;
                      if (cachedCursor) {
                        recordJumpPosition(cm, cachedCursor, motionResult);
                        delete jumpList.cachedCursor;
                      } else {
                        recordJumpPosition(cm, origHead, motionResult);
                      }
                    }
                    if (motionResult instanceof Array) {
                      newAnchor = motionResult[0];
                      newHead = motionResult[1];
                    } else {
                      newHead = motionResult;
                    }
                    // TODO: Handle null returns from motion commands better.
                    if (!newHead) {
                      newHead = copyCursor(origHead);
                    }
                    if (vim.visualMode) {
                      if (!(vim.visualBlock && newHead.ch === Infinity)) {
                        newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
                      }
                      if (newAnchor) {
                        newAnchor = clipCursorToContent(cm, newAnchor, true);
                      }
                      newAnchor = newAnchor || oldAnchor;
                      sel.anchor = newAnchor;
                      sel.head = newHead;
                      updateCmSelection(cm);
                      updateMark(cm, vim, '<',
                          cursorIsBefore(newAnchor, newHead) ? newAnchor
                              : newHead);
                      updateMark(cm, vim, '>',
                          cursorIsBefore(newAnchor, newHead) ? newHead
                              : newAnchor);
                    } else if (!operator) {
                      newHead = clipCursorToContent(cm, newHead);
                      cm.setCursor(newHead.line, newHead.ch);
                    }
                  }
                  if (operator) {
                    if (operatorArgs.lastSel) {
                      // Replaying a visual mode operation
                      newAnchor = oldAnchor;
                      var lastSel = operatorArgs.lastSel;
                      var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line);
                      var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch);
                      if (lastSel.visualLine) {
                        // Linewise Visual mode: The same number of lines.
                        newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
                      } else if (lastSel.visualBlock) {
                        // Blockwise Visual mode: The same number of lines and columns.
                        newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset);
                      } else if (lastSel.head.line == lastSel.anchor.line) {
                        // Normal Visual mode within one line: The same number of characters.
                        newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset);
                      } else {
                        // Normal Visual mode with several lines: The same number of lines, in the
                        // last line the same number of characters as in the last line the last time.
                        newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
                      }
                      vim.visualMode = true;
                      vim.visualLine = lastSel.visualLine;
                      vim.visualBlock = lastSel.visualBlock;
                      sel = vim.sel = {
                        anchor: newAnchor,
                        head: newHead
                      };
                      updateCmSelection(cm);
                    } else if (vim.visualMode) {
                      operatorArgs.lastSel = {
                        anchor: copyCursor(sel.anchor),
                        head: copyCursor(sel.head),
                        visualBlock: vim.visualBlock,
                        visualLine: vim.visualLine
                      };
                    }
                    var curStart, curEnd, linewise, mode;
                    var cmSel;
                    if (vim.visualMode) {
                      // Init visual op
                      curStart = cursorMin(sel.head, sel.anchor);
                      curEnd = cursorMax(sel.head, sel.anchor);
                      linewise = vim.visualLine || operatorArgs.linewise;
                      mode = vim.visualBlock ? 'block' :
                             linewise ? 'line' :
                             'char';
                      cmSel = makeCmSelection(cm, {
                        anchor: curStart,
                        head: curEnd
                      }, mode);
                      if (linewise) {
                        var ranges = cmSel.ranges;
                        if (mode == 'block') {
                          // Linewise operators in visual block mode extend to end of line
                          for (var i = 0; i < ranges.length; i++) {
                            ranges[i].head.ch = lineLength(cm, ranges[i].head.line);
                          }
                        } else if (mode == 'line') {
                          ranges[0].head = Pos(ranges[0].head.line + 1, 0);
                        }
                      }
                    } else {
                      // Init motion op
                      curStart = copyCursor(newAnchor || oldAnchor);
                      curEnd = copyCursor(newHead || oldHead);
                      if (cursorIsBefore(curEnd, curStart)) {
                        var tmp = curStart;
                        curStart = curEnd;
                        curEnd = tmp;
                      }
                      linewise = motionArgs.linewise || operatorArgs.linewise;
                      if (linewise) {
                        // Expand selection to entire line.
                        expandSelectionToLine(cm, curStart, curEnd);
                      } else if (motionArgs.forward) {
                        // Clip to trailing newlines only if the motion goes forward.
                        clipToLine(cm, curStart, curEnd);
                      }
                      mode = 'char';
                      var exclusive = !motionArgs.inclusive || linewise;
                      cmSel = makeCmSelection(cm, {
                        anchor: curStart,
                        head: curEnd
                      }, mode, exclusive);
                    }
                    cm.setSelections(cmSel.ranges, cmSel.primary);
                    vim.lastMotion = null;
                    operatorArgs.repeat = repeat; // For indent in visual mode.
                    operatorArgs.registerName = registerName;
                    // Keep track of linewise as it affects how paste and change behave.
                    operatorArgs.linewise = linewise;
                    var operatorMoveTo = operators[operator](
                      cm, operatorArgs, cmSel.ranges, oldAnchor, newHead);
                    if (vim.visualMode) {
                      exitVisualMode(cm, operatorMoveTo != null);
                    }
                    if (operatorMoveTo) {
                      cm.setCursor(operatorMoveTo);
                    }
                  }
                },
                recordLastEdit: function(vim, inputState, actionCommand) {
                  var macroModeState = vimGlobalState.macroModeState;
                  if (macroModeState.isPlaying) { return; }
                  vim.lastEditInputState = inputState;
                  vim.lastEditActionCommand = actionCommand;
                  macroModeState.lastInsertModeChanges.changes = [];
                  macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false;
                }
              };
          
              /**
               * typedef {Object{line:number,ch:number}} Cursor An object containing the
               *     position of the cursor.
               */
              // All of the functions below return Cursor objects.
              var motions = {
                moveToTopLine: function(cm, _head, motionArgs) {
                  var line = getUserVisibleLines(cm).top + motionArgs.repeat -1;
                  return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
                },
                moveToMiddleLine: function(cm) {
                  var range = getUserVisibleLines(cm);
                  var line = Math.floor((range.top + range.bottom) * 0.5);
                  return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
                },
                moveToBottomLine: function(cm, _head, motionArgs) {
                  var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1;
                  return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
                },
                expandToLine: function(_cm, head, motionArgs) {
                  // Expands forward to end of line, and then to next line if repeat is
                  // >1. Does not handle backward motion!
                  var cur = head;
                  return Pos(cur.line + motionArgs.repeat - 1, Infinity);
                },
                findNext: function(cm, _head, motionArgs) {
                  var state = getSearchState(cm);
                  var query = state.getQuery();
                  if (!query) {
                    return;
                  }
                  var prev = !motionArgs.forward;
                  // If search is initiated with ? instead of /, negate direction.
                  prev = (state.isReversed()) ? !prev : prev;
                  highlightSearchMatches(cm, query);
                  return findNext(cm, prev/** prev */, query, motionArgs.repeat);
                },
                goToMark: function(cm, _head, motionArgs, vim) {
                  var mark = vim.marks[motionArgs.selectedCharacter];
                  if (mark) {
                    var pos = mark.find();
                    return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
                  }
                  return null;
                },
                moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) {
                  if (vim.visualBlock && motionArgs.sameLine) {
                    var sel = vim.sel;
                    return [
                      clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)),
                      clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))
                    ];
                  } else {
                    return ([vim.sel.head, vim.sel.anchor]);
                  }
                },
                jumpToMark: function(cm, head, motionArgs, vim) {
                  var best = head;
                  for (var i = 0; i < motionArgs.repeat; i++) {
                    var cursor = best;
                    for (var key in vim.marks) {
                      if (!isLowerCase(key)) {
                        continue;
                      }
                      var mark = vim.marks[key].find();
                      var isWrongDirection = (motionArgs.forward) ?
                        cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark);
          
                      if (isWrongDirection) {
                        continue;
                      }
                      if (motionArgs.linewise && (mark.line == cursor.line)) {
                        continue;
                      }
          
                      var equal = cursorEqual(cursor, best);
                      var between = (motionArgs.forward) ?
                        cursorIsBetween(cursor, mark, best) :
                        cursorIsBetween(best, mark, cursor);
          
                      if (equal || between) {
                        best = mark;
                      }
                    }
                  }
          
                  if (motionArgs.linewise) {
                    // Vim places the cursor on the first non-whitespace character of
                    // the line if there is one, else it places the cursor at the end
                    // of the line, regardless of whether a mark was found.
                    best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)));
                  }
                  return best;
                },
                moveByCharacters: function(_cm, head, motionArgs) {
                  var cur = head;
                  var repeat = motionArgs.repeat;
                  var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat;
                  return Pos(cur.line, ch);
                },
                moveByLines: function(cm, head, motionArgs, vim) {
                  var cur = head;
                  var endCh = cur.ch;
                  // Depending what our last motion was, we may want to do different
                  // things. If our last motion was moving vertically, we want to
                  // preserve the HPos from our last horizontal move.  If our last motion
                  // was going to the end of a line, moving vertically we should go to
                  // the end of the line, etc.
                  switch (vim.lastMotion) {
                    case this.moveByLines:
                    case this.moveByDisplayLines:
                    case this.moveByScroll:
                    case this.moveToColumn:
                    case this.moveToEol:
                      endCh = vim.lastHPos;
                      break;
                    default:
                      vim.lastHPos = endCh;
                  }
                  var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0);
                  var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat;
                  var first = cm.firstLine();
                  var last = cm.lastLine();
                  // Vim cancels linewise motions that start on an edge and move beyond
                  // that edge. It does not cancel motions that do not start on an edge.
                  if ((line < first && cur.line == first) ||
                      (line > last && cur.line == last)) {
                    return;
                  }
                  if (motionArgs.toFirstChar){
                    endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
                    vim.lastHPos = endCh;
                  }
                  vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left;
                  return Pos(line, endCh);
                },
                moveByDisplayLines: function(cm, head, motionArgs, vim) {
                  var cur = head;
                  switch (vim.lastMotion) {
                    case this.moveByDisplayLines:
                    case this.moveByScroll:
                    case this.moveByLines:
                    case this.moveToColumn:
                    case this.moveToEol:
                      break;
                    default:
                      vim.lastHSPos = cm.charCoords(cur,'div').left;
                  }
                  var repeat = motionArgs.repeat;
                  var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos);
                  if (res.hitSide) {
                    if (motionArgs.forward) {
                      var lastCharCoords = cm.charCoords(res, 'div');
                      var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos };
                      var res = cm.coordsChar(goalCoords, 'div');
                    } else {
                      var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div');
                      resCoords.left = vim.lastHSPos;
                      res = cm.coordsChar(resCoords, 'div');
                    }
                  }
                  vim.lastHPos = res.ch;
                  return res;
                },
                moveByPage: function(cm, head, motionArgs) {
                  // CodeMirror only exposes functions that move the cursor page down, so
                  // doing this bad hack to move the cursor and move it back. evalInput
                  // will move the cursor to where it should be in the end.
                  var curStart = head;
                  var repeat = motionArgs.repeat;
                  return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page');
                },
                moveByParagraph: function(cm, head, motionArgs) {
                  var dir = motionArgs.forward ? 1 : -1;
                  return findParagraph(cm, head, motionArgs.repeat, dir);
                },
                moveByScroll: function(cm, head, motionArgs, vim) {
                  var scrollbox = cm.getScrollInfo();
                  var curEnd = null;
                  var repeat = motionArgs.repeat;
                  if (!repeat) {
                    repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight());
                  }
                  var orig = cm.charCoords(head, 'local');
                  motionArgs.repeat = repeat;
                  var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim);
                  if (!curEnd) {
                    return null;
                  }
                  var dest = cm.charCoords(curEnd, 'local');
                  cm.scrollTo(null, scrollbox.top + dest.top - orig.top);
                  return curEnd;
                },
                moveByWords: function(cm, head, motionArgs) {
                  return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward,
                      !!motionArgs.wordEnd, !!motionArgs.bigWord);
                },
                moveTillCharacter: function(cm, _head, motionArgs) {
                  var repeat = motionArgs.repeat;
                  var curEnd = moveToCharacter(cm, repeat, motionArgs.forward,
                      motionArgs.selectedCharacter);
                  var increment = motionArgs.forward ? -1 : 1;
                  recordLastCharacterSearch(increment, motionArgs);
                  if (!curEnd) return null;
                  curEnd.ch += increment;
                  return curEnd;
                },
                moveToCharacter: function(cm, head, motionArgs) {
                  var repeat = motionArgs.repeat;
                  recordLastCharacterSearch(0, motionArgs);
                  return moveToCharacter(cm, repeat, motionArgs.forward,
                      motionArgs.selectedCharacter) || head;
                },
                moveToSymbol: function(cm, head, motionArgs) {
                  var repeat = motionArgs.repeat;
                  return findSymbol(cm, repeat, motionArgs.forward,
                      motionArgs.selectedCharacter) || head;
                },
                moveToColumn: function(cm, head, motionArgs, vim) {
                  var repeat = motionArgs.repeat;
                  // repeat is equivalent to which column we want to move to!
                  vim.lastHPos = repeat - 1;
                  vim.lastHSPos = cm.charCoords(head,'div').left;
                  return moveToColumn(cm, repeat);
                },
                moveToEol: function(cm, head, motionArgs, vim) {
                  var cur = head;
                  vim.lastHPos = Infinity;
                  var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);
                  var end=cm.clipPos(retval);
                  end.ch--;
                  vim.lastHSPos = cm.charCoords(end,'div').left;
                  return retval;
                },
                moveToFirstNonWhiteSpaceCharacter: function(cm, head) {
                  // Go to the start of the line where the text begins, or the end for
                  // whitespace-only lines
                  var cursor = head;
                  return Pos(cursor.line,
                             findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)));
                },
                moveToMatchedSymbol: function(cm, head) {
                  var cursor = head;
                  var line = cursor.line;
                  var ch = cursor.ch;
                  var lineText = cm.getLine(line);
                  var symbol;
                  do {
                    symbol = lineText.charAt(ch++);
                    if (symbol && isMatchableSymbol(symbol)) {
                      var style = cm.getTokenTypeAt(Pos(line, ch));
                      if (style !== "string" && style !== "comment") {
                        break;
                      }
                    }
                  } while (symbol);
                  if (symbol) {
                    var matched = cm.findMatchingBracket(Pos(line, ch));
                    return matched.to;
                  } else {
                    return cursor;
                  }
                },
                moveToStartOfLine: function(_cm, head) {
                  return Pos(head.line, 0);
                },
                moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) {
                  var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine();
                  if (motionArgs.repeatIsExplicit) {
                    lineNum = motionArgs.repeat - cm.getOption('firstLineNumber');
                  }
                  return Pos(lineNum,
                             findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)));
                },
                textObjectManipulation: function(cm, head, motionArgs, vim) {
                  // TODO: lots of possible exceptions that can be thrown here. Try da(
                  //     outside of a () block.
          
                  // TODO: adding <> >< to this map doesn't work, presumably because
                  // they're operators
                  var mirroredPairs = {'(': ')', ')': '(',
                                       '{': '}', '}': '{',
                                       '[': ']', ']': '['};
                  var selfPaired = {'\'': true, '"': true};
          
                  var character = motionArgs.selectedCharacter;
                  // 'b' refers to  '()' block.
                  // 'B' refers to  '{}' block.
                  if (character == 'b') {
                    character = '(';
                  } else if (character == 'B') {
                    character = '{';
                  }
          
                  // Inclusive is the difference between a and i
                  // TODO: Instead of using the additional text object map to perform text
                  //     object operations, merge the map into the defaultKeyMap and use
                  //     motionArgs to define behavior. Define separate entries for 'aw',
                  //     'iw', 'a[', 'i[', etc.
                  var inclusive = !motionArgs.textObjectInner;
          
                  var tmp;
                  if (mirroredPairs[character]) {
                    tmp = selectCompanionObject(cm, head, character, inclusive);
                  } else if (selfPaired[character]) {
                    tmp = findBeginningAndEnd(cm, head, character, inclusive);
                  } else if (character === 'W') {
                    tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
                                                               true /** bigWord */);
                  } else if (character === 'w') {
                    tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
                                                               false /** bigWord */);
                  } else if (character === 'p') {
                    tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);
                    motionArgs.linewise = true;
                    if (vim.visualMode) {
                      if (!vim.visualLine) { vim.visualLine = true; }
                    } else {
                      var operatorArgs = vim.inputState.operatorArgs;
                      if (operatorArgs) { operatorArgs.linewise = true; }
                      tmp.end.line--;
                    }
                  } else {
                    // No text object defined for this, don't move.
                    return null;
                  }
          
                  if (!cm.state.vim.visualMode) {
                    return [tmp.start, tmp.end];
                  } else {
                    return expandSelection(cm, tmp.start, tmp.end);
                  }
                },
          
                repeatLastCharacterSearch: function(cm, head, motionArgs) {
                  var lastSearch = vimGlobalState.lastChararacterSearch;
                  var repeat = motionArgs.repeat;
                  var forward = motionArgs.forward === lastSearch.forward;
                  var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
                  cm.moveH(-increment, 'char');
                  motionArgs.inclusive = forward ? true : false;
                  var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter);
                  if (!curEnd) {
                    cm.moveH(increment, 'char');
                    return head;
                  }
                  curEnd.ch += increment;
                  return curEnd;
                }
              };
          
              function defineMotion(name, fn) {
                motions[name] = fn;
              }
          
              function fillArray(val, times) {
                var arr = [];
                for (var i = 0; i < times; i++) {
                  arr.push(val);
                }
                return arr;
              }
              /**
               * An operator acts on a text selection. It receives the list of selections
               * as input. The corresponding CodeMirror selection is guaranteed to
              * match the input selection.
               */
              var operators = {
                change: function(cm, args, ranges) {
                  var finalHead, text;
                  var vim = cm.state.vim;
                  vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock;
                  if (!vim.visualMode) {
                    var anchor = ranges[0].anchor,
                        head = ranges[0].head;
                    text = cm.getRange(anchor, head);
                    if (!isWhiteSpaceString(text)) {
                      // Exclude trailing whitespace if the range is not all whitespace.
                      var match = (/\s+$/).exec(text);
                      if (match) {
                        head = offsetCursor(head, 0, - match[0].length);
                        text = text.slice(0, - match[0].length);
                      }
                    }
                    var wasLastLine = head.line - 1 == cm.lastLine();
                    cm.replaceRange('', anchor, head);
                    if (args.linewise && !wasLastLine) {
                      // Push the next line back down, if there is a next line.
                      CodeMirror.commands.newlineAndIndent(cm);
                      // null ch so setCursor moves to end of line.
                      anchor.ch = null;
                    }
                    finalHead = anchor;
                  } else {
                    text = cm.getSelection();
                    var replacement = fillArray('', ranges.length);
                    cm.replaceSelections(replacement);
                    finalHead = cursorMin(ranges[0].head, ranges[0].anchor);
                  }
                  vimGlobalState.registerController.pushText(
                      args.registerName, 'change', text,
                      args.linewise, ranges.length > 1);
                  actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim);
                },
                // delete is a javascript keyword.
                'delete': function(cm, args, ranges) {
                  var finalHead, text;
                  var vim = cm.state.vim;
                  if (!vim.visualBlock) {
                    var anchor = ranges[0].anchor,
                        head = ranges[0].head;
                    if (args.linewise &&
                        head.line != cm.firstLine() &&
                        anchor.line == cm.lastLine() &&
                        anchor.line == head.line - 1) {
                      // Special case for dd on last line (and first line).
                      if (anchor.line == cm.firstLine()) {
                        anchor.ch = 0;
                      } else {
                        anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1));
                      }
                    }
                    text = cm.getRange(anchor, head);
                    cm.replaceRange('', anchor, head);
                    finalHead = anchor;
                    if (args.linewise) {
                      finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor);
                    }
                  } else {
                    text = cm.getSelection();
                    var replacement = fillArray('', ranges.length);
                    cm.replaceSelections(replacement);
                    finalHead = ranges[0].anchor;
                  }
                  vimGlobalState.registerController.pushText(
                      args.registerName, 'delete', text,
                      args.linewise, vim.visualBlock);
                  return clipCursorToContent(cm, finalHead);
                },
                indent: function(cm, args, ranges) {
                  var vim = cm.state.vim;
                  var startLine = ranges[0].anchor.line;
                  var endLine = vim.visualBlock ?
                    ranges[ranges.length - 1].anchor.line :
                    ranges[0].head.line;
                  // In visual mode, n> shifts the selection right n times, instead of
                  // shifting n lines right once.
                  var repeat = (vim.visualMode) ? args.repeat : 1;
                  if (args.linewise) {
                    // The only way to delete a newline is to delete until the start of
                    // the next line, so in linewise mode evalInput will include the next
                    // line. We don't want this in indent, so we go back a line.
                    endLine--;
                  }
                  for (var i = startLine; i <= endLine; i++) {
                    for (var j = 0; j < repeat; j++) {
                      cm.indentLine(i, args.indentRight);
                    }
                  }
                  return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);
                },
                changeCase: function(cm, args, ranges, oldAnchor, newHead) {
                  var selections = cm.getSelections();
                  var swapped = [];
                  var toLower = args.toLower;
                  for (var j = 0; j < selections.length; j++) {
                    var toSwap = selections[j];
                    var text = '';
                    if (toLower === true) {
                      text = toSwap.toLowerCase();
                    } else if (toLower === false) {
                      text = toSwap.toUpperCase();
                    } else {
                      for (var i = 0; i < toSwap.length; i++) {
                        var character = toSwap.charAt(i);
                        text += isUpperCase(character) ? character.toLowerCase() :
                            character.toUpperCase();
                      }
                    }
                    swapped.push(text);
                  }
                  cm.replaceSelections(swapped);
                  if (args.shouldMoveCursor){
                    return newHead;
                  } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {
                    return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);
                  } else if (args.linewise){
                    return oldAnchor;
                  } else {
                    return cursorMin(ranges[0].anchor, ranges[0].head);
                  }
                },
                yank: function(cm, args, ranges, oldAnchor) {
                  var vim = cm.state.vim;
                  var text = cm.getSelection();
                  var endPos = vim.visualMode
                    ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor)
                    : oldAnchor;
                  vimGlobalState.registerController.pushText(
                      args.registerName, 'yank',
                      text, args.linewise, vim.visualBlock);
                  return endPos;
                }
              };
          
              function defineOperator(name, fn) {
                operators[name] = fn;
              }
          
              var actions = {
                jumpListWalk: function(cm, actionArgs, vim) {
                  if (vim.visualMode) {
                    return;
                  }
                  var repeat = actionArgs.repeat;
                  var forward = actionArgs.forward;
                  var jumpList = vimGlobalState.jumpList;
          
                  var mark = jumpList.move(cm, forward ? repeat : -repeat);
                  var markPos = mark ? mark.find() : undefined;
                  markPos = markPos ? markPos : cm.getCursor();
                  cm.setCursor(markPos);
                },
                scroll: function(cm, actionArgs, vim) {
                  if (vim.visualMode) {
                    return;
                  }
                  var repeat = actionArgs.repeat || 1;
                  var lineHeight = cm.defaultTextHeight();
                  var top = cm.getScrollInfo().top;
                  var delta = lineHeight * repeat;
                  var newPos = actionArgs.forward ? top + delta : top - delta;
                  var cursor = copyCursor(cm.getCursor());
                  var cursorCoords = cm.charCoords(cursor, 'local');
                  if (actionArgs.forward) {
                    if (newPos > cursorCoords.top) {
                       cursor.line += (newPos - cursorCoords.top) / lineHeight;
                       cursor.line = Math.ceil(cursor.line);
                       cm.setCursor(cursor);
                       cursorCoords = cm.charCoords(cursor, 'local');
                       cm.scrollTo(null, cursorCoords.top);
                    } else {
                       // Cursor stays within bounds.  Just reposition the scroll window.
                       cm.scrollTo(null, newPos);
                    }
                  } else {
                    var newBottom = newPos + cm.getScrollInfo().clientHeight;
                    if (newBottom < cursorCoords.bottom) {
                       cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight;
                       cursor.line = Math.floor(cursor.line);
                       cm.setCursor(cursor);
                       cursorCoords = cm.charCoords(cursor, 'local');
                       cm.scrollTo(
                           null, cursorCoords.bottom - cm.getScrollInfo().clientHeight);
                    } else {
                       // Cursor stays within bounds.  Just reposition the scroll window.
                       cm.scrollTo(null, newPos);
                    }
                  }
                },
                scrollToCursor: function(cm, actionArgs) {
                  var lineNum = cm.getCursor().line;
                  var charCoords = cm.charCoords(Pos(lineNum, 0), 'local');
                  var height = cm.getScrollInfo().clientHeight;
                  var y = charCoords.top;
                  var lineHeight = charCoords.bottom - y;
                  switch (actionArgs.position) {
                    case 'center': y = y - (height / 2) + lineHeight;
                      break;
                    case 'bottom': y = y - height + lineHeight*1.4;
                      break;
                    case 'top': y = y + lineHeight*0.4;
                      break;
                  }
                  cm.scrollTo(null, y);
                },
                replayMacro: function(cm, actionArgs, vim) {
                  var registerName = actionArgs.selectedCharacter;
                  var repeat = actionArgs.repeat;
                  var macroModeState = vimGlobalState.macroModeState;
                  if (registerName == '@') {
                    registerName = macroModeState.latestRegister;
                  }
                  while(repeat--){
                    executeMacroRegister(cm, vim, macroModeState, registerName);
                  }
                },
                enterMacroRecordMode: function(cm, actionArgs) {
                  var macroModeState = vimGlobalState.macroModeState;
                  var registerName = actionArgs.selectedCharacter;
                  macroModeState.enterMacroRecordMode(cm, registerName);
                },
                enterInsertMode: function(cm, actionArgs, vim) {
                  if (cm.getOption('readOnly')) { return; }
                  vim.insertMode = true;
                  vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
                  var insertAt = (actionArgs) ? actionArgs.insertAt : null;
                  var sel = vim.sel;
                  var head = actionArgs.head || cm.getCursor('head');
                  var height = cm.listSelections().length;
                  if (insertAt == 'eol') {
                    head = Pos(head.line, lineLength(cm, head.line));
                  } else if (insertAt == 'charAfter') {
                    head = offsetCursor(head, 0, 1);
                  } else if (insertAt == 'firstNonBlank') {
                    head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head);
                  } else if (insertAt == 'startOfSelectedArea') {
                    if (!vim.visualBlock) {
                      if (sel.head.line < sel.anchor.line) {
                        head = sel.head;
                      } else {
                        head = Pos(sel.anchor.line, 0);
                      }
                    } else {
                      head = Pos(
                          Math.min(sel.head.line, sel.anchor.line),
                          Math.min(sel.head.ch, sel.anchor.ch));
                      height = Math.abs(sel.head.line - sel.anchor.line) + 1;
                    }
                  } else if (insertAt == 'endOfSelectedArea') {
                    if (!vim.visualBlock) {
                      if (sel.head.line >= sel.anchor.line) {
                        head = offsetCursor(sel.head, 0, 1);
                      } else {
                        head = Pos(sel.anchor.line, 0);
                      }
                    } else {
                      head = Pos(
                          Math.min(sel.head.line, sel.anchor.line),
                          Math.max(sel.head.ch + 1, sel.anchor.ch));
                      height = Math.abs(sel.head.line - sel.anchor.line) + 1;
                    }
                  } else if (insertAt == 'inplace') {
                    if (vim.visualMode){
                      return;
                    }
                  }
                  cm.setOption('keyMap', 'vim-insert');
                  cm.setOption('disableInput', false);
                  if (actionArgs && actionArgs.replace) {
                    // Handle Replace-mode as a special case of insert mode.
                    cm.toggleOverwrite(true);
                    cm.setOption('keyMap', 'vim-replace');
                    CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
                  } else {
                    cm.setOption('keyMap', 'vim-insert');
                    CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
                  }
                  if (!vimGlobalState.macroModeState.isPlaying) {
                    // Only record if not replaying.
                    cm.on('change', onChange);
                    CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
                  }
                  if (vim.visualMode) {
                    exitVisualMode(cm);
                  }
                  selectForInsert(cm, head, height);
                },
                toggleVisualMode: function(cm, actionArgs, vim) {
                  var repeat = actionArgs.repeat;
                  var anchor = cm.getCursor();
                  var head;
                  // TODO: The repeat should actually select number of characters/lines
                  //     equal to the repeat times the size of the previous visual
                  //     operation.
                  if (!vim.visualMode) {
                    // Entering visual mode
                    vim.visualMode = true;
                    vim.visualLine = !!actionArgs.linewise;
                    vim.visualBlock = !!actionArgs.blockwise;
                    head = clipCursorToContent(
                        cm, Pos(anchor.line, anchor.ch + repeat - 1),
                        true /** includeLineBreak */);
                    vim.sel = {
                      anchor: anchor,
                      head: head
                    };
                    CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
                    updateCmSelection(cm);
                    updateMark(cm, vim, '<', cursorMin(anchor, head));
                    updateMark(cm, vim, '>', cursorMax(anchor, head));
                  } else if (vim.visualLine ^ actionArgs.linewise ||
                      vim.visualBlock ^ actionArgs.blockwise) {
                    // Toggling between modes
                    vim.visualLine = !!actionArgs.linewise;
                    vim.visualBlock = !!actionArgs.blockwise;
                    CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
                    updateCmSelection(cm);
                  } else {
                    exitVisualMode(cm);
                  }
                },
                reselectLastSelection: function(cm, _actionArgs, vim) {
                  var lastSelection = vim.lastSelection;
                  if (vim.visualMode) {
                    updateLastSelection(cm, vim);
                  }
                  if (lastSelection) {
                    var anchor = lastSelection.anchorMark.find();
                    var head = lastSelection.headMark.find();
                    if (!anchor || !head) {
                      // If the marks have been destroyed due to edits, do nothing.
                      return;
                    }
                    vim.sel = {
                      anchor: anchor,
                      head: head
                    };
                    vim.visualMode = true;
                    vim.visualLine = lastSelection.visualLine;
                    vim.visualBlock = lastSelection.visualBlock;
                    updateCmSelection(cm);
                    updateMark(cm, vim, '<', cursorMin(anchor, head));
                    updateMark(cm, vim, '>', cursorMax(anchor, head));
                    CodeMirror.signal(cm, 'vim-mode-change', {
                      mode: 'visual',
                      subMode: vim.visualLine ? 'linewise' :
                               vim.visualBlock ? 'blockwise' : ''});
                  }
                },
                joinLines: function(cm, actionArgs, vim) {
                  var curStart, curEnd;
                  if (vim.visualMode) {
                    curStart = cm.getCursor('anchor');
                    curEnd = cm.getCursor('head');
                    if (cursorIsBefore(curEnd, curStart)) {
                      var tmp = curEnd;
                      curEnd = curStart;
                      curStart = tmp;
                    }
                    curEnd.ch = lineLength(cm, curEnd.line) - 1;
                  } else {
                    // Repeat is the number of lines to join. Minimum 2 lines.
                    var repeat = Math.max(actionArgs.repeat, 2);
                    curStart = cm.getCursor();
                    curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1,
                                                         Infinity));
                  }
                  var finalCh = 0;
                  for (var i = curStart.line; i < curEnd.line; i++) {
                    finalCh = lineLength(cm, curStart.line);
                    var tmp = Pos(curStart.line + 1,
                                  lineLength(cm, curStart.line + 1));
                    var text = cm.getRange(curStart, tmp);
                    text = text.replace(/\n\s*/g, ' ');
                    cm.replaceRange(text, curStart, tmp);
                  }
                  var curFinalPos = Pos(curStart.line, finalCh);
                  if (vim.visualMode) {
                    exitVisualMode(cm, false);
                  }
                  cm.setCursor(curFinalPos);
                },
                newLineAndEnterInsertMode: function(cm, actionArgs, vim) {
                  vim.insertMode = true;
                  var insertAt = copyCursor(cm.getCursor());
                  if (insertAt.line === cm.firstLine() && !actionArgs.after) {
                    // Special case for inserting newline before start of document.
                    cm.replaceRange('\n', Pos(cm.firstLine(), 0));
                    cm.setCursor(cm.firstLine(), 0);
                  } else {
                    insertAt.line = (actionArgs.after) ? insertAt.line :
                        insertAt.line - 1;
                    insertAt.ch = lineLength(cm, insertAt.line);
                    cm.setCursor(insertAt);
                    var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment ||
                        CodeMirror.commands.newlineAndIndent;
                    newlineFn(cm);
                  }
                  this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim);
                },
                paste: function(cm, actionArgs, vim) {
                  var cur = copyCursor(cm.getCursor());
                  var register = vimGlobalState.registerController.getRegister(
                      actionArgs.registerName);
                  var text = register.toString();
                  if (!text) {
                    return;
                  }
                  if (actionArgs.matchIndent) {
                    var tabSize = cm.getOption("tabSize");
                    // length that considers tabs and tabSize
                    var whitespaceLength = function(str) {
                      var tabs = (str.split("\t").length - 1);
                      var spaces = (str.split(" ").length - 1);
                      return tabs * tabSize + spaces * 1;
                    };
                    var currentLine = cm.getLine(cm.getCursor().line);
                    var indent = whitespaceLength(currentLine.match(/^\s*/)[0]);
                    // chomp last newline b/c don't want it to match /^\s*/gm
                    var chompedText = text.replace(/\n$/, '');
                    var wasChomped = text !== chompedText;
                    var firstIndent = whitespaceLength(text.match(/^\s*/)[0]);
                    var text = chompedText.replace(/^\s*/gm, function(wspace) {
                      var newIndent = indent + (whitespaceLength(wspace) - firstIndent);
                      if (newIndent < 0) {
                        return "";
                      }
                      else if (cm.getOption("indentWithTabs")) {
                        var quotient = Math.floor(newIndent / tabSize);
                        return Array(quotient + 1).join('\t');
                      }
                      else {
                        return Array(newIndent + 1).join(' ');
                      }
                    });
                    text += wasChomped ? "\n" : "";
                  }
                  if (actionArgs.repeat > 1) {
                    var text = Array(actionArgs.repeat + 1).join(text);
                  }
                  var linewise = register.linewise;
                  var blockwise = register.blockwise;
                  if (linewise) {
                    if(vim.visualMode) {
                      text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n';
                    } else if (actionArgs.after) {
                      // Move the newline at the end to the start instead, and paste just
                      // before the newline character of the line we are on right now.
                      text = '\n' + text.slice(0, text.length - 1);
                      cur.ch = lineLength(cm, cur.line);
                    } else {
                      cur.ch = 0;
                    }
                  } else {
                    if (blockwise) {
                      text = text.split('\n');
                      for (var i = 0; i < text.length; i++) {
                        text[i] = (text[i] == '') ? ' ' : text[i];
                      }
                    }
                    cur.ch += actionArgs.after ? 1 : 0;
                  }
                  var curPosFinal;
                  var idx;
                  if (vim.visualMode) {
                    //  save the pasted text for reselection if the need arises
                    vim.lastPastedText = text;
                    var lastSelectionCurEnd;
                    var selectedArea = getSelectedAreaRange(cm, vim);
                    var selectionStart = selectedArea[0];
                    var selectionEnd = selectedArea[1];
                    var selectedText = cm.getSelection();
                    var selections = cm.listSelections();
                    var emptyStrings = new Array(selections.length).join('1').split('1');
                    // save the curEnd marker before it get cleared due to cm.replaceRange.
                    if (vim.lastSelection) {
                      lastSelectionCurEnd = vim.lastSelection.headMark.find();
                    }
                    // push the previously selected text to unnamed register
                    vimGlobalState.registerController.unnamedRegister.setText(selectedText);
                    if (blockwise) {
                      // first delete the selected text
                      cm.replaceSelections(emptyStrings);
                      // Set new selections as per the block length of the yanked text
                      selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch);
                      cm.setCursor(selectionStart);
                      selectBlock(cm, selectionEnd);
                      cm.replaceSelections(text);
                      curPosFinal = selectionStart;
                    } else if (vim.visualBlock) {
                      cm.replaceSelections(emptyStrings);
                      cm.setCursor(selectionStart);
                      cm.replaceRange(text, selectionStart, selectionStart);
                      curPosFinal = selectionStart;
                    } else {
                      cm.replaceRange(text, selectionStart, selectionEnd);
                      curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);
                    }
                    // restore the the curEnd marker
                    if(lastSelectionCurEnd) {
                      vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd);
                    }
                    if (linewise) {
                      curPosFinal.ch=0;
                    }
                  } else {
                    if (blockwise) {
                      cm.setCursor(cur);
                      for (var i = 0; i < text.length; i++) {
                        var line = cur.line+i;
                        if (line > cm.lastLine()) {
                          cm.replaceRange('\n',  Pos(line, 0));
                        }
                        var lastCh = lineLength(cm, line);
                        if (lastCh < cur.ch) {
                          extendLineToColumn(cm, line, cur.ch);
                        }
                      }
                      cm.setCursor(cur);
                      selectBlock(cm, Pos(cur.line + text.length-1, cur.ch));
                      cm.replaceSelections(text);
                      curPosFinal = cur;
                    } else {
                      cm.replaceRange(text, cur);
                      // Now fine tune the cursor to where we want it.
                      if (linewise && actionArgs.after) {
                        curPosFinal = Pos(
                        cur.line + 1,
                        findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)));
                      } else if (linewise && !actionArgs.after) {
                        curPosFinal = Pos(
                          cur.line,
                          findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)));
                      } else if (!linewise && actionArgs.after) {
                        idx = cm.indexFromPos(cur);
                        curPosFinal = cm.posFromIndex(idx + text.length - 1);
                      } else {
                        idx = cm.indexFromPos(cur);
                        curPosFinal = cm.posFromIndex(idx + text.length);
                      }
                    }
                  }
                  if (vim.visualMode) {
                    exitVisualMode(cm, false);
                  }
                  cm.setCursor(curPosFinal);
                },
                undo: function(cm, actionArgs) {
                  cm.operation(function() {
                    repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)();
                    cm.setCursor(cm.getCursor('anchor'));
                  });
                },
                redo: function(cm, actionArgs) {
                  repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)();
                },
                setRegister: function(_cm, actionArgs, vim) {
                  vim.inputState.registerName = actionArgs.selectedCharacter;
                },
                setMark: function(cm, actionArgs, vim) {
                  var markName = actionArgs.selectedCharacter;
                  updateMark(cm, vim, markName, cm.getCursor());
                },
                replace: function(cm, actionArgs, vim) {
                  var replaceWith = actionArgs.selectedCharacter;
                  var curStart = cm.getCursor();
                  var replaceTo;
                  var curEnd;
                  var selections = cm.listSelections();
                  if (vim.visualMode) {
                    curStart = cm.getCursor('start');
                    curEnd = cm.getCursor('end');
                  } else {
                    var line = cm.getLine(curStart.line);
                    replaceTo = curStart.ch + actionArgs.repeat;
                    if (replaceTo > line.length) {
                      replaceTo=line.length;
                    }
                    curEnd = Pos(curStart.line, replaceTo);
                  }
                  if (replaceWith=='\n') {
                    if (!vim.visualMode) cm.replaceRange('', curStart, curEnd);
                    // special case, where vim help says to replace by just one line-break
                    (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm);
                  } else {
                    var replaceWithStr = cm.getRange(curStart, curEnd);
                    //replace all characters in range by selected, but keep linebreaks
                    replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith);
                    if (vim.visualBlock) {
                      // Tabs are split in visua block before replacing
                      var spaces = new Array(cm.getOption("tabSize")+1).join(' ');
                      replaceWithStr = cm.getSelection();
                      replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n');
                      cm.replaceSelections(replaceWithStr);
                    } else {
                      cm.replaceRange(replaceWithStr, curStart, curEnd);
                    }
                    if (vim.visualMode) {
                      curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ?
                                   selections[0].anchor : selections[0].head;
                      cm.setCursor(curStart);
                      exitVisualMode(cm, false);
                    } else {
                      cm.setCursor(offsetCursor(curEnd, 0, -1));
                    }
                  }
                },
                incrementNumberToken: function(cm, actionArgs) {
                  var cur = cm.getCursor();
                  var lineStr = cm.getLine(cur.line);
                  var re = /-?\d+/g;
                  var match;
                  var start;
                  var end;
                  var numberStr;
                  var token;
                  while ((match = re.exec(lineStr)) !== null) {
                    token = match[0];
                    start = match.index;
                    end = start + token.length;
                    if (cur.ch < end)break;
                  }
                  if (!actionArgs.backtrack && (end <= cur.ch))return;
                  if (token) {
                    var increment = actionArgs.increase ? 1 : -1;
                    var number = parseInt(token) + (increment * actionArgs.repeat);
                    var from = Pos(cur.line, start);
                    var to = Pos(cur.line, end);
                    numberStr = number.toString();
                    cm.replaceRange(numberStr, from, to);
                  } else {
                    return;
                  }
                  cm.setCursor(Pos(cur.line, start + numberStr.length - 1));
                },
                repeatLastEdit: function(cm, actionArgs, vim) {
                  var lastEditInputState = vim.lastEditInputState;
                  if (!lastEditInputState) { return; }
                  var repeat = actionArgs.repeat;
                  if (repeat && actionArgs.repeatIsExplicit) {
                    vim.lastEditInputState.repeatOverride = repeat;
                  } else {
                    repeat = vim.lastEditInputState.repeatOverride || repeat;
                  }
                  repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */);
                },
                exitInsertMode: exitInsertMode
              };
          
              function defineAction(name, fn) {
                actions[name] = fn;
              }
          
              /*
               * Below are miscellaneous utility functions used by vim.js
               */
          
              /**
               * Clips cursor to ensure that line is within the buffer's range
               * If includeLineBreak is true, then allow cur.ch == lineLength.
               */
              function clipCursorToContent(cm, cur, includeLineBreak) {
                var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() );
                var maxCh = lineLength(cm, line) - 1;
                maxCh = (includeLineBreak) ? maxCh + 1 : maxCh;
                var ch = Math.min(Math.max(0, cur.ch), maxCh);
                return Pos(line, ch);
              }
              function copyArgs(args) {
                var ret = {};
                for (var prop in args) {
                  if (args.hasOwnProperty(prop)) {
                    ret[prop] = args[prop];
                  }
                }
                return ret;
              }
              function offsetCursor(cur, offsetLine, offsetCh) {
                if (typeof offsetLine === 'object') {
                  offsetCh = offsetLine.ch;
                  offsetLine = offsetLine.line;
                }
                return Pos(cur.line + offsetLine, cur.ch + offsetCh);
              }
              function getOffset(anchor, head) {
                return {
                  line: head.line - anchor.line,
                  ch: head.line - anchor.line
                };
              }
              function commandMatches(keys, keyMap, context, inputState) {
                // Partial matches are not applied. They inform the key handler
                // that the current key sequence is a subsequence of a valid key
                // sequence, so that the key buffer is not cleared.
                var match, partial = [], full = [];
                for (var i = 0; i < keyMap.length; i++) {
                  var command = keyMap[i];
                  if (context == 'insert' && command.context != 'insert' ||
                      command.context && command.context != context ||
                      inputState.operator && command.type == 'action' ||
                      !(match = commandMatch(keys, command.keys))) { continue; }
                  if (match == 'partial') { partial.push(command); }
                  if (match == 'full') { full.push(command); }
                }
                return {
                  partial: partial.length && partial,
                  full: full.length && full
                };
              }
              function commandMatch(pressed, mapped) {
                if (mapped.slice(-11) == '<character>') {
                  // Last character matches anything.
                  var prefixLen = mapped.length - 11;
                  var pressedPrefix = pressed.slice(0, prefixLen);
                  var mappedPrefix = mapped.slice(0, prefixLen);
                  return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' :
                         mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false;
                } else {
                  return pressed == mapped ? 'full' :
                         mapped.indexOf(pressed) == 0 ? 'partial' : false;
                }
              }
              function lastChar(keys) {
                var match = /^.*(<[\w\-]+>)$/.exec(keys);
                var selectedCharacter = match ? match[1] : keys.slice(-1);
                if (selectedCharacter.length > 1){
                  switch(selectedCharacter){
                    case '<CR>':
                      selectedCharacter='\n';
                      break;
                    case '<Space>':
                      selectedCharacter=' ';
                      break;
                    default:
                      break;
                  }
                }
                return selectedCharacter;
              }
              function repeatFn(cm, fn, repeat) {
                return function() {
                  for (var i = 0; i < repeat; i++) {
                    fn(cm);
                  }
                };
              }
              function copyCursor(cur) {
                return Pos(cur.line, cur.ch);
              }
              function cursorEqual(cur1, cur2) {
                return cur1.ch == cur2.ch && cur1.line == cur2.line;
              }
              function cursorIsBefore(cur1, cur2) {
                if (cur1.line < cur2.line) {
                  return true;
                }
                if (cur1.line == cur2.line && cur1.ch < cur2.ch) {
                  return true;
                }
                return false;
              }
              function cursorMin(cur1, cur2) {
                if (arguments.length > 2) {
                  cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1));
                }
                return cursorIsBefore(cur1, cur2) ? cur1 : cur2;
              }
              function cursorMax(cur1, cur2) {
                if (arguments.length > 2) {
                  cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1));
                }
                return cursorIsBefore(cur1, cur2) ? cur2 : cur1;
              }
              function cursorIsBetween(cur1, cur2, cur3) {
                // returns true if cur2 is between cur1 and cur3.
                var cur1before2 = cursorIsBefore(cur1, cur2);
                var cur2before3 = cursorIsBefore(cur2, cur3);
                return cur1before2 && cur2before3;
              }
              function lineLength(cm, lineNum) {
                return cm.getLine(lineNum).length;
              }
              function reverse(s){
                return s.split('').reverse().join('');
              }
              function trim(s) {
                if (s.trim) {
                  return s.trim();
                }
                return s.replace(/^\s+|\s+$/g, '');
              }
              function escapeRegex(s) {
                return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1');
              }
              function extendLineToColumn(cm, lineNum, column) {
                var endCh = lineLength(cm, lineNum);
                var spaces = new Array(column-endCh+1).join(' ');
                cm.setCursor(Pos(lineNum, endCh));
                cm.replaceRange(spaces, cm.getCursor());
              }
              // This functions selects a rectangular block
              // of text with selectionEnd as any of its corner
              // Height of block:
              // Difference in selectionEnd.line and first/last selection.line
              // Width of the block:
              // Distance between selectionEnd.ch and any(first considered here) selection.ch
              function selectBlock(cm, selectionEnd) {
                var selections = [], ranges = cm.listSelections();
                var head = copyCursor(cm.clipPos(selectionEnd));
                var isClipped = !cursorEqual(selectionEnd, head);
                var curHead = cm.getCursor('head');
                var primIndex = getIndex(ranges, curHead);
                var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor);
                var max = ranges.length - 1;
                var index = max - primIndex > primIndex ? max : 0;
                var base = ranges[index].anchor;
          
                var firstLine = Math.min(base.line, head.line);
                var lastLine = Math.max(base.line, head.line);
                var baseCh = base.ch, headCh = head.ch;
          
                var dir = ranges[index].head.ch - baseCh;
                var newDir = headCh - baseCh;
                if (dir > 0 && newDir <= 0) {
                  baseCh++;
                  if (!isClipped) { headCh--; }
                } else if (dir < 0 && newDir >= 0) {
                  baseCh--;
                  if (!wasClipped) { headCh++; }
                } else if (dir < 0 && newDir == -1) {
                  baseCh--;
                  headCh++;
                }
                for (var line = firstLine; line <= lastLine; line++) {
                  var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)};
                  selections.push(range);
                }
                primIndex = head.line == lastLine ? selections.length - 1 : 0;
                cm.setSelections(selections);
                selectionEnd.ch = headCh;
                base.ch = baseCh;
                return base;
              }
              function selectForInsert(cm, head, height) {
                var sel = [];
                for (var i = 0; i < height; i++) {
                  var lineHead = offsetCursor(head, i, 0);
                  sel.push({anchor: lineHead, head: lineHead});
                }
                cm.setSelections(sel, 0);
              }
              // getIndex returns the index of the cursor in the selections.
              function getIndex(ranges, cursor, end) {
                for (var i = 0; i < ranges.length; i++) {
                  var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor);
                  var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor);
                  if (atAnchor || atHead) {
                    return i;
                  }
                }
                return -1;
              }
              function getSelectedAreaRange(cm, vim) {
                var lastSelection = vim.lastSelection;
                var getCurrentSelectedAreaRange = function() {
                  var selections = cm.listSelections();
                  var start =  selections[0];
                  var end = selections[selections.length-1];
                  var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;
                  var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
                  return [selectionStart, selectionEnd];
                };
                var getLastSelectedAreaRange = function() {
                  var selectionStart = cm.getCursor();
                  var selectionEnd = cm.getCursor();
                  var block = lastSelection.visualBlock;
                  if (block) {
                    var width = block.width;
                    var height = block.height;
                    selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width);
                    var selections = [];
                    // selectBlock creates a 'proper' rectangular block.
                    // We do not want that in all cases, so we manually set selections.
                    for (var i = selectionStart.line; i < selectionEnd.line; i++) {
                      var anchor = Pos(i, selectionStart.ch);
                      var head = Pos(i, selectionEnd.ch);
                      var range = {anchor: anchor, head: head};
                      selections.push(range);
                    }
                    cm.setSelections(selections);
                  } else {
                    var start = lastSelection.anchorMark.find();
                    var end = lastSelection.headMark.find();
                    var line = end.line - start.line;
                    var ch = end.ch - start.ch;
                    selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch};
                    if (lastSelection.visualLine) {
                      selectionStart = Pos(selectionStart.line, 0);
                      selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line));
                    }
                    cm.setSelection(selectionStart, selectionEnd);
                  }
                  return [selectionStart, selectionEnd];
                };
                if (!vim.visualMode) {
                // In case of replaying the action.
                  return getLastSelectedAreaRange();
                } else {
                  return getCurrentSelectedAreaRange();
                }
              }
              // Updates the previous selection with the current selection's values. This
              // should only be called in visual mode.
              function updateLastSelection(cm, vim) {
                var anchor = vim.sel.anchor;
                var head = vim.sel.head;
                // To accommodate the effect of lastPastedText in the last selection
                if (vim.lastPastedText) {
                  head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length);
                  vim.lastPastedText = null;
                }
                vim.lastSelection = {'anchorMark': cm.setBookmark(anchor),
                                     'headMark': cm.setBookmark(head),
                                     'anchor': copyCursor(anchor),
                                     'head': copyCursor(head),
                                     'visualMode': vim.visualMode,
                                     'visualLine': vim.visualLine,
                                     'visualBlock': vim.visualBlock};
              }
              function expandSelection(cm, start, end) {
                var sel = cm.state.vim.sel;
                var head = sel.head;
                var anchor = sel.anchor;
                var tmp;
                if (cursorIsBefore(end, start)) {
                  tmp = end;
                  end = start;
                  start = tmp;
                }
                if (cursorIsBefore(head, anchor)) {
                  head = cursorMin(start, head);
                  anchor = cursorMax(anchor, end);
                } else {
                  anchor = cursorMin(start, anchor);
                  head = cursorMax(head, end);
                  head = offsetCursor(head, 0, -1);
                  if (head.ch == -1 && head.line != cm.firstLine()) {
                    head = Pos(head.line - 1, lineLength(cm, head.line - 1));
                  }
                }
                return [anchor, head];
              }
              /**
               * Updates the CodeMirror selection to match the provided vim selection.
               * If no arguments are given, it uses the current vim selection state.
               */
              function updateCmSelection(cm, sel, mode) {
                var vim = cm.state.vim;
                sel = sel || vim.sel;
                var mode = mode ||
                  vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char';
                var cmSel = makeCmSelection(cm, sel, mode);
                cm.setSelections(cmSel.ranges, cmSel.primary);
                updateFakeCursor(cm);
              }
              function makeCmSelection(cm, sel, mode, exclusive) {
                var head = copyCursor(sel.head);
                var anchor = copyCursor(sel.anchor);
                if (mode == 'char') {
                  var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
                  var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
                  head = offsetCursor(sel.head, 0, headOffset);
                  anchor = offsetCursor(sel.anchor, 0, anchorOffset);
                  return {
                    ranges: [{anchor: anchor, head: head}],
                    primary: 0
                  };
                } else if (mode == 'line') {
                  if (!cursorIsBefore(sel.head, sel.anchor)) {
                    anchor.ch = 0;
          
                    var lastLine = cm.lastLine();
                    if (head.line > lastLine) {
                      head.line = lastLine;
                    }
                    head.ch = lineLength(cm, head.line);
                  } else {
                    head.ch = 0;
                    anchor.ch = lineLength(cm, anchor.line);
                  }
                  return {
                    ranges: [{anchor: anchor, head: head}],
                    primary: 0
                  };
                } else if (mode == 'block') {
                  var top = Math.min(anchor.line, head.line),
                      left = Math.min(anchor.ch, head.ch),
                      bottom = Math.max(anchor.line, head.line),
                      right = Math.max(anchor.ch, head.ch) + 1;
                  var height = bottom - top + 1;
                  var primary = head.line == top ? 0 : height - 1;
                  var ranges = [];
                  for (var i = 0; i < height; i++) {
                    ranges.push({
                      anchor: Pos(top + i, left),
                      head: Pos(top + i, right)
                    });
                  }
                  return {
                    ranges: ranges,
                    primary: primary
                  };
                }
              }
              function getHead(cm) {
                var cur = cm.getCursor('head');
                if (cm.getSelection().length == 1) {
                  // Small corner case when only 1 character is selected. The "real"
                  // head is the left of head and anchor.
                  cur = cursorMin(cur, cm.getCursor('anchor'));
                }
                return cur;
              }
          
              /**
               * If moveHead is set to false, the CodeMirror selection will not be
               * touched. The caller assumes the responsibility of putting the cursor
              * in the right place.
               */
              function exitVisualMode(cm, moveHead) {
                var vim = cm.state.vim;
                if (moveHead !== false) {
                  cm.setCursor(clipCursorToContent(cm, vim.sel.head));
                }
                updateLastSelection(cm, vim);
                vim.visualMode = false;
                vim.visualLine = false;
                vim.visualBlock = false;
                CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
                if (vim.fakeCursor) {
                  vim.fakeCursor.clear();
                }
              }
          
              // Remove any trailing newlines from the selection. For
              // example, with the caret at the start of the last word on the line,
              // 'dw' should word, but not the newline, while 'w' should advance the
              // caret to the first character of the next line.
              function clipToLine(cm, curStart, curEnd) {
                var selection = cm.getRange(curStart, curEnd);
                // Only clip if the selection ends with trailing newline + whitespace
                if (/\n\s*$/.test(selection)) {
                  var lines = selection.split('\n');
                  // We know this is all whitepsace.
                  lines.pop();
          
                  // Cases:
                  // 1. Last word is an empty line - do not clip the trailing '\n'
                  // 2. Last word is not an empty line - clip the trailing '\n'
                  var line;
                  // Find the line containing the last word, and clip all whitespace up
                  // to it.
                  for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) {
                    curEnd.line--;
                    curEnd.ch = 0;
                  }
                  // If the last word is not an empty line, clip an additional newline
                  if (line) {
                    curEnd.line--;
                    curEnd.ch = lineLength(cm, curEnd.line);
                  } else {
                    curEnd.ch = 0;
                  }
                }
              }
          
              // Expand the selection to line ends.
              function expandSelectionToLine(_cm, curStart, curEnd) {
                curStart.ch = 0;
                curEnd.ch = 0;
                curEnd.line++;
              }
          
              function findFirstNonWhiteSpaceCharacter(text) {
                if (!text) {
                  return 0;
                }
                var firstNonWS = text.search(/\S/);
                return firstNonWS == -1 ? text.length : firstNonWS;
              }
          
              function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) {
                var cur = getHead(cm);
                var line = cm.getLine(cur.line);
                var idx = cur.ch;
          
                // Seek to first word or non-whitespace character, depending on if
                // noSymbol is true.
                var textAfterIdx = line.substring(idx);
                var firstMatchedChar;
                if (noSymbol) {
                  firstMatchedChar = textAfterIdx.search(/\w/);
                } else {
                  firstMatchedChar = textAfterIdx.search(/\S/);
                }
                if (firstMatchedChar == -1) {
                  return null;
                }
                idx += firstMatchedChar;
                textAfterIdx = line.substring(idx);
                var textBeforeIdx = line.substring(0, idx);
          
                var matchRegex;
                // Greedy matchers for the "word" we are trying to expand.
                if (bigWord) {
                  matchRegex = /^\S+/;
                } else {
                  if ((/\w/).test(line.charAt(idx))) {
                    matchRegex = /^\w+/;
                  } else {
                    matchRegex = /^[^\w\s]+/;
                  }
                }
          
                var wordAfterRegex = matchRegex.exec(textAfterIdx);
                var wordStart = idx;
                var wordEnd = idx + wordAfterRegex[0].length;
                // TODO: Find a better way to do this. It will be slow on very long lines.
                var revTextBeforeIdx = reverse(textBeforeIdx);
                var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx);
                if (wordBeforeRegex) {
                  wordStart -= wordBeforeRegex[0].length;
                }
          
                if (inclusive) {
                  // If present, trim all whitespace after word.
                  // Otherwise, trim all whitespace before word.
                  var textAfterWordEnd = line.substring(wordEnd);
                  var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length;
                  if (whitespacesAfterWord > 0) {
                    wordEnd += whitespacesAfterWord;
                  } else {
                    var revTrim = revTextBeforeIdx.length - wordStart;
                    var textBeforeWordStart = revTextBeforeIdx.substring(revTrim);
                    var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length;
                    wordStart -= whitespacesBeforeWord;
                  }
                }
          
                return { start: Pos(cur.line, wordStart),
                         end: Pos(cur.line, wordEnd) };
              }
          
              function recordJumpPosition(cm, oldCur, newCur) {
                if (!cursorEqual(oldCur, newCur)) {
                  vimGlobalState.jumpList.add(cm, oldCur, newCur);
                }
              }
          
              function recordLastCharacterSearch(increment, args) {
                  vimGlobalState.lastChararacterSearch.increment = increment;
                  vimGlobalState.lastChararacterSearch.forward = args.forward;
                  vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter;
              }
          
              var symbolToMode = {
                  '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket',
                  '[': 'section', ']': 'section',
                  '*': 'comment', '/': 'comment',
                  'm': 'method', 'M': 'method',
                  '#': 'preprocess'
              };
              var findSymbolModes = {
                bracket: {
                  isComplete: function(state) {
                    if (state.nextCh === state.symb) {
                      state.depth++;
                      if (state.depth >= 1)return true;
                    } else if (state.nextCh === state.reverseSymb) {
                      state.depth--;
                    }
                    return false;
                  }
                },
                section: {
                  init: function(state) {
                    state.curMoveThrough = true;
                    state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}';
                  },
                  isComplete: function(state) {
                    return state.index === 0 && state.nextCh === state.symb;
                  }
                },
                comment: {
                  isComplete: function(state) {
                    var found = state.lastCh === '*' && state.nextCh === '/';
                    state.lastCh = state.nextCh;
                    return found;
                  }
                },
                // TODO: The original Vim implementation only operates on level 1 and 2.
                // The current implementation doesn't check for code block level and
                // therefore it operates on any levels.
                method: {
                  init: function(state) {
                    state.symb = (state.symb === 'm' ? '{' : '}');
                    state.reverseSymb = state.symb === '{' ? '}' : '{';
                  },
                  isComplete: function(state) {
                    if (state.nextCh === state.symb)return true;
                    return false;
                  }
                },
                preprocess: {
                  init: function(state) {
                    state.index = 0;
                  },
                  isComplete: function(state) {
                    if (state.nextCh === '#') {
                      var token = state.lineText.match(/#(\w+)/)[1];
                      if (token === 'endif') {
                        if (state.forward && state.depth === 0) {
                          return true;
                        }
                        state.depth++;
                      } else if (token === 'if') {
                        if (!state.forward && state.depth === 0) {
                          return true;
                        }
                        state.depth--;
                      }
                      if (token === 'else' && state.depth === 0)return true;
                    }
                    return false;
                  }
                }
              };
              function findSymbol(cm, repeat, forward, symb) {
                var cur = copyCursor(cm.getCursor());
                var increment = forward ? 1 : -1;
                var endLine = forward ? cm.lineCount() : -1;
                var curCh = cur.ch;
                var line = cur.line;
                var lineText = cm.getLine(line);
                var state = {
                  lineText: lineText,
                  nextCh: lineText.charAt(curCh),
                  lastCh: null,
                  index: curCh,
                  symb: symb,
                  reverseSymb: (forward ?  { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb],
                  forward: forward,
                  depth: 0,
                  curMoveThrough: false
                };
                var mode = symbolToMode[symb];
                if (!mode)return cur;
                var init = findSymbolModes[mode].init;
                var isComplete = findSymbolModes[mode].isComplete;
                if (init) { init(state); }
                while (line !== endLine && repeat) {
                  state.index += increment;
                  state.nextCh = state.lineText.charAt(state.index);
                  if (!state.nextCh) {
                    line += increment;
                    state.lineText = cm.getLine(line) || '';
                    if (increment > 0) {
                      state.index = 0;
                    } else {
                      var lineLen = state.lineText.length;
                      state.index = (lineLen > 0) ? (lineLen-1) : 0;
                    }
                    state.nextCh = state.lineText.charAt(state.index);
                  }
                  if (isComplete(state)) {
                    cur.line = line;
                    cur.ch = state.index;
                    repeat--;
                  }
                }
                if (state.nextCh || state.curMoveThrough) {
                  return Pos(line, state.index);
                }
                return cur;
              }
          
              /*
               * Returns the boundaries of the next word. If the cursor in the middle of
               * the word, then returns the boundaries of the current word, starting at
               * the cursor. If the cursor is at the start/end of a word, and we are going
               * forward/backward, respectively, find the boundaries of the next word.
               *
               * @param {CodeMirror} cm CodeMirror object.
               * @param {Cursor} cur The cursor position.
               * @param {boolean} forward True to search forward. False to search
               *     backward.
               * @param {boolean} bigWord True if punctuation count as part of the word.
               *     False if only [a-zA-Z0-9] characters count as part of the word.
               * @param {boolean} emptyLineIsWord True if empty lines should be treated
               *     as words.
               * @return {Object{from:number, to:number, line: number}} The boundaries of
               *     the word, or null if there are no more words.
               */
              function findWord(cm, cur, forward, bigWord, emptyLineIsWord) {
                var lineNum = cur.line;
                var pos = cur.ch;
                var line = cm.getLine(lineNum);
                var dir = forward ? 1 : -1;
                var regexps = bigWord ? bigWordRegexp : wordRegexp;
          
                if (emptyLineIsWord && line == '') {
                  lineNum += dir;
                  line = cm.getLine(lineNum);
                  if (!isLine(cm, lineNum)) {
                    return null;
                  }
                  pos = (forward) ? 0 : line.length;
                }
          
                while (true) {
                  if (emptyLineIsWord && line == '') {
                    return { from: 0, to: 0, line: lineNum };
                  }
                  var stop = (dir > 0) ? line.length : -1;
                  var wordStart = stop, wordEnd = stop;
                  // Find bounds of next word.
                  while (pos != stop) {
                    var foundWord = false;
                    for (var i = 0; i < regexps.length && !foundWord; ++i) {
                      if (regexps[i].test(line.charAt(pos))) {
                        wordStart = pos;
                        // Advance to end of word.
                        while (pos != stop && regexps[i].test(line.charAt(pos))) {
                          pos += dir;
                        }
                        wordEnd = pos;
                        foundWord = wordStart != wordEnd;
                        if (wordStart == cur.ch && lineNum == cur.line &&
                            wordEnd == wordStart + dir) {
                          // We started at the end of a word. Find the next one.
                          continue;
                        } else {
                          return {
                            from: Math.min(wordStart, wordEnd + 1),
                            to: Math.max(wordStart, wordEnd),
                            line: lineNum };
                        }
                      }
                    }
                    if (!foundWord) {
                      pos += dir;
                    }
                  }
                  // Advance to next/prev line.
                  lineNum += dir;
                  if (!isLine(cm, lineNum)) {
                    return null;
                  }
                  line = cm.getLine(lineNum);
                  pos = (dir > 0) ? 0 : line.length;
                }
                // Should never get here.
                throw new Error('The impossible happened.');
              }
          
              /**
               * @param {CodeMirror} cm CodeMirror object.
               * @param {Pos} cur The position to start from.
               * @param {int} repeat Number of words to move past.
               * @param {boolean} forward True to search forward. False to search
               *     backward.
               * @param {boolean} wordEnd True to move to end of word. False to move to
               *     beginning of word.
               * @param {boolean} bigWord True if punctuation count as part of the word.
               *     False if only alphabet characters count as part of the word.
               * @return {Cursor} The position the cursor should move to.
               */
              function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) {
                var curStart = copyCursor(cur);
                var words = [];
                if (forward && !wordEnd || !forward && wordEnd) {
                  repeat++;
                }
                // For 'e', empty lines are not considered words, go figure.
                var emptyLineIsWord = !(forward && wordEnd);
                for (var i = 0; i < repeat; i++) {
                  var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord);
                  if (!word) {
                    var eodCh = lineLength(cm, cm.lastLine());
                    words.push(forward
                        ? {line: cm.lastLine(), from: eodCh, to: eodCh}
                        : {line: 0, from: 0, to: 0});
                    break;
                  }
                  words.push(word);
                  cur = Pos(word.line, forward ? (word.to - 1) : word.from);
                }
                var shortCircuit = words.length != repeat;
                var firstWord = words[0];
                var lastWord = words.pop();
                if (forward && !wordEnd) {
                  // w
                  if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) {
                    // We did not start in the middle of a word. Discard the extra word at the end.
                    lastWord = words.pop();
                  }
                  return Pos(lastWord.line, lastWord.from);
                } else if (forward && wordEnd) {
                  return Pos(lastWord.line, lastWord.to - 1);
                } else if (!forward && wordEnd) {
                  // ge
                  if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) {
                    // We did not start in the middle of a word. Discard the extra word at the end.
                    lastWord = words.pop();
                  }
                  return Pos(lastWord.line, lastWord.to);
                } else {
                  // b
                  return Pos(lastWord.line, lastWord.from);
                }
              }
          
              function moveToCharacter(cm, repeat, forward, character) {
                var cur = cm.getCursor();
                var start = cur.ch;
                var idx;
                for (var i = 0; i < repeat; i ++) {
                  var line = cm.getLine(cur.line);
                  idx = charIdxInLine(start, line, character, forward, true);
                  if (idx == -1) {
                    return null;
                  }
                  start = idx;
                }
                return Pos(cm.getCursor().line, idx);
              }
          
              function moveToColumn(cm, repeat) {
                // repeat is always >= 1, so repeat - 1 always corresponds
                // to the column we want to go to.
                var line = cm.getCursor().line;
                return clipCursorToContent(cm, Pos(line, repeat - 1));
              }
          
              function updateMark(cm, vim, markName, pos) {
                if (!inArray(markName, validMarks)) {
                  return;
                }
                if (vim.marks[markName]) {
                  vim.marks[markName].clear();
                }
                vim.marks[markName] = cm.setBookmark(pos);
              }
          
              function charIdxInLine(start, line, character, forward, includeChar) {
                // Search for char in line.
                // motion_options: {forward, includeChar}
                // If includeChar = true, include it too.
                // If forward = true, search forward, else search backwards.
                // If char is not found on this line, do nothing
                var idx;
                if (forward) {
                  idx = line.indexOf(character, start + 1);
                  if (idx != -1 && !includeChar) {
                    idx -= 1;
                  }
                } else {
                  idx = line.lastIndexOf(character, start - 1);
                  if (idx != -1 && !includeChar) {
                    idx += 1;
                  }
                }
                return idx;
              }
          
              function findParagraph(cm, head, repeat, dir, inclusive) {
                var line = head.line;
                var min = cm.firstLine();
                var max = cm.lastLine();
                var start, end, i = line;
                function isEmpty(i) { return !cm.getLine(i); }
                function isBoundary(i, dir, any) {
                  if (any) { return isEmpty(i) != isEmpty(i + dir); }
                  return !isEmpty(i) && isEmpty(i + dir);
                }
                if (dir) {
                  while (min <= i && i <= max && repeat > 0) {
                    if (isBoundary(i, dir)) { repeat--; }
                    i += dir;
                  }
                  return new Pos(i, 0);
                }
          
                var vim = cm.state.vim;
                if (vim.visualLine && isBoundary(line, 1, true)) {
                  var anchor = vim.sel.anchor;
                  if (isBoundary(anchor.line, -1, true)) {
                    if (!inclusive || anchor.line != line) {
                      line += 1;
                    }
                  }
                }
                var startState = isEmpty(line);
                for (i = line; i <= max && repeat; i++) {
                  if (isBoundary(i, 1, true)) {
                    if (!inclusive || isEmpty(i) != startState) {
                      repeat--;
                    }
                  }
                }
                end = new Pos(i, 0);
                // select boundary before paragraph for the last one
                if (i > max && !startState) { startState = true; }
                else { inclusive = false; }
                for (i = line; i > min; i--) {
                  if (!inclusive || isEmpty(i) == startState || i == line) {
                    if (isBoundary(i, -1, true)) { break; }
                  }
                }
                start = new Pos(i, 0);
                return { start: start, end: end };
              }
          
              // TODO: perhaps this finagling of start and end positions belonds
              // in codmirror/replaceRange?
              function selectCompanionObject(cm, head, symb, inclusive) {
                var cur = head, start, end;
          
                var bracketRegexp = ({
                  '(': /[()]/, ')': /[()]/,
                  '[': /[[\]]/, ']': /[[\]]/,
                  '{': /[{}]/, '}': /[{}]/})[symb];
                var openSym = ({
                  '(': '(', ')': '(',
                  '[': '[', ']': '[',
                  '{': '{', '}': '{'})[symb];
                var curChar = cm.getLine(cur.line).charAt(cur.ch);
                // Due to the behavior of scanForBracket, we need to add an offset if the
                // cursor is on a matching open bracket.
                var offset = curChar === openSym ? 1 : 0;
          
                start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp});
                end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp});
          
                if (!start || !end) {
                  return { start: cur, end: cur };
                }
          
                start = start.pos;
                end = end.pos;
          
                if ((start.line == end.line && start.ch > end.ch)
                    || (start.line > end.line)) {
                  var tmp = start;
                  start = end;
                  end = tmp;
                }
          
                if (inclusive) {
                  end.ch += 1;
                } else {
                  start.ch += 1;
                }
          
                return { start: start, end: end };
              }
          
              // Takes in a symbol and a cursor and tries to simulate text objects that
              // have identical opening and closing symbols
              // TODO support across multiple lines
              function findBeginningAndEnd(cm, head, symb, inclusive) {
                var cur = copyCursor(head);
                var line = cm.getLine(cur.line);
                var chars = line.split('');
                var start, end, i, len;
                var firstIndex = chars.indexOf(symb);
          
                // the decision tree is to always look backwards for the beginning first,
                // but if the cursor is in front of the first instance of the symb,
                // then move the cursor forward
                if (cur.ch < firstIndex) {
                  cur.ch = firstIndex;
                  // Why is this line even here???
                  // cm.setCursor(cur.line, firstIndex+1);
                }
                // otherwise if the cursor is currently on the closing symbol
                else if (firstIndex < cur.ch && chars[cur.ch] == symb) {
                  end = cur.ch; // assign end to the current cursor
                  --cur.ch; // make sure to look backwards
                }
          
                // if we're currently on the symbol, we've got a start
                if (chars[cur.ch] == symb && !end) {
                  start = cur.ch + 1; // assign start to ahead of the cursor
                } else {
                  // go backwards to find the start
                  for (i = cur.ch; i > -1 && !start; i--) {
                    if (chars[i] == symb) {
                      start = i + 1;
                    }
                  }
                }
          
                // look forwards for the end symbol
                if (start && !end) {
                  for (i = start, len = chars.length; i < len && !end; i++) {
                    if (chars[i] == symb) {
                      end = i;
                    }
                  }
                }
          
                // nothing found
                if (!start || !end) {
                  return { start: cur, end: cur };
                }
          
                // include the symbols
                if (inclusive) {
                  --start; ++end;
                }
          
                return {
                  start: Pos(cur.line, start),
                  end: Pos(cur.line, end)
                };
              }
          
              // Search functions
              defineOption('pcre', true, 'boolean');
              function SearchState() {}
              SearchState.prototype = {
                getQuery: function() {
                  return vimGlobalState.query;
                },
                setQuery: function(query) {
                  vimGlobalState.query = query;
                },
                getOverlay: function() {
                  return this.searchOverlay;
                },
                setOverlay: function(overlay) {
                  this.searchOverlay = overlay;
                },
                isReversed: function() {
                  return vimGlobalState.isReversed;
                },
                setReversed: function(reversed) {
                  vimGlobalState.isReversed = reversed;
                },
                getScrollbarAnnotate: function() {
                  return this.annotate;
                },
                setScrollbarAnnotate: function(annotate) {
                  this.annotate = annotate;
                }
              };
              function getSearchState(cm) {
                var vim = cm.state.vim;
                return vim.searchState_ || (vim.searchState_ = new SearchState());
              }
              function dialog(cm, template, shortText, onClose, options) {
                if (cm.openDialog) {
                  cm.openDialog(template, onClose, { bottom: true, value: options.value,
                      onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp });
                }
                else {
                  onClose(prompt(shortText, ''));
                }
              }
              function splitBySlash(argString) {
                var slashes = findUnescapedSlashes(argString) || [];
                if (!slashes.length) return [];
                var tokens = [];
                // in case of strings like foo/bar
                if (slashes[0] !== 0) return;
                for (var i = 0; i < slashes.length; i++) {
                  if (typeof slashes[i] == 'number')
                    tokens.push(argString.substring(slashes[i] + 1, slashes[i+1]));
                }
                return tokens;
              }
          
              function findUnescapedSlashes(str) {
                var escapeNextChar = false;
                var slashes = [];
                for (var i = 0; i < str.length; i++) {
                  var c = str.charAt(i);
                  if (!escapeNextChar && c == '/') {
                    slashes.push(i);
                  }
                  escapeNextChar = !escapeNextChar && (c == '\\');
                }
                return slashes;
              }
          
              // Translates a search string from ex (vim) syntax into javascript form.
              function translateRegex(str) {
                // When these match, add a '\' if unescaped or remove one if escaped.
                var specials = '|(){';
                // Remove, but never add, a '\' for these.
                var unescape = '}';
                var escapeNextChar = false;
                var out = [];
                for (var i = -1; i < str.length; i++) {
                  var c = str.charAt(i) || '';
                  var n = str.charAt(i+1) || '';
                  var specialComesNext = (n && specials.indexOf(n) != -1);
                  if (escapeNextChar) {
                    if (c !== '\\' || !specialComesNext) {
                      out.push(c);
                    }
                    escapeNextChar = false;
                  } else {
                    if (c === '\\') {
                      escapeNextChar = true;
                      // Treat the unescape list as special for removing, but not adding '\'.
                      if (n && unescape.indexOf(n) != -1) {
                        specialComesNext = true;
                      }
                      // Not passing this test means removing a '\'.
                      if (!specialComesNext || n === '\\') {
                        out.push(c);
                      }
                    } else {
                      out.push(c);
                      if (specialComesNext && n !== '\\') {
                        out.push('\\');
                      }
                    }
                  }
                }
                return out.join('');
              }
          
              // Translates the replace part of a search and replace from ex (vim) syntax into
              // javascript form.  Similar to translateRegex, but additionally fixes back references
              // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'.
              function translateRegexReplace(str) {
                var escapeNextChar = false;
                var out = [];
                for (var i = -1; i < str.length; i++) {
                  var c = str.charAt(i) || '';
                  var n = str.charAt(i+1) || '';
                  if (escapeNextChar) {
                    // At any point in the loop, escapeNextChar is true if the previous
                    // character was a '\' and was not escaped.
                    out.push(c);
                    escapeNextChar = false;
                  } else {
                    if (c === '\\') {
                      escapeNextChar = true;
                      if ((isNumber(n) || n === '$')) {
                        out.push('$');
                      } else if (n !== '/' && n !== '\\') {
                        out.push('\\');
                      }
                    } else {
                      if (c === '$') {
                        out.push('$');
                      }
                      out.push(c);
                      if (n === '/') {
                        out.push('\\');
                      }
                    }
                  }
                }
                return out.join('');
              }
          
              // Unescape \ and / in the replace part, for PCRE mode.
              function unescapeRegexReplace(str) {
                var stream = new CodeMirror.StringStream(str);
                var output = [];
                while (!stream.eol()) {
                  // Search for \.
                  while (stream.peek() && stream.peek() != '\\') {
                    output.push(stream.next());
                  }
                  if (stream.match('\\/', true)) {
                    // \/ => /
                    output.push('/');
                  } else if (stream.match('\\\\', true)) {
                    // \\ => \
                    output.push('\\');
                  } else {
                    // Don't change anything
                    output.push(stream.next());
                  }
                }
                return output.join('');
              }
          
              /**
               * Extract the regular expression from the query and return a Regexp object.
               * Returns null if the query is blank.
               * If ignoreCase is passed in, the Regexp object will have the 'i' flag set.
               * If smartCase is passed in, and the query contains upper case letters,
               *   then ignoreCase is overridden, and the 'i' flag will not be set.
               * If the query contains the /i in the flag part of the regular expression,
               *   then both ignoreCase and smartCase are ignored, and 'i' will be passed
               *   through to the Regex object.
               */
              function parseQuery(query, ignoreCase, smartCase) {
                // First update the last search register
                var lastSearchRegister = vimGlobalState.registerController.getRegister('/');
                lastSearchRegister.setText(query);
                // Check if the query is already a regex.
                if (query instanceof RegExp) { return query; }
                // First try to extract regex + flags from the input. If no flags found,
                // extract just the regex. IE does not accept flags directly defined in
                // the regex string in the form /regex/flags
                var slashes = findUnescapedSlashes(query);
                var regexPart;
                var forceIgnoreCase;
                if (!slashes.length) {
                  // Query looks like 'regexp'
                  regexPart = query;
                } else {
                  // Query looks like 'regexp/...'
                  regexPart = query.substring(0, slashes[0]);
                  var flagsPart = query.substring(slashes[0]);
                  forceIgnoreCase = (flagsPart.indexOf('i') != -1);
                }
                if (!regexPart) {
                  return null;
                }
                if (!getOption('pcre')) {
                  regexPart = translateRegex(regexPart);
                }
                if (smartCase) {
                  ignoreCase = (/^[^A-Z]*$/).test(regexPart);
                }
                var regexp = new RegExp(regexPart,
                    (ignoreCase || forceIgnoreCase) ? 'i' : undefined);
                return regexp;
              }
              function showConfirm(cm, text) {
                if (cm.openNotification) {
                  cm.openNotification('<span style="color: red">' + text + '</span>',
                                      {bottom: true, duration: 5000});
                } else {
                  alert(text);
                }
              }
              function makePrompt(prefix, desc) {
                var raw = '';
                if (prefix) {
                  raw += '<span style="font-family: monospace">' + prefix + '</span>';
                }
                raw += '<input type="text"/> ' +
                    '<span style="color: #888">';
                if (desc) {
                  raw += '<span style="color: #888">';
                  raw += desc;
                  raw += '</span>';
                }
                return raw;
              }
              var searchPromptDesc = '(Javascript regexp)';
              function showPrompt(cm, options) {
                var shortText = (options.prefix || '') + ' ' + (options.desc || '');
                var prompt = makePrompt(options.prefix, options.desc);
                dialog(cm, prompt, shortText, options.onClose, options);
              }
              function regexEqual(r1, r2) {
                if (r1 instanceof RegExp && r2 instanceof RegExp) {
                    var props = ['global', 'multiline', 'ignoreCase', 'source'];
                    for (var i = 0; i < props.length; i++) {
                        var prop = props[i];
                        if (r1[prop] !== r2[prop]) {
                            return false;
                        }
                    }
                    return true;
                }
                return false;
              }
              // Returns true if the query is valid.
              function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) {
                if (!rawQuery) {
                  return;
                }
                var state = getSearchState(cm);
                var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase);
                if (!query) {
                  return;
                }
                highlightSearchMatches(cm, query);
                if (regexEqual(query, state.getQuery())) {
                  return query;
                }
                state.setQuery(query);
                return query;
              }
              function searchOverlay(query) {
                if (query.source.charAt(0) == '^') {
                  var matchSol = true;
                }
                return {
                  token: function(stream) {
                    if (matchSol && !stream.sol()) {
                      stream.skipToEnd();
                      return;
                    }
                    var match = stream.match(query, false);
                    if (match) {
                      if (match[0].length == 0) {
                        // Matched empty string, skip to next.
                        stream.next();
                        return 'searching';
                      }
                      if (!stream.sol()) {
                        // Backtrack 1 to match \b
                        stream.backUp(1);
                        if (!query.exec(stream.next() + match[0])) {
                          stream.next();
                          return null;
                        }
                      }
                      stream.match(query);
                      return 'searching';
                    }
                    while (!stream.eol()) {
                      stream.next();
                      if (stream.match(query, false)) break;
                    }
                  },
                  query: query
                };
              }
              function highlightSearchMatches(cm, query) {
                var searchState = getSearchState(cm);
                var overlay = searchState.getOverlay();
                if (!overlay || query != overlay.query) {
                  if (overlay) {
                    cm.removeOverlay(overlay);
                  }
                  overlay = searchOverlay(query);
                  cm.addOverlay(overlay);
                  if (cm.showMatchesOnScrollbar) {
                    if (searchState.getScrollbarAnnotate()) {
                      searchState.getScrollbarAnnotate().clear();
                    }
                    searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query));
                  }
                  searchState.setOverlay(overlay);
                }
              }
              function findNext(cm, prev, query, repeat) {
                if (repeat === undefined) { repeat = 1; }
                return cm.operation(function() {
                  var pos = cm.getCursor();
                  var cursor = cm.getSearchCursor(query, pos);
                  for (var i = 0; i < repeat; i++) {
                    var found = cursor.find(prev);
                    if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); }
                    if (!found) {
                      // SearchCursor may have returned null because it hit EOF, wrap
                      // around and try again.
                      cursor = cm.getSearchCursor(query,
                          (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) );
                      if (!cursor.find(prev)) {
                        return;
                      }
                    }
                  }
                  return cursor.from();
                });
              }
              function clearSearchHighlight(cm) {
                var state = getSearchState(cm);
                cm.removeOverlay(getSearchState(cm).getOverlay());
                state.setOverlay(null);
                if (state.getScrollbarAnnotate()) {
                  state.getScrollbarAnnotate().clear();
                  state.setScrollbarAnnotate(null);
                }
              }
              /**
               * Check if pos is in the specified range, INCLUSIVE.
               * Range can be specified with 1 or 2 arguments.
               * If the first range argument is an array, treat it as an array of line
               * numbers. Match pos against any of the lines.
               * If the first range argument is a number,
               *   if there is only 1 range argument, check if pos has the same line
               *       number
               *   if there are 2 range arguments, then check if pos is in between the two
               *       range arguments.
               */
              function isInRange(pos, start, end) {
                if (typeof pos != 'number') {
                  // Assume it is a cursor position. Get the line number.
                  pos = pos.line;
                }
                if (start instanceof Array) {
                  return inArray(pos, start);
                } else {
                  if (end) {
                    return (pos >= start && pos <= end);
                  } else {
                    return pos == start;
                  }
                }
              }
              function getUserVisibleLines(cm) {
                var scrollInfo = cm.getScrollInfo();
                var occludeToleranceTop = 6;
                var occludeToleranceBottom = 10;
                var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local');
                var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top;
                var to = cm.coordsChar({left:0, top: bottomY}, 'local');
                return {top: from.line, bottom: to.line};
              }
          
              // Ex command handling
              // Care must be taken when adding to the default Ex command map. For any
              // pair of commands that have a shared prefix, at least one of their
              // shortNames must not match the prefix of the other command.
              var defaultExCommandMap = [
                { name: 'map' },
                { name: 'imap', shortName: 'im' },
                { name: 'nmap', shortName: 'nm' },
                { name: 'vmap', shortName: 'vm' },
                { name: 'unmap' },
                { name: 'write', shortName: 'w' },
                { name: 'undo', shortName: 'u' },
                { name: 'redo', shortName: 'red' },
                { name: 'set', shortName: 'set' },
                { name: 'sort', shortName: 'sor' },
                { name: 'substitute', shortName: 's', possiblyAsync: true },
                { name: 'nohlsearch', shortName: 'noh' },
                { name: 'delmarks', shortName: 'delm' },
                { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
                { name: 'global', shortName: 'g' }
              ];
              var ExCommandDispatcher = function() {
                this.buildCommandMap_();
              };
              ExCommandDispatcher.prototype = {
                processCommand: function(cm, input, opt_params) {
                  var vim = cm.state.vim;
                  var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
                  var previousCommand = commandHistoryRegister.toString();
                  if (vim.visualMode) {
                    exitVisualMode(cm);
                  }
                  var inputStream = new CodeMirror.StringStream(input);
                  // update ": with the latest command whether valid or invalid
                  commandHistoryRegister.setText(input);
                  var params = opt_params || {};
                  params.input = input;
                  try {
                    this.parseInput_(cm, inputStream, params);
                  } catch(e) {
                    showConfirm(cm, e);
                    throw e;
                  }
                  var command;
                  var commandName;
                  if (!params.commandName) {
                    // If only a line range is defined, move to the line.
                    if (params.line !== undefined) {
                      commandName = 'move';
                    }
                  } else {
                    command = this.matchCommand_(params.commandName);
                    if (command) {
                      commandName = command.name;
                      if (command.excludeFromCommandHistory) {
                        commandHistoryRegister.setText(previousCommand);
                      }
                      this.parseCommandArgs_(inputStream, params, command);
                      if (command.type == 'exToKey') {
                        // Handle Ex to Key mapping.
                        for (var i = 0; i < command.toKeys.length; i++) {
                          CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping');
                        }
                        return;
                      } else if (command.type == 'exToEx') {
                        // Handle Ex to Ex mapping.
                        this.processCommand(cm, command.toInput);
                        return;
                      }
                    }
                  }
                  if (!commandName) {
                    showConfirm(cm, 'Not an editor command ":' + input + '"');
                    return;
                  }
                  try {
                    exCommands[commandName](cm, params);
                    // Possibly asynchronous commands (e.g. substitute, which might have a
                    // user confirmation), are responsible for calling the callback when
                    // done. All others have it taken care of for them here.
                    if ((!command || !command.possiblyAsync) && params.callback) {
                      params.callback();
                    }
                  } catch(e) {
                    showConfirm(cm, e);
                    throw e;
                  }
                },
                parseInput_: function(cm, inputStream, result) {
                  inputStream.eatWhile(':');
                  // Parse range.
                  if (inputStream.eat('%')) {
                    result.line = cm.firstLine();
                    result.lineEnd = cm.lastLine();
                  } else {
                    result.line = this.parseLineSpec_(cm, inputStream);
                    if (result.line !== undefined && inputStream.eat(',')) {
                      result.lineEnd = this.parseLineSpec_(cm, inputStream);
                    }
                  }
          
                  // Parse command name.
                  var commandMatch = inputStream.match(/^(\w+)/);
                  if (commandMatch) {
                    result.commandName = commandMatch[1];
                  } else {
                    result.commandName = inputStream.match(/.*/)[0];
                  }
          
                  return result;
                },
                parseLineSpec_: function(cm, inputStream) {
                  var numberMatch = inputStream.match(/^(\d+)/);
                  if (numberMatch) {
                    return parseInt(numberMatch[1], 10) - 1;
                  }
                  switch (inputStream.next()) {
                    case '.':
                      return cm.getCursor().line;
                    case '$':
                      return cm.lastLine();
                    case '\'':
                      var mark = cm.state.vim.marks[inputStream.next()];
                      if (mark && mark.find()) {
                        return mark.find().line;
                      }
                      throw new Error('Mark not set');
                    default:
                      inputStream.backUp(1);
                      return undefined;
                  }
                },
                parseCommandArgs_: function(inputStream, params, command) {
                  if (inputStream.eol()) {
                    return;
                  }
                  params.argString = inputStream.match(/.*/)[0];
                  // Parse command-line arguments
                  var delim = command.argDelimiter || /\s+/;
                  var args = trim(params.argString).split(delim);
                  if (args.length && args[0]) {
                    params.args = args;
                  }
                },
                matchCommand_: function(commandName) {
                  // Return the command in the command map that matches the shortest
                  // prefix of the passed in command name. The match is guaranteed to be
                  // unambiguous if the defaultExCommandMap's shortNames are set up
                  // correctly. (see @code{defaultExCommandMap}).
                  for (var i = commandName.length; i > 0; i--) {
                    var prefix = commandName.substring(0, i);
                    if (this.commandMap_[prefix]) {
                      var command = this.commandMap_[prefix];
                      if (command.name.indexOf(commandName) === 0) {
                        return command;
                      }
                    }
                  }
                  return null;
                },
                buildCommandMap_: function() {
                  this.commandMap_ = {};
                  for (var i = 0; i < defaultExCommandMap.length; i++) {
                    var command = defaultExCommandMap[i];
                    var key = command.shortName || command.name;
                    this.commandMap_[key] = command;
                  }
                },
                map: function(lhs, rhs, ctx) {
                  if (lhs != ':' && lhs.charAt(0) == ':') {
                    if (ctx) { throw Error('Mode not supported for ex mappings'); }
                    var commandName = lhs.substring(1);
                    if (rhs != ':' && rhs.charAt(0) == ':') {
                      // Ex to Ex mapping
                      this.commandMap_[commandName] = {
                        name: commandName,
                        type: 'exToEx',
                        toInput: rhs.substring(1),
                        user: true
                      };
                    } else {
                      // Ex to key mapping
                      this.commandMap_[commandName] = {
                        name: commandName,
                        type: 'exToKey',
                        toKeys: rhs,
                        user: true
                      };
                    }
                  } else {
                    if (rhs != ':' && rhs.charAt(0) == ':') {
                      // Key to Ex mapping.
                      var mapping = {
                        keys: lhs,
                        type: 'keyToEx',
                        exArgs: { input: rhs.substring(1) },
                        user: true};
                      if (ctx) { mapping.context = ctx; }
                      defaultKeymap.unshift(mapping);
                    } else {
                      // Key to key mapping
                      var mapping = {
                        keys: lhs,
                        type: 'keyToKey',
                        toKeys: rhs,
                        user: true
                      };
                      if (ctx) { mapping.context = ctx; }
                      defaultKeymap.unshift(mapping);
                    }
                  }
                },
                unmap: function(lhs, ctx) {
                  if (lhs != ':' && lhs.charAt(0) == ':') {
                    // Ex to Ex or Ex to key mapping
                    if (ctx) { throw Error('Mode not supported for ex mappings'); }
                    var commandName = lhs.substring(1);
                    if (this.commandMap_[commandName] && this.commandMap_[commandName].user) {
                      delete this.commandMap_[commandName];
                      return;
                    }
                  } else {
                    // Key to Ex or key to key mapping
                    var keys = lhs;
                    for (var i = 0; i < defaultKeymap.length; i++) {
                      if (keys == defaultKeymap[i].keys
                          && defaultKeymap[i].context === ctx
                          && defaultKeymap[i].user) {
                        defaultKeymap.splice(i, 1);
                        return;
                      }
                    }
                  }
                  throw Error('No such mapping.');
                }
              };
          
              var exCommands = {
                map: function(cm, params, ctx) {
                  var mapArgs = params.args;
                  if (!mapArgs || mapArgs.length < 2) {
                    if (cm) {
                      showConfirm(cm, 'Invalid mapping: ' + params.input);
                    }
                    return;
                  }
                  exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx);
                },
                imap: function(cm, params) { this.map(cm, params, 'insert'); },
                nmap: function(cm, params) { this.map(cm, params, 'normal'); },
                vmap: function(cm, params) { this.map(cm, params, 'visual'); },
                unmap: function(cm, params, ctx) {
                  var mapArgs = params.args;
                  if (!mapArgs || mapArgs.length < 1) {
                    if (cm) {
                      showConfirm(cm, 'No such mapping: ' + params.input);
                    }
                    return;
                  }
                  exCommandDispatcher.unmap(mapArgs[0], ctx);
                },
                move: function(cm, params) {
                  commandDispatcher.processCommand(cm, cm.state.vim, {
                      type: 'motion',
                      motion: 'moveToLineOrEdgeOfDocument',
                      motionArgs: { forward: false, explicitRepeat: true,
                        linewise: true },
                      repeatOverride: params.line+1});
                },
                set: function(cm, params) {
                  var setArgs = params.args;
                  if (!setArgs || setArgs.length < 1) {
                    if (cm) {
                      showConfirm(cm, 'Invalid mapping: ' + params.input);
                    }
                    return;
                  }
                  var expr = setArgs[0].split('=');
                  var optionName = expr[0];
                  var value = expr[1];
                  var forceGet = false;
          
                  if (optionName.charAt(optionName.length - 1) == '?') {
                    // If post-fixed with ?, then the set is actually a get.
                    if (value) { throw Error('Trailing characters: ' + params.argString); }
                    optionName = optionName.substring(0, optionName.length - 1);
                    forceGet = true;
                  }
                  if (value === undefined && optionName.substring(0, 2) == 'no') {
                    // To set boolean options to false, the option name is prefixed with
                    // 'no'.
                    optionName = optionName.substring(2);
                    value = false;
                  }
                  var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
                  if (optionIsBoolean && value == undefined) {
                    // Calling set with a boolean option sets it to true.
                    value = true;
                  }
                  if (!optionIsBoolean && !value || forceGet) {
                    var oldValue = getOption(optionName);
                    // If no value is provided, then we assume this is a get.
                    if (oldValue === true || oldValue === false) {
                      showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
                    } else {
                      showConfirm(cm, '  ' + optionName + '=' + oldValue);
                    }
                  } else {
                    setOption(optionName, value);
                  }
                },
                registers: function(cm,params) {
                  var regArgs = params.args;
                  var registers = vimGlobalState.registerController.registers;
                  var regInfo = '----------Registers----------<br><br>';
                  if (!regArgs) {
                    for (var registerName in registers) {
                      var text = registers[registerName].toString();
                      if (text.length) {
                        regInfo += '"' + registerName + '    ' + text + '<br>';
                      }
                    }
                  } else {
                    var registerName;
                    regArgs = regArgs.join('');
                    for (var i = 0; i < regArgs.length; i++) {
                      registerName = regArgs.charAt(i);
                      if (!vimGlobalState.registerController.isValidRegister(registerName)) {
                        continue;
                      }
                      var register = registers[registerName] || new Register();
                      regInfo += '"' + registerName + '    ' + register.toString() + '<br>';
                    }
                  }
                  showConfirm(cm, regInfo);
                },
                sort: function(cm, params) {
                  var reverse, ignoreCase, unique, number;
                  function parseArgs() {
                    if (params.argString) {
                      var args = new CodeMirror.StringStream(params.argString);
                      if (args.eat('!')) { reverse = true; }
                      if (args.eol()) { return; }
                      if (!args.eatSpace()) { return 'Invalid arguments'; }
                      var opts = args.match(/[a-z]+/);
                      if (opts) {
                        opts = opts[0];
                        ignoreCase = opts.indexOf('i') != -1;
                        unique = opts.indexOf('u') != -1;
                        var decimal = opts.indexOf('d') != -1 && 1;
                        var hex = opts.indexOf('x') != -1 && 1;
                        var octal = opts.indexOf('o') != -1 && 1;
                        if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
                        number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
                      }
                      if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; }
                    }
                  }
                  var err = parseArgs();
                  if (err) {
                    showConfirm(cm, err + ': ' + params.argString);
                    return;
                  }
                  var lineStart = params.line || cm.firstLine();
                  var lineEnd = params.lineEnd || params.line || cm.lastLine();
                  if (lineStart == lineEnd) { return; }
                  var curStart = Pos(lineStart, 0);
                  var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));
                  var text = cm.getRange(curStart, curEnd).split('\n');
                  var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ :
                     (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i :
                     (number == 'octal') ? /([0-7]+)/ : null;
                  var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null;
                  var numPart = [], textPart = [];
                  if (number) {
                    for (var i = 0; i < text.length; i++) {
                      if (numberRegex.exec(text[i])) {
                        numPart.push(text[i]);
                      } else {
                        textPart.push(text[i]);
                      }
                    }
                  } else {
                    textPart = text;
                  }
                  function compareFn(a, b) {
                    if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
                    if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); }
                    var anum = number && numberRegex.exec(a);
                    var bnum = number && numberRegex.exec(b);
                    if (!anum) { return a < b ? -1 : 1; }
                    anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix);
                    bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix);
                    return anum - bnum;
                  }
                  numPart.sort(compareFn);
                  textPart.sort(compareFn);
                  text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart);
                  if (unique) { // Remove duplicate lines
                    var textOld = text;
                    var lastLine;
                    text = [];
                    for (var i = 0; i < textOld.length; i++) {
                      if (textOld[i] != lastLine) {
                        text.push(textOld[i]);
                      }
                      lastLine = textOld[i];
                    }
                  }
                  cm.replaceRange(text.join('\n'), curStart, curEnd);
                },
                global: function(cm, params) {
                  // a global command is of the form
                  // :[range]g/pattern/[cmd]
                  // argString holds the string /pattern/[cmd]
                  var argString = params.argString;
                  if (!argString) {
                    showConfirm(cm, 'Regular Expression missing from global');
                    return;
                  }
                  // range is specified here
                  var lineStart = (params.line !== undefined) ? params.line : cm.firstLine();
                  var lineEnd = params.lineEnd || params.line || cm.lastLine();
                  // get the tokens from argString
                  var tokens = splitBySlash(argString);
                  var regexPart = argString, cmd;
                  if (tokens.length) {
                    regexPart = tokens[0];
                    cmd = tokens.slice(1, tokens.length).join('/');
                  }
                  if (regexPart) {
                    // If regex part is empty, then use the previous query. Otherwise
                    // use the regex part as the new query.
                    try {
                     updateSearchQuery(cm, regexPart, true /** ignoreCase */,
                       true /** smartCase */);
                    } catch (e) {
                     showConfirm(cm, 'Invalid regex: ' + regexPart);
                     return;
                    }
                  }
                  // now that we have the regexPart, search for regex matches in the
                  // specified range of lines
                  var query = getSearchState(cm).getQuery();
                  var matchedLines = [], content = '';
                  for (var i = lineStart; i <= lineEnd; i++) {
                    var matched = query.test(cm.getLine(i));
                    if (matched) {
                      matchedLines.push(i+1);
                      content+= cm.getLine(i) + '<br>';
                    }
                  }
                  // if there is no [cmd], just display the list of matched lines
                  if (!cmd) {
                    showConfirm(cm, content);
                    return;
                  }
                  var index = 0;
                  var nextCommand = function() {
                    if (index < matchedLines.length) {
                      var command = matchedLines[index] + cmd;
                      exCommandDispatcher.processCommand(cm, command, {
                        callback: nextCommand
                      });
                    }
                    index++;
                  };
                  nextCommand();
                },
                substitute: function(cm, params) {
                  if (!cm.getSearchCursor) {
                    throw new Error('Search feature not available. Requires searchcursor.js or ' +
                        'any other getSearchCursor implementation.');
                  }
                  var argString = params.argString;
                  var tokens = argString ? splitBySlash(argString) : [];
                  var regexPart, replacePart = '', trailing, flagsPart, count;
                  var confirm = false; // Whether to confirm each replace.
                  var global = false; // True to replace all instances on a line, false to replace only 1.
                  if (tokens.length) {
                    regexPart = tokens[0];
                    replacePart = tokens[1];
                    if (replacePart !== undefined) {
                      if (getOption('pcre')) {
                        replacePart = unescapeRegexReplace(replacePart);
                      } else {
                        replacePart = translateRegexReplace(replacePart);
                      }
                      vimGlobalState.lastSubstituteReplacePart = replacePart;
                    }
                    trailing = tokens[2] ? tokens[2].split(' ') : [];
                  } else {
                    // either the argString is empty or its of the form ' hello/world'
                    // actually splitBySlash returns a list of tokens
                    // only if the string starts with a '/'
                    if (argString && argString.length) {
                      showConfirm(cm, 'Substitutions should be of the form ' +
                          ':s/pattern/replace/');
                      return;
                    }
                  }
                  // After the 3rd slash, we can have flags followed by a space followed
                  // by count.
                  if (trailing) {
                    flagsPart = trailing[0];
                    count = parseInt(trailing[1]);
                    if (flagsPart) {
                      if (flagsPart.indexOf('c') != -1) {
                        confirm = true;
                        flagsPart.replace('c', '');
                      }
                      if (flagsPart.indexOf('g') != -1) {
                        global = true;
                        flagsPart.replace('g', '');
                      }
                      regexPart = regexPart + '/' + flagsPart;
                    }
                  }
                  if (regexPart) {
                    // If regex part is empty, then use the previous query. Otherwise use
                    // the regex part as the new query.
                    try {
                      updateSearchQuery(cm, regexPart, true /** ignoreCase */,
                        true /** smartCase */);
                    } catch (e) {
                      showConfirm(cm, 'Invalid regex: ' + regexPart);
                      return;
                    }
                  }
                  replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart;
                  if (replacePart === undefined) {
                    showConfirm(cm, 'No previous substitute regular expression');
                    return;
                  }
                  var state = getSearchState(cm);
                  var query = state.getQuery();
                  var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;
                  var lineEnd = params.lineEnd || lineStart;
                  if (count) {
                    lineStart = lineEnd;
                    lineEnd = lineStart + count - 1;
                  }
                  var startPos = clipCursorToContent(cm, Pos(lineStart, 0));
                  var cursor = cm.getSearchCursor(query, startPos);
                  doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback);
                },
                redo: CodeMirror.commands.redo,
                undo: CodeMirror.commands.undo,
                write: function(cm) {
                  if (CodeMirror.commands.save) {
                    // If a save command is defined, call it.
                    CodeMirror.commands.save(cm);
                  } else {
                    // Saves to text area if no save command is defined.
                    cm.save();
                  }
                },
                nohlsearch: function(cm) {
                  clearSearchHighlight(cm);
                },
                delmarks: function(cm, params) {
                  if (!params.argString || !trim(params.argString)) {
                    showConfirm(cm, 'Argument required');
                    return;
                  }
          
                  var state = cm.state.vim;
                  var stream = new CodeMirror.StringStream(trim(params.argString));
                  while (!stream.eol()) {
                    stream.eatSpace();
          
                    // Record the streams position at the beginning of the loop for use
                    // in error messages.
                    var count = stream.pos;
          
                    if (!stream.match(/[a-zA-Z]/, false)) {
                      showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
                      return;
                    }
          
                    var sym = stream.next();
                    // Check if this symbol is part of a range
                    if (stream.match('-', true)) {
                      // This symbol is part of a range.
          
                      // The range must terminate at an alphabetic character.
                      if (!stream.match(/[a-zA-Z]/, false)) {
                        showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
                        return;
                      }
          
                      var startMark = sym;
                      var finishMark = stream.next();
                      // The range must terminate at an alphabetic character which
                      // shares the same case as the start of the range.
                      if (isLowerCase(startMark) && isLowerCase(finishMark) ||
                          isUpperCase(startMark) && isUpperCase(finishMark)) {
                        var start = startMark.charCodeAt(0);
                        var finish = finishMark.charCodeAt(0);
                        if (start >= finish) {
                          showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
                          return;
                        }
          
                        // Because marks are always ASCII values, and we have
                        // determined that they are the same case, we can use
                        // their char codes to iterate through the defined range.
                        for (var j = 0; j <= finish - start; j++) {
                          var mark = String.fromCharCode(start + j);
                          delete state.marks[mark];
                        }
                      } else {
                        showConfirm(cm, 'Invalid argument: ' + startMark + '-');
                        return;
                      }
                    } else {
                      // This symbol is a valid mark, and is not part of a range.
                      delete state.marks[sym];
                    }
                  }
                }
              };
          
              var exCommandDispatcher = new ExCommandDispatcher();
          
              /**
              * @param {CodeMirror} cm CodeMirror instance we are in.
              * @param {boolean} confirm Whether to confirm each replace.
              * @param {Cursor} lineStart Line to start replacing from.
              * @param {Cursor} lineEnd Line to stop replacing at.
              * @param {RegExp} query Query for performing matches with.
              * @param {string} replaceWith Text to replace matches with. May contain $1,
              *     $2, etc for replacing captured groups using Javascript replace.
              * @param {function()} callback A callback for when the replace is done.
              */
              function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query,
                  replaceWith, callback) {
                // Set up all the functions.
                cm.state.vim.exMode = true;
                var done = false;
                var lastPos = searchCursor.from();
                function replaceAll() {
                  cm.operation(function() {
                    while (!done) {
                      replace();
                      next();
                    }
                    stop();
                  });
                }
                function replace() {
                  var text = cm.getRange(searchCursor.from(), searchCursor.to());
                  var newText = text.replace(query, replaceWith);
                  searchCursor.replace(newText);
                }
                function next() {
                  var found;
                  // The below only loops to skip over multiple occurrences on the same
                  // line when 'global' is not true.
                  while(found = searchCursor.findNext() &&
                        isInRange(searchCursor.from(), lineStart, lineEnd)) {
                    if (!global && lastPos && searchCursor.from().line == lastPos.line) {
                      continue;
                    }
                    cm.scrollIntoView(searchCursor.from(), 30);
                    cm.setSelection(searchCursor.from(), searchCursor.to());
                    lastPos = searchCursor.from();
                    done = false;
                    return;
                  }
                  done = true;
                }
                function stop(close) {
                  if (close) { close(); }
                  cm.focus();
                  if (lastPos) {
                    cm.setCursor(lastPos);
                    var vim = cm.state.vim;
                    vim.exMode = false;
                    vim.lastHPos = vim.lastHSPos = lastPos.ch;
                  }
                  if (callback) { callback(); }
                }
                function onPromptKeyDown(e, _value, close) {
                  // Swallow all keys.
                  CodeMirror.e_stop(e);
                  var keyName = CodeMirror.keyName(e);
                  switch (keyName) {
                    case 'Y':
                      replace(); next(); break;
                    case 'N':
                      next(); break;
                    case 'A':
                      // replaceAll contains a call to close of its own. We don't want it
                      // to fire too early or multiple times.
                      var savedCallback = callback;
                      callback = undefined;
                      cm.operation(replaceAll);
                      callback = savedCallback;
                      break;
                    case 'L':
                      replace();
                      // fall through and exit.
                    case 'Q':
                    case 'Esc':
                    case 'Ctrl-C':
                    case 'Ctrl-[':
                      stop(close);
                      break;
                  }
                  if (done) { stop(close); }
                  return true;
                }
          
                // Actually do replace.
                next();
                if (done) {
                  showConfirm(cm, 'No matches for ' + query.source);
                  return;
                }
                if (!confirm) {
                  replaceAll();
                  if (callback) { callback(); };
                  return;
                }
                showPrompt(cm, {
                  prefix: 'replace with <strong>' + replaceWith + '</strong> (y/n/a/q/l)',
                  onKeyDown: onPromptKeyDown
                });
              }
          
              CodeMirror.keyMap.vim = {
                attach: attachVimMap,
                detach: detachVimMap,
                call: cmKey
              };
          
              function exitInsertMode(cm) {
                var vim = cm.state.vim;
                var macroModeState = vimGlobalState.macroModeState;
                var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.');
                var isPlaying = macroModeState.isPlaying;
                var lastChange = macroModeState.lastInsertModeChanges;
                // In case of visual block, the insertModeChanges are not saved as a
                // single word, so we convert them to a single word
                // so as to update the ". register as expected in real vim.
                var text = [];
                if (!isPlaying) {
                  var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1;
                  var changes = lastChange.changes;
                  var text = [];
                  var i = 0;
                  // In case of multiple selections in blockwise visual,
                  // the inserted text, for example: 'f<Backspace>oo', is stored as
                  // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines).
                  // We push the contents of the changes array as per the following:
                  // 1. In case of InsertModeKey, just increment by 1.
                  // 2. In case of a character, jump by selLength (2 in the example).
                  while (i < changes.length) {
                    // This loop will convert 'ff<bs>oooo' to 'f<bs>oo'.
                    text.push(changes[i]);
                    if (changes[i] instanceof InsertModeKey) {
                       i++;
                    } else {
                       i+= selLength;
                    }
                  }
                  lastChange.changes = text;
                  cm.off('change', onChange);
                  CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
                }
                if (!isPlaying && vim.insertModeRepeat > 1) {
                  // Perform insert mode repeat for commands like 3,a and 3,o.
                  repeatLastEdit(cm, vim, vim.insertModeRepeat - 1,
                      true /** repeatForInsert */);
                  vim.lastEditInputState.repeatOverride = vim.insertModeRepeat;
                }
                delete vim.insertModeRepeat;
                vim.insertMode = false;
                cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1);
                cm.setOption('keyMap', 'vim');
                cm.setOption('disableInput', true);
                cm.toggleOverwrite(false); // exit replace mode if we were in it.
                // update the ". register before exiting insert mode
                insertModeChangeRegister.setText(lastChange.changes.join(''));
                CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
                if (macroModeState.isRecording) {
                  logInsertModeChange(macroModeState);
                }
              }
          
              function _mapCommand(command) {
                defaultKeymap.push(command);
              }
          
              function mapCommand(keys, type, name, args, extra) {
                var command = {keys: keys, type: type};
                command[type] = name;
                command[type + "Args"] = args;
                for (var key in extra)
                  command[key] = extra[key];
                _mapCommand(command);
              }
          
              // The timeout in milliseconds for the two-character ESC keymap should be
              // adjusted according to your typing speed to prevent false positives.
              defineOption('insertModeEscKeysTimeout', 200, 'number');
          
              CodeMirror.keyMap['vim-insert'] = {
                // TODO: override navigation keys so that Esc will cancel automatic
                // indentation from o, O, i_<CR>
                'Ctrl-N': 'autocomplete',
                'Ctrl-P': 'autocomplete',
                'Enter': function(cm) {
                  var fn = CodeMirror.commands.newlineAndIndentContinueComment ||
                      CodeMirror.commands.newlineAndIndent;
                  fn(cm);
                },
                fallthrough: ['default'],
                attach: attachVimMap,
                detach: detachVimMap,
                call: cmKey
              };
          
              CodeMirror.keyMap['vim-replace'] = {
                'Backspace': 'goCharLeft',
                fallthrough: ['vim-insert'],
                attach: attachVimMap,
                detach: detachVimMap,
                call: cmKey
              };
          
              function executeMacroRegister(cm, vim, macroModeState, registerName) {
                var register = vimGlobalState.registerController.getRegister(registerName);
                var keyBuffer = register.keyBuffer;
                var imc = 0;
                macroModeState.isPlaying = true;
                macroModeState.replaySearchQueries = register.searchQueries.slice(0);
                for (var i = 0; i < keyBuffer.length; i++) {
                  var text = keyBuffer[i];
                  var match, key;
                  while (text) {
                    // Pull off one command key, which is either a single character
                    // or a special sequence wrapped in '<' and '>', e.g. '<Space>'.
                    match = (/<\w+-.+?>|<\w+>|./).exec(text);
                    key = match[0];
                    text = text.substring(match.index + key.length);
                    CodeMirror.Vim.handleKey(cm, key, 'macro');
                    if (vim.insertMode) {
                      var changes = register.insertModeChanges[imc++].changes;
                      vimGlobalState.macroModeState.lastInsertModeChanges.changes =
                          changes;
                      repeatInsertModeChanges(cm, changes, 1);
                      exitInsertMode(cm);
                    }
                  }
                };
                macroModeState.isPlaying = false;
              }
          
              function logKey(macroModeState, key) {
                if (macroModeState.isPlaying) { return; }
                var registerName = macroModeState.latestRegister;
                var register = vimGlobalState.registerController.getRegister(registerName);
                if (register) {
                  register.pushText(key);
                }
              }
          
              function logInsertModeChange(macroModeState) {
                if (macroModeState.isPlaying) { return; }
                var registerName = macroModeState.latestRegister;
                var register = vimGlobalState.registerController.getRegister(registerName);
                if (register) {
                  register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
                }
              }
          
              function logSearchQuery(macroModeState, query) {
                if (macroModeState.isPlaying) { return; }
                var registerName = macroModeState.latestRegister;
                var register = vimGlobalState.registerController.getRegister(registerName);
                if (register) {
                  register.pushSearchQuery(query);
                }
              }
          
              /**
               * Listens for changes made in insert mode.
               * Should only be active in insert mode.
               */
              function onChange(_cm, changeObj) {
                var macroModeState = vimGlobalState.macroModeState;
                var lastChange = macroModeState.lastInsertModeChanges;
                if (!macroModeState.isPlaying) {
                  while(changeObj) {
                    lastChange.expectCursorActivityForChange = true;
                    if (changeObj.origin == '+input' || changeObj.origin == 'paste'
                        || changeObj.origin === undefined /* only in testing */) {
                      var text = changeObj.text.join('\n');
                      lastChange.changes.push(text);
                    }
                    // Change objects may be chained with next.
                    changeObj = changeObj.next;
                  }
                }
              }
          
              /**
              * Listens for any kind of cursor activity on CodeMirror.
              */
              function onCursorActivity(cm) {
                var vim = cm.state.vim;
                if (vim.insertMode) {
                  // Tracking cursor activity in insert mode (for macro support).
                  var macroModeState = vimGlobalState.macroModeState;
                  if (macroModeState.isPlaying) { return; }
                  var lastChange = macroModeState.lastInsertModeChanges;
                  if (lastChange.expectCursorActivityForChange) {
                    lastChange.expectCursorActivityForChange = false;
                  } else {
                    // Cursor moved outside the context of an edit. Reset the change.
                    lastChange.changes = [];
                  }
                } else if (!cm.curOp.isVimOp) {
                  handleExternalSelection(cm, vim);
                }
                if (vim.visualMode) {
                  updateFakeCursor(cm);
                }
              }
              function updateFakeCursor(cm) {
                var vim = cm.state.vim;
                var from = copyCursor(vim.sel.head);
                var to = offsetCursor(from, 0, 1);
                if (vim.fakeCursor) {
                  vim.fakeCursor.clear();
                }
                vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'});
              }
              function handleExternalSelection(cm, vim) {
                var anchor = cm.getCursor('anchor');
                var head = cm.getCursor('head');
                // Enter or exit visual mode to match mouse selection.
                if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) {
                  exitVisualMode(cm, false);
                } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
                  vim.visualMode = true;
                  vim.visualLine = false;
                  CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});
                }
                if (vim.visualMode) {
                  // Bind CodeMirror selection model to vim selection model.
                  // Mouse selections are considered visual characterwise.
                  var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
                  var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
                  head = offsetCursor(head, 0, headOffset);
                  anchor = offsetCursor(anchor, 0, anchorOffset);
                  vim.sel = {
                    anchor: anchor,
                    head: head
                  };
                  updateMark(cm, vim, '<', cursorMin(head, anchor));
                  updateMark(cm, vim, '>', cursorMax(head, anchor));
                } else if (!vim.insertMode) {
                  // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse.
                  vim.lastHPos = cm.getCursor().ch;
                }
              }
          
              /** Wrapper for special keys pressed in insert mode */
              function InsertModeKey(keyName) {
                this.keyName = keyName;
              }
          
              /**
              * Handles raw key down events from the text area.
              * - Should only be active in insert mode.
              * - For recording deletes in insert mode.
              */
              function onKeyEventTargetKeyDown(e) {
                var macroModeState = vimGlobalState.macroModeState;
                var lastChange = macroModeState.lastInsertModeChanges;
                var keyName = CodeMirror.keyName(e);
                if (!keyName) { return; }
                function onKeyFound() {
                  lastChange.changes.push(new InsertModeKey(keyName));
                  return true;
                }
                if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) {
                  CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound);
                }
              }
          
              /**
               * Repeats the last edit, which includes exactly 1 command and at most 1
               * insert. Operator and motion commands are read from lastEditInputState,
               * while action commands are read from lastEditActionCommand.
               *
               * If repeatForInsert is true, then the function was called by
               * exitInsertMode to repeat the insert mode changes the user just made. The
               * corresponding enterInsertMode call was made with a count.
               */
              function repeatLastEdit(cm, vim, repeat, repeatForInsert) {
                var macroModeState = vimGlobalState.macroModeState;
                macroModeState.isPlaying = true;
                var isAction = !!vim.lastEditActionCommand;
                var cachedInputState = vim.inputState;
                function repeatCommand() {
                  if (isAction) {
                    commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand);
                  } else {
                    commandDispatcher.evalInput(cm, vim);
                  }
                }
                function repeatInsert(repeat) {
                  if (macroModeState.lastInsertModeChanges.changes.length > 0) {
                    // For some reason, repeat cw in desktop VIM does not repeat
                    // insert mode changes. Will conform to that behavior.
                    repeat = !vim.lastEditActionCommand ? 1 : repeat;
                    var changeObject = macroModeState.lastInsertModeChanges;
                    repeatInsertModeChanges(cm, changeObject.changes, repeat);
                  }
                }
                vim.inputState = vim.lastEditInputState;
                if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) {
                  // o and O repeat have to be interlaced with insert repeats so that the
                  // insertions appear on separate lines instead of the last line.
                  for (var i = 0; i < repeat; i++) {
                    repeatCommand();
                    repeatInsert(1);
                  }
                } else {
                  if (!repeatForInsert) {
                    // Hack to get the cursor to end up at the right place. If I is
                    // repeated in insert mode repeat, cursor will be 1 insert
                    // change set left of where it should be.
                    repeatCommand();
                  }
                  repeatInsert(repeat);
                }
                vim.inputState = cachedInputState;
                if (vim.insertMode && !repeatForInsert) {
                  // Don't exit insert mode twice. If repeatForInsert is set, then we
                  // were called by an exitInsertMode call lower on the stack.
                  exitInsertMode(cm);
                }
                macroModeState.isPlaying = false;
              };
          
              function repeatInsertModeChanges(cm, changes, repeat) {
                function keyHandler(binding) {
                  if (typeof binding == 'string') {
                    CodeMirror.commands[binding](cm);
                  } else {
                    binding(cm);
                  }
                  return true;
                }
                var head = cm.getCursor('head');
                var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock;
                if (inVisualBlock) {
                  // Set up block selection again for repeating the changes.
                  var vim = cm.state.vim;
                  var lastSel = vim.lastSelection;
                  var offset = getOffset(lastSel.anchor, lastSel.head);
                  selectForInsert(cm, head, offset.line + 1);
                  repeat = cm.listSelections().length;
                  cm.setCursor(head);
                }
                for (var i = 0; i < repeat; i++) {
                  if (inVisualBlock) {
                    cm.setCursor(offsetCursor(head, i, 0));
                  }
                  for (var j = 0; j < changes.length; j++) {
                    var change = changes[j];
                    if (change instanceof InsertModeKey) {
                      CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler);
                    } else {
                      var cur = cm.getCursor();
                      cm.replaceRange(change, cur, cur);
                    }
                  }
                }
                if (inVisualBlock) {
                  cm.setCursor(offsetCursor(head, 0, 1));
                }
              }
          
              resetVimGlobalState();
              return vimApi;
            };
            // Initialize Vim and make it available as an API.
            CodeMirror.Vim = Vim();
          });
          
      • lib
        • codemirror.css
          /* BASICS */
          
          .CodeMirror {
            /* Set height, width, borders, and global font properties here */
            font-family: monospace;
            height: 300px;
            color: black;
          }
          
          /* PADDING */
          
          .CodeMirror-lines {
            padding: 4px 0; /* Vertical padding around content */
          }
          .CodeMirror pre {
            padding: 0 4px; /* Horizontal padding of content */
          }
          
          .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
            background-color: white; /* The little square between H and V scrollbars */
          }
          
          /* GUTTER */
          
          .CodeMirror-gutters {
            border-right: 1px solid #ddd;
            background-color: #f7f7f7;
            white-space: nowrap;
          }
          .CodeMirror-linenumbers {}
          .CodeMirror-linenumber {
            padding: 0 3px 0 5px;
            min-width: 20px;
            text-align: right;
            color: #999;
            -moz-box-sizing: content-box;
            box-sizing: content-box;
          }
          
          .CodeMirror-guttermarker { color: black; }
          .CodeMirror-guttermarker-subtle { color: #999; }
          
          /* CURSOR */
          
          .CodeMirror div.CodeMirror-cursor {
            border-left: 1px solid black;
          }
          /* Shown when moving in bi-directional text */
          .CodeMirror div.CodeMirror-secondarycursor {
            border-left: 1px solid silver;
          }
          .CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
            width: auto;
            border: 0;
            background: #7e7;
          }
          .CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
            z-index: 1;
          }
          
          .cm-animate-fat-cursor {
            width: auto;
            border: 0;
            -webkit-animation: blink 1.06s steps(1) infinite;
            -moz-animation: blink 1.06s steps(1) infinite;
            animation: blink 1.06s steps(1) infinite;
          }
          @-moz-keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          @-webkit-keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          @keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          
          /* Can style cursor different in overwrite (non-insert) mode */
          div.CodeMirror-overwrite div.CodeMirror-cursor {}
          
          .cm-tab { display: inline-block; text-decoration: inherit; }
          
          .CodeMirror-ruler {
            border-left: 1px solid #ccc;
            position: absolute;
          }
          
          /* DEFAULT THEME */
          
          .cm-s-default .cm-keyword {color: #708;}
          .cm-s-default .cm-atom {color: #219;}
          .cm-s-default .cm-number {color: #164;}
          .cm-s-default .cm-def {color: #00f;}
          .cm-s-default .cm-variable,
          .cm-s-default .cm-punctuation,
          .cm-s-default .cm-property,
          .cm-s-default .cm-operator {}
          .cm-s-default .cm-variable-2 {color: #05a;}
          .cm-s-default .cm-variable-3 {color: #085;}
          .cm-s-default .cm-comment {color: #a50;}
          .cm-s-default .cm-string {color: #a11;}
          .cm-s-default .cm-string-2 {color: #f50;}
          .cm-s-default .cm-meta {color: #555;}
          .cm-s-default .cm-qualifier {color: #555;}
          .cm-s-default .cm-builtin {color: #30a;}
          .cm-s-default .cm-bracket {color: #997;}
          .cm-s-default .cm-tag {color: #170;}
          .cm-s-default .cm-attribute {color: #00c;}
          .cm-s-default .cm-header {color: blue;}
          .cm-s-default .cm-quote {color: #090;}
          .cm-s-default .cm-hr {color: #999;}
          .cm-s-default .cm-link {color: #00c;}
          
          .cm-negative {color: #d44;}
          .cm-positive {color: #292;}
          .cm-header, .cm-strong {font-weight: bold;}
          .cm-em {font-style: italic;}
          .cm-link {text-decoration: underline;}
          .cm-strikethrough {text-decoration: line-through;}
          
          .cm-s-default .cm-error {color: #f00;}
          .cm-invalidchar {color: #f00;}
          
          /* Default styles for common addons */
          
          div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
          div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
          .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
          .CodeMirror-activeline-background {background: #e8f2ff;}
          
          /* STOP */
          
          /* The rest of this file contains styles related to the mechanics of
             the editor. You probably shouldn't touch them. */
          
          .CodeMirror {
            position: relative;
            overflow: hidden;
            background: white;
          }
          
          .CodeMirror-scroll {
            overflow: scroll !important; /* Things will break if this is overridden */
            /* 30px is the magic margin used to hide the element's real scrollbars */
            /* See overflow: hidden in .CodeMirror */
            margin-bottom: -30px; margin-right: -30px;
            padding-bottom: 30px;
            height: 100%;
            outline: none; /* Prevent dragging from highlighting the element */
            position: relative;
            -moz-box-sizing: content-box;
            box-sizing: content-box;
          }
          .CodeMirror-sizer {
            position: relative;
            border-right: 30px solid transparent;
            -moz-box-sizing: content-box;
            box-sizing: content-box;
          }
          
          /* The fake, visible scrollbars. Used to force redraw during scrolling
             before actuall scrolling happens, thus preventing shaking and
             flickering artifacts. */
          .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
            position: absolute;
            z-index: 6;
            display: none;
          }
          .CodeMirror-vscrollbar {
            right: 0; top: 0;
            overflow-x: hidden;
            overflow-y: scroll;
          }
          .CodeMirror-hscrollbar {
            bottom: 0; left: 0;
            overflow-y: hidden;
            overflow-x: scroll;
          }
          .CodeMirror-scrollbar-filler {
            right: 0; bottom: 0;
          }
          .CodeMirror-gutter-filler {
            left: 0; bottom: 0;
          }
          
          .CodeMirror-gutters {
            position: absolute; left: 0; top: 0;
            z-index: 3;
          }
          .CodeMirror-gutter {
            white-space: normal;
            height: 100%;
            -moz-box-sizing: content-box;
            box-sizing: content-box;
            display: inline-block;
            margin-bottom: -30px;
            /* Hack to make IE7 behave */
            *zoom:1;
            *display:inline;
          }
          .CodeMirror-gutter-wrapper {
            position: absolute;
            z-index: 4;
            height: 100%;
          }
          .CodeMirror-gutter-elt {
            position: absolute;
            cursor: default;
            z-index: 4;
          }
          .CodeMirror-gutter-wrapper {
            -webkit-user-select: none;
            -moz-user-select: none;
            user-select: none;
          }
          
          .CodeMirror-lines {
            cursor: text;
            min-height: 1px; /* prevents collapsing before first draw */
          }
          .CodeMirror pre {
            /* Reset some styles that the rest of the page might have set */
            -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
            border-width: 0;
            background: transparent;
            font-family: inherit;
            font-size: inherit;
            margin: 0;
            white-space: pre;
            word-wrap: normal;
            line-height: inherit;
            color: inherit;
            z-index: 2;
            position: relative;
            overflow: visible;
            -webkit-tap-highlight-color: transparent;
          }
          .CodeMirror-wrap pre {
            word-wrap: break-word;
            white-space: pre-wrap;
            word-break: normal;
          }
          
          .CodeMirror-linebackground {
            position: absolute;
            left: 0; right: 0; top: 0; bottom: 0;
            z-index: 0;
          }
          
          .CodeMirror-linewidget {
            position: relative;
            z-index: 2;
            overflow: auto;
          }
          
          .CodeMirror-widget {}
          
          .CodeMirror-code {
            outline: none;
          }
          
          .CodeMirror-measure {
            position: absolute;
            width: 100%;
            height: 0;
            overflow: hidden;
            visibility: hidden;
          }
          .CodeMirror-measure pre { position: static; }
          
          .CodeMirror div.CodeMirror-cursor {
            position: absolute;
            border-right: none;
            width: 0;
          }
          
          div.CodeMirror-cursors {
            visibility: hidden;
            position: relative;
            z-index: 3;
          }
          .CodeMirror-focused div.CodeMirror-cursors {
            visibility: visible;
          }
          
          .CodeMirror-selected { background: #d9d9d9; }
          .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
          .CodeMirror-crosshair { cursor: crosshair; }
          .CodeMirror ::selection { background: #d7d4f0; }
          .CodeMirror ::-moz-selection { background: #d7d4f0; }
          
          .cm-searching {
            background: #ffa;
            background: rgba(255, 255, 0, .4);
          }
          
          /* IE7 hack to prevent it from returning funny offsetTops on the spans */
          .CodeMirror span { *vertical-align: text-bottom; }
          
          /* Used to force a border model for a node */
          .cm-force-border { padding-right: .1px; }
          
          @media print {
            /* Hide the cursor when printing */
            .CodeMirror div.CodeMirror-cursors {
              visibility: hidden;
            }
          }
          
          /* See issue #2901 */
          .cm-tab-wrap-hack:after { content: ''; }
          
          /* Help users use markselection to safely style text background */
          span.CodeMirror-selectedtext { background: none; }
          
        • codemirror.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          // This is CodeMirror (http://codemirror.net), a code editor
          // implemented in JavaScript on top of the browser's DOM.
          //
          // You can find some technical background for some of the code below
          // at http://marijnhaverbeke.nl/blog/#cm-internals .
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              module.exports = mod();
            else if (typeof define == "function" && define.amd) // AMD
              return define([], mod);
            else // Plain browser env
              this.CodeMirror = mod();
          })(function() {
            "use strict";
          
            // BROWSER SNIFFING
          
            // Kludges for bugs and behavior differences that can't be feature
            // detected are enabled based on userAgent etc sniffing.
          
            var gecko = /gecko\/\d/i.test(navigator.userAgent);
            var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
            var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
            var ie = ie_upto10 || ie_11up;
            var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
            var webkit = /WebKit\//.test(navigator.userAgent);
            var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
            var chrome = /Chrome\//.test(navigator.userAgent);
            var presto = /Opera\//.test(navigator.userAgent);
            var safari = /Apple Computer/.test(navigator.vendor);
            var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
            var phantom = /PhantomJS/.test(navigator.userAgent);
          
            var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
            // This is woefully incomplete. Suggestions for alternative methods welcome.
            var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
            var mac = ios || /Mac/.test(navigator.platform);
            var windows = /win/i.test(navigator.platform);
          
            var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
            if (presto_version) presto_version = Number(presto_version[1]);
            if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
            // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
            var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
            var captureRightClick = gecko || (ie && ie_version >= 9);
          
            // Optimize some code when these features are not used.
            var sawReadOnlySpans = false, sawCollapsedSpans = false;
          
            // EDITOR CONSTRUCTOR
          
            // A CodeMirror instance represents an editor. This is the object
            // that user code is usually dealing with.
          
            function CodeMirror(place, options) {
              if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
          
              this.options = options = options ? copyObj(options) : {};
              // Determine effective options based on given values and defaults.
              copyObj(defaults, options, false);
              setGuttersForLineNumbers(options);
          
              var doc = options.value;
              if (typeof doc == "string") doc = new Doc(doc, options.mode);
              this.doc = doc;
          
              var input = new CodeMirror.inputStyles[options.inputStyle](this);
              var display = this.display = new Display(place, doc, input);
              display.wrapper.CodeMirror = this;
              updateGutters(this);
              themeChanged(this);
              if (options.lineWrapping)
                this.display.wrapper.className += " CodeMirror-wrap";
              if (options.autofocus && !mobile) display.input.focus();
              initScrollbars(this);
          
              this.state = {
                keyMaps: [],  // stores maps added by addKeyMap
                overlays: [], // highlighting overlays, as added by addOverlay
                modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
                overwrite: false, focused: false,
                suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
                pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
                draggingText: false,
                highlight: new Delayed(), // stores highlight worker timeout
                keySeq: null  // Unfinished key sequence
              };
          
              var cm = this;
          
              // Override magic textarea content restore that IE sometimes does
              // on our hidden textarea on reload
              if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
          
              registerEventHandlers(this);
              ensureGlobalHandlers();
          
              startOperation(this);
              this.curOp.forceUpdate = true;
              attachDoc(this, doc);
          
              if ((options.autofocus && !mobile) || cm.hasFocus())
                setTimeout(bind(onFocus, this), 20);
              else
                onBlur(this);
          
              for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
                optionHandlers[opt](this, options[opt], Init);
              maybeUpdateLineNumberWidth(this);
              if (options.finishInit) options.finishInit(this);
              for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
              endOperation(this);
              // Suppress optimizelegibility in Webkit, since it breaks text
              // measuring on line wrapping boundaries.
              if (webkit && options.lineWrapping &&
                  getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
                display.lineDiv.style.textRendering = "auto";
            }
          
            // DISPLAY CONSTRUCTOR
          
            // The display handles the DOM integration, both for input reading
            // and content drawing. It holds references to DOM nodes and
            // display-related state.
          
            function Display(place, doc, input) {
              var d = this;
              this.input = input;
          
              // Covers bottom-right square when both scrollbars are present.
              d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
              d.scrollbarFiller.setAttribute("cm-not-content", "true");
              // Covers bottom of gutter when coverGutterNextToScrollbar is on
              // and h scrollbar is present.
              d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
              d.gutterFiller.setAttribute("cm-not-content", "true");
              // Will contain the actual code, positioned to cover the viewport.
              d.lineDiv = elt("div", null, "CodeMirror-code");
              // Elements are added to these to represent selection and cursors.
              d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
              d.cursorDiv = elt("div", null, "CodeMirror-cursors");
              // A visibility: hidden element used to find the size of things.
              d.measure = elt("div", null, "CodeMirror-measure");
              // When lines outside of the viewport are measured, they are drawn in this.
              d.lineMeasure = elt("div", null, "CodeMirror-measure");
              // Wraps everything that needs to exist inside the vertically-padded coordinate system
              d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
                                null, "position: relative; outline: none");
              // Moved around its parent to cover visible view.
              d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
              // Set to the height of the document, allowing scrolling.
              d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
              d.sizerWidth = null;
              // Behavior of elts with overflow: auto and padding is
              // inconsistent across browsers. This is used to ensure the
              // scrollable area is big enough.
              d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
              // Will contain the gutters, if any.
              d.gutters = elt("div", null, "CodeMirror-gutters");
              d.lineGutter = null;
              // Actual scrollable element.
              d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
              d.scroller.setAttribute("tabIndex", "-1");
              // The element in which the editor lives.
              d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
          
              // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
              if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
              if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
          
              if (place) {
                if (place.appendChild) place.appendChild(d.wrapper);
                else place(d.wrapper);
              }
          
              // Current rendered range (may be bigger than the view window).
              d.viewFrom = d.viewTo = doc.first;
              d.reportedViewFrom = d.reportedViewTo = doc.first;
              // Information about the rendered lines.
              d.view = [];
              d.renderedView = null;
              // Holds info about a single rendered line when it was rendered
              // for measurement, while not in view.
              d.externalMeasured = null;
              // Empty space (in pixels) above the view
              d.viewOffset = 0;
              d.lastWrapHeight = d.lastWrapWidth = 0;
              d.updateLineNumbers = null;
          
              d.nativeBarWidth = d.barHeight = d.barWidth = 0;
              d.scrollbarsClipped = false;
          
              // Used to only resize the line number gutter when necessary (when
              // the amount of lines crosses a boundary that makes its width change)
              d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
              // Set to true when a non-horizontal-scrolling line widget is
              // added. As an optimization, line widget aligning is skipped when
              // this is false.
              d.alignWidgets = false;
          
              d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
          
              // Tracks the maximum line length so that the horizontal scrollbar
              // can be kept static when scrolling.
              d.maxLine = null;
              d.maxLineLength = 0;
              d.maxLineChanged = false;
          
              // Used for measuring wheel scrolling granularity
              d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
          
              // True when shift is held down.
              d.shift = false;
          
              // Used to track whether anything happened since the context menu
              // was opened.
              d.selForContextMenu = null;
          
              d.activeTouch = null;
          
              input.init(d);
            }
          
            // STATE UPDATES
          
            // Used to get the editor into a consistent state again when options change.
          
            function loadMode(cm) {
              cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
              resetModeState(cm);
            }
          
            function resetModeState(cm) {
              cm.doc.iter(function(line) {
                if (line.stateAfter) line.stateAfter = null;
                if (line.styles) line.styles = null;
              });
              cm.doc.frontier = cm.doc.first;
              startWorker(cm, 100);
              cm.state.modeGen++;
              if (cm.curOp) regChange(cm);
            }
          
            function wrappingChanged(cm) {
              if (cm.options.lineWrapping) {
                addClass(cm.display.wrapper, "CodeMirror-wrap");
                cm.display.sizer.style.minWidth = "";
                cm.display.sizerWidth = null;
              } else {
                rmClass(cm.display.wrapper, "CodeMirror-wrap");
                findMaxLine(cm);
              }
              estimateLineHeights(cm);
              regChange(cm);
              clearCaches(cm);
              setTimeout(function(){updateScrollbars(cm);}, 100);
            }
          
            // Returns a function that estimates the height of a line, to use as
            // first approximation until the line becomes visible (and is thus
            // properly measurable).
            function estimateHeight(cm) {
              var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
              var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
              return function(line) {
                if (lineIsHidden(cm.doc, line)) return 0;
          
                var widgetsHeight = 0;
                if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
                  if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
                }
          
                if (wrapping)
                  return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
                else
                  return widgetsHeight + th;
              };
            }
          
            function estimateLineHeights(cm) {
              var doc = cm.doc, est = estimateHeight(cm);
              doc.iter(function(line) {
                var estHeight = est(line);
                if (estHeight != line.height) updateLineHeight(line, estHeight);
              });
            }
          
            function themeChanged(cm) {
              cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
                cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
              clearCaches(cm);
            }
          
            function guttersChanged(cm) {
              updateGutters(cm);
              regChange(cm);
              setTimeout(function(){alignHorizontally(cm);}, 20);
            }
          
            // Rebuild the gutter elements, ensure the margin to the left of the
            // code matches their width.
            function updateGutters(cm) {
              var gutters = cm.display.gutters, specs = cm.options.gutters;
              removeChildren(gutters);
              for (var i = 0; i < specs.length; ++i) {
                var gutterClass = specs[i];
                var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
                if (gutterClass == "CodeMirror-linenumbers") {
                  cm.display.lineGutter = gElt;
                  gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
                }
              }
              gutters.style.display = i ? "" : "none";
              updateGutterSpace(cm);
            }
          
            function updateGutterSpace(cm) {
              var width = cm.display.gutters.offsetWidth;
              cm.display.sizer.style.marginLeft = width + "px";
            }
          
            // Compute the character length of a line, taking into account
            // collapsed ranges (see markText) that might hide parts, and join
            // other lines onto it.
            function lineLength(line) {
              if (line.height == 0) return 0;
              var len = line.text.length, merged, cur = line;
              while (merged = collapsedSpanAtStart(cur)) {
                var found = merged.find(0, true);
                cur = found.from.line;
                len += found.from.ch - found.to.ch;
              }
              cur = line;
              while (merged = collapsedSpanAtEnd(cur)) {
                var found = merged.find(0, true);
                len -= cur.text.length - found.from.ch;
                cur = found.to.line;
                len += cur.text.length - found.to.ch;
              }
              return len;
            }
          
            // Find the longest line in the document.
            function findMaxLine(cm) {
              var d = cm.display, doc = cm.doc;
              d.maxLine = getLine(doc, doc.first);
              d.maxLineLength = lineLength(d.maxLine);
              d.maxLineChanged = true;
              doc.iter(function(line) {
                var len = lineLength(line);
                if (len > d.maxLineLength) {
                  d.maxLineLength = len;
                  d.maxLine = line;
                }
              });
            }
          
            // Make sure the gutters options contains the element
            // "CodeMirror-linenumbers" when the lineNumbers option is true.
            function setGuttersForLineNumbers(options) {
              var found = indexOf(options.gutters, "CodeMirror-linenumbers");
              if (found == -1 && options.lineNumbers) {
                options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
              } else if (found > -1 && !options.lineNumbers) {
                options.gutters = options.gutters.slice(0);
                options.gutters.splice(found, 1);
              }
            }
          
            // SCROLLBARS
          
            // Prepare DOM reads needed to update the scrollbars. Done in one
            // shot to minimize update/measure roundtrips.
            function measureForScrollbars(cm) {
              var d = cm.display, gutterW = d.gutters.offsetWidth;
              var docH = Math.round(cm.doc.height + paddingVert(cm.display));
              return {
                clientHeight: d.scroller.clientHeight,
                viewHeight: d.wrapper.clientHeight,
                scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
                viewWidth: d.wrapper.clientWidth,
                barLeft: cm.options.fixedGutter ? gutterW : 0,
                docHeight: docH,
                scrollHeight: docH + scrollGap(cm) + d.barHeight,
                nativeBarWidth: d.nativeBarWidth,
                gutterWidth: gutterW
              };
            }
          
            function NativeScrollbars(place, scroll, cm) {
              this.cm = cm;
              var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
              var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
              place(vert); place(horiz);
          
              on(vert, "scroll", function() {
                if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
              });
              on(horiz, "scroll", function() {
                if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
              });
          
              this.checkedOverlay = false;
              // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
              if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
            }
          
            NativeScrollbars.prototype = copyObj({
              update: function(measure) {
                var needsH = measure.scrollWidth > measure.clientWidth + 1;
                var needsV = measure.scrollHeight > measure.clientHeight + 1;
                var sWidth = measure.nativeBarWidth;
          
                if (needsV) {
                  this.vert.style.display = "block";
                  this.vert.style.bottom = needsH ? sWidth + "px" : "0";
                  var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
                  // A bug in IE8 can cause this value to be negative, so guard it.
                  this.vert.firstChild.style.height =
                    Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
                } else {
                  this.vert.style.display = "";
                  this.vert.firstChild.style.height = "0";
                }
          
                if (needsH) {
                  this.horiz.style.display = "block";
                  this.horiz.style.right = needsV ? sWidth + "px" : "0";
                  this.horiz.style.left = measure.barLeft + "px";
                  var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
                  this.horiz.firstChild.style.width =
                    (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
                } else {
                  this.horiz.style.display = "";
                  this.horiz.firstChild.style.width = "0";
                }
          
                if (!this.checkedOverlay && measure.clientHeight > 0) {
                  if (sWidth == 0) this.overlayHack();
                  this.checkedOverlay = true;
                }
          
                return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
              },
              setScrollLeft: function(pos) {
                if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
              },
              setScrollTop: function(pos) {
                if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
              },
              overlayHack: function() {
                var w = mac && !mac_geMountainLion ? "12px" : "18px";
                this.horiz.style.minHeight = this.vert.style.minWidth = w;
                var self = this;
                var barMouseDown = function(e) {
                  if (e_target(e) != self.vert && e_target(e) != self.horiz)
                    operation(self.cm, onMouseDown)(e);
                };
                on(this.vert, "mousedown", barMouseDown);
                on(this.horiz, "mousedown", barMouseDown);
              },
              clear: function() {
                var parent = this.horiz.parentNode;
                parent.removeChild(this.horiz);
                parent.removeChild(this.vert);
              }
            }, NativeScrollbars.prototype);
          
            function NullScrollbars() {}
          
            NullScrollbars.prototype = copyObj({
              update: function() { return {bottom: 0, right: 0}; },
              setScrollLeft: function() {},
              setScrollTop: function() {},
              clear: function() {}
            }, NullScrollbars.prototype);
          
            CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
          
            function initScrollbars(cm) {
              if (cm.display.scrollbars) {
                cm.display.scrollbars.clear();
                if (cm.display.scrollbars.addClass)
                  rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
              }
          
              cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
                cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
                // Prevent clicks in the scrollbars from killing focus
                on(node, "mousedown", function() {
                  if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
                });
                node.setAttribute("cm-not-content", "true");
              }, function(pos, axis) {
                if (axis == "horizontal") setScrollLeft(cm, pos);
                else setScrollTop(cm, pos);
              }, cm);
              if (cm.display.scrollbars.addClass)
                addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
            }
          
            function updateScrollbars(cm, measure) {
              if (!measure) measure = measureForScrollbars(cm);
              var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
              updateScrollbarsInner(cm, measure);
              for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
                if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
                  updateHeightsInViewport(cm);
                updateScrollbarsInner(cm, measureForScrollbars(cm));
                startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
              }
            }
          
            // Re-synchronize the fake scrollbars with the actual size of the
            // content.
            function updateScrollbarsInner(cm, measure) {
              var d = cm.display;
              var sizes = d.scrollbars.update(measure);
          
              d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
              d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
          
              if (sizes.right && sizes.bottom) {
                d.scrollbarFiller.style.display = "block";
                d.scrollbarFiller.style.height = sizes.bottom + "px";
                d.scrollbarFiller.style.width = sizes.right + "px";
              } else d.scrollbarFiller.style.display = "";
              if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
                d.gutterFiller.style.display = "block";
                d.gutterFiller.style.height = sizes.bottom + "px";
                d.gutterFiller.style.width = measure.gutterWidth + "px";
              } else d.gutterFiller.style.display = "";
            }
          
            // Compute the lines that are visible in a given viewport (defaults
            // the the current scroll position). viewport may contain top,
            // height, and ensure (see op.scrollToPos) properties.
            function visibleLines(display, doc, viewport) {
              var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
              top = Math.floor(top - paddingTop(display));
              var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
          
              var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
              // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
              // forces those lines into the viewport (if possible).
              if (viewport && viewport.ensure) {
                var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
                if (ensureFrom < from) {
                  from = ensureFrom;
                  to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
                } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
                  from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
                  to = ensureTo;
                }
              }
              return {from: from, to: Math.max(to, from + 1)};
            }
          
            // LINE NUMBERS
          
            // Re-align line numbers and gutter marks to compensate for
            // horizontal scrolling.
            function alignHorizontally(cm) {
              var display = cm.display, view = display.view;
              if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
              var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
              var gutterW = display.gutters.offsetWidth, left = comp + "px";
              for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
                if (cm.options.fixedGutter && view[i].gutter)
                  view[i].gutter.style.left = left;
                var align = view[i].alignable;
                if (align) for (var j = 0; j < align.length; j++)
                  align[j].style.left = left;
              }
              if (cm.options.fixedGutter)
                display.gutters.style.left = (comp + gutterW) + "px";
            }
          
            // Used to ensure that the line number gutter is still the right
            // size for the current document size. Returns true when an update
            // is needed.
            function maybeUpdateLineNumberWidth(cm) {
              if (!cm.options.lineNumbers) return false;
              var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
              if (last.length != display.lineNumChars) {
                var test = display.measure.appendChild(elt("div", [elt("div", last)],
                                                           "CodeMirror-linenumber CodeMirror-gutter-elt"));
                var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
                display.lineGutter.style.width = "";
                display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
                display.lineNumWidth = display.lineNumInnerWidth + padding;
                display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
                display.lineGutter.style.width = display.lineNumWidth + "px";
                updateGutterSpace(cm);
                return true;
              }
              return false;
            }
          
            function lineNumberFor(options, i) {
              return String(options.lineNumberFormatter(i + options.firstLineNumber));
            }
          
            // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
            // but using getBoundingClientRect to get a sub-pixel-accurate
            // result.
            function compensateForHScroll(display) {
              return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
            }
          
            // DISPLAY DRAWING
          
            function DisplayUpdate(cm, viewport, force) {
              var display = cm.display;
          
              this.viewport = viewport;
              // Store some values that we'll need later (but don't want to force a relayout for)
              this.visible = visibleLines(display, cm.doc, viewport);
              this.editorIsHidden = !display.wrapper.offsetWidth;
              this.wrapperHeight = display.wrapper.clientHeight;
              this.wrapperWidth = display.wrapper.clientWidth;
              this.oldDisplayWidth = displayWidth(cm);
              this.force = force;
              this.dims = getDimensions(cm);
              this.events = [];
            }
          
            DisplayUpdate.prototype.signal = function(emitter, type) {
              if (hasHandler(emitter, type))
                this.events.push(arguments);
            };
            DisplayUpdate.prototype.finish = function() {
              for (var i = 0; i < this.events.length; i++)
                signal.apply(null, this.events[i]);
            };
          
            function maybeClipScrollbars(cm) {
              var display = cm.display;
              if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
                display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
                display.heightForcer.style.height = scrollGap(cm) + "px";
                display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
                display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
                display.scrollbarsClipped = true;
              }
            }
          
            // Does the actual updating of the line display. Bails out
            // (returning false) when there is nothing to be done and forced is
            // false.
            function updateDisplayIfNeeded(cm, update) {
              var display = cm.display, doc = cm.doc;
          
              if (update.editorIsHidden) {
                resetView(cm);
                return false;
              }
          
              // Bail out if the visible area is already rendered and nothing changed.
              if (!update.force &&
                  update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
                  (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
                  display.renderedView == display.view && countDirtyView(cm) == 0)
                return false;
          
              if (maybeUpdateLineNumberWidth(cm)) {
                resetView(cm);
                update.dims = getDimensions(cm);
              }
          
              // Compute a suitable new viewport (from & to)
              var end = doc.first + doc.size;
              var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
              var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
              if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
              if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
              if (sawCollapsedSpans) {
                from = visualLineNo(cm.doc, from);
                to = visualLineEndNo(cm.doc, to);
              }
          
              var different = from != display.viewFrom || to != display.viewTo ||
                display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
              adjustView(cm, from, to);
          
              display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
              // Position the mover div to align with the current scroll position
              cm.display.mover.style.top = display.viewOffset + "px";
          
              var toUpdate = countDirtyView(cm);
              if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
                  (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
                return false;
          
              // For big changes, we hide the enclosing element during the
              // update, since that speeds up the operations on most browsers.
              var focused = activeElt();
              if (toUpdate > 4) display.lineDiv.style.display = "none";
              patchDisplay(cm, display.updateLineNumbers, update.dims);
              if (toUpdate > 4) display.lineDiv.style.display = "";
              display.renderedView = display.view;
              // There might have been a widget with a focused element that got
              // hidden or updated, if so re-focus it.
              if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
          
              // Prevent selection and cursors from interfering with the scroll
              // width and height.
              removeChildren(display.cursorDiv);
              removeChildren(display.selectionDiv);
              display.gutters.style.height = 0;
          
              if (different) {
                display.lastWrapHeight = update.wrapperHeight;
                display.lastWrapWidth = update.wrapperWidth;
                startWorker(cm, 400);
              }
          
              display.updateLineNumbers = null;
          
              return true;
            }
          
            function postUpdateDisplay(cm, update) {
              var force = update.force, viewport = update.viewport;
              for (var first = true;; first = false) {
                if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
                  force = true;
                } else {
                  force = false;
                  // Clip forced viewport to actual scrollable area.
                  if (viewport && viewport.top != null)
                    viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
                  // Updated line heights might result in the drawn area not
                  // actually covering the viewport. Keep looping until it does.
                  update.visible = visibleLines(cm.display, cm.doc, viewport);
                  if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
                    break;
                }
                if (!updateDisplayIfNeeded(cm, update)) break;
                updateHeightsInViewport(cm);
                var barMeasure = measureForScrollbars(cm);
                updateSelection(cm);
                setDocumentHeight(cm, barMeasure);
                updateScrollbars(cm, barMeasure);
              }
          
              update.signal(cm, "update", cm);
              if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
                update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
                cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
              }
            }
          
            function updateDisplaySimple(cm, viewport) {
              var update = new DisplayUpdate(cm, viewport);
              if (updateDisplayIfNeeded(cm, update)) {
                updateHeightsInViewport(cm);
                postUpdateDisplay(cm, update);
                var barMeasure = measureForScrollbars(cm);
                updateSelection(cm);
                setDocumentHeight(cm, barMeasure);
                updateScrollbars(cm, barMeasure);
                update.finish();
              }
            }
          
            function setDocumentHeight(cm, measure) {
              cm.display.sizer.style.minHeight = measure.docHeight + "px";
              var total = measure.docHeight + cm.display.barHeight;
              cm.display.heightForcer.style.top = total + "px";
              cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
            }
          
            // Read the actual heights of the rendered lines, and update their
            // stored heights to match.
            function updateHeightsInViewport(cm) {
              var display = cm.display;
              var prevBottom = display.lineDiv.offsetTop;
              for (var i = 0; i < display.view.length; i++) {
                var cur = display.view[i], height;
                if (cur.hidden) continue;
                if (ie && ie_version < 8) {
                  var bot = cur.node.offsetTop + cur.node.offsetHeight;
                  height = bot - prevBottom;
                  prevBottom = bot;
                } else {
                  var box = cur.node.getBoundingClientRect();
                  height = box.bottom - box.top;
                }
                var diff = cur.line.height - height;
                if (height < 2) height = textHeight(display);
                if (diff > .001 || diff < -.001) {
                  updateLineHeight(cur.line, height);
                  updateWidgetHeight(cur.line);
                  if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
                    updateWidgetHeight(cur.rest[j]);
                }
              }
            }
          
            // Read and store the height of line widgets associated with the
            // given line.
            function updateWidgetHeight(line) {
              if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
                line.widgets[i].height = line.widgets[i].node.offsetHeight;
            }
          
            // Do a bulk-read of the DOM positions and sizes needed to draw the
            // view, so that we don't interleave reading and writing to the DOM.
            function getDimensions(cm) {
              var d = cm.display, left = {}, width = {};
              var gutterLeft = d.gutters.clientLeft;
              for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
                left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
                width[cm.options.gutters[i]] = n.clientWidth;
              }
              return {fixedPos: compensateForHScroll(d),
                      gutterTotalWidth: d.gutters.offsetWidth,
                      gutterLeft: left,
                      gutterWidth: width,
                      wrapperWidth: d.wrapper.clientWidth};
            }
          
            // Sync the actual display DOM structure with display.view, removing
            // nodes for lines that are no longer in view, and creating the ones
            // that are not there yet, and updating the ones that are out of
            // date.
            function patchDisplay(cm, updateNumbersFrom, dims) {
              var display = cm.display, lineNumbers = cm.options.lineNumbers;
              var container = display.lineDiv, cur = container.firstChild;
          
              function rm(node) {
                var next = node.nextSibling;
                // Works around a throw-scroll bug in OS X Webkit
                if (webkit && mac && cm.display.currentWheelTarget == node)
                  node.style.display = "none";
                else
                  node.parentNode.removeChild(node);
                return next;
              }
          
              var view = display.view, lineN = display.viewFrom;
              // Loop over the elements in the view, syncing cur (the DOM nodes
              // in display.lineDiv) with the view as we go.
              for (var i = 0; i < view.length; i++) {
                var lineView = view[i];
                if (lineView.hidden) {
                } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
                  var node = buildLineElement(cm, lineView, lineN, dims);
                  container.insertBefore(node, cur);
                } else { // Already drawn
                  while (cur != lineView.node) cur = rm(cur);
                  var updateNumber = lineNumbers && updateNumbersFrom != null &&
                    updateNumbersFrom <= lineN && lineView.lineNumber;
                  if (lineView.changes) {
                    if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
                    updateLineForChanges(cm, lineView, lineN, dims);
                  }
                  if (updateNumber) {
                    removeChildren(lineView.lineNumber);
                    lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
                  }
                  cur = lineView.node.nextSibling;
                }
                lineN += lineView.size;
              }
              while (cur) cur = rm(cur);
            }
          
            // When an aspect of a line changes, a string is added to
            // lineView.changes. This updates the relevant part of the line's
            // DOM structure.
            function updateLineForChanges(cm, lineView, lineN, dims) {
              for (var j = 0; j < lineView.changes.length; j++) {
                var type = lineView.changes[j];
                if (type == "text") updateLineText(cm, lineView);
                else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
                else if (type == "class") updateLineClasses(lineView);
                else if (type == "widget") updateLineWidgets(cm, lineView, dims);
              }
              lineView.changes = null;
            }
          
            // Lines with gutter elements, widgets or a background class need to
            // be wrapped, and have the extra elements added to the wrapper div
            function ensureLineWrapped(lineView) {
              if (lineView.node == lineView.text) {
                lineView.node = elt("div", null, null, "position: relative");
                if (lineView.text.parentNode)
                  lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
                lineView.node.appendChild(lineView.text);
                if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
              }
              return lineView.node;
            }
          
            function updateLineBackground(lineView) {
              var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
              if (cls) cls += " CodeMirror-linebackground";
              if (lineView.background) {
                if (cls) lineView.background.className = cls;
                else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
              } else if (cls) {
                var wrap = ensureLineWrapped(lineView);
                lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
              }
            }
          
            // Wrapper around buildLineContent which will reuse the structure
            // in display.externalMeasured when possible.
            function getLineContent(cm, lineView) {
              var ext = cm.display.externalMeasured;
              if (ext && ext.line == lineView.line) {
                cm.display.externalMeasured = null;
                lineView.measure = ext.measure;
                return ext.built;
              }
              return buildLineContent(cm, lineView);
            }
          
            // Redraw the line's text. Interacts with the background and text
            // classes because the mode may output tokens that influence these
            // classes.
            function updateLineText(cm, lineView) {
              var cls = lineView.text.className;
              var built = getLineContent(cm, lineView);
              if (lineView.text == lineView.node) lineView.node = built.pre;
              lineView.text.parentNode.replaceChild(built.pre, lineView.text);
              lineView.text = built.pre;
              if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
                lineView.bgClass = built.bgClass;
                lineView.textClass = built.textClass;
                updateLineClasses(lineView);
              } else if (cls) {
                lineView.text.className = cls;
              }
            }
          
            function updateLineClasses(lineView) {
              updateLineBackground(lineView);
              if (lineView.line.wrapClass)
                ensureLineWrapped(lineView).className = lineView.line.wrapClass;
              else if (lineView.node != lineView.text)
                lineView.node.className = "";
              var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
              lineView.text.className = textClass || "";
            }
          
            function updateLineGutter(cm, lineView, lineN, dims) {
              if (lineView.gutter) {
                lineView.node.removeChild(lineView.gutter);
                lineView.gutter = null;
              }
              var markers = lineView.line.gutterMarkers;
              if (cm.options.lineNumbers || markers) {
                var wrap = ensureLineWrapped(lineView);
                var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
                                                       (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
                                                       "px; width: " + dims.gutterTotalWidth + "px");
                cm.display.input.setUneditable(gutterWrap);
                wrap.insertBefore(gutterWrap, lineView.text);
                if (lineView.line.gutterClass)
                  gutterWrap.className += " " + lineView.line.gutterClass;
                if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
                  lineView.lineNumber = gutterWrap.appendChild(
                    elt("div", lineNumberFor(cm.options, lineN),
                        "CodeMirror-linenumber CodeMirror-gutter-elt",
                        "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
                        + cm.display.lineNumInnerWidth + "px"));
                if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
                  var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
                  if (found)
                    gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
                                               dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
                }
              }
            }
          
            function updateLineWidgets(cm, lineView, dims) {
              if (lineView.alignable) lineView.alignable = null;
              for (var node = lineView.node.firstChild, next; node; node = next) {
                var next = node.nextSibling;
                if (node.className == "CodeMirror-linewidget")
                  lineView.node.removeChild(node);
              }
              insertLineWidgets(cm, lineView, dims);
            }
          
            // Build a line's DOM representation from scratch
            function buildLineElement(cm, lineView, lineN, dims) {
              var built = getLineContent(cm, lineView);
              lineView.text = lineView.node = built.pre;
              if (built.bgClass) lineView.bgClass = built.bgClass;
              if (built.textClass) lineView.textClass = built.textClass;
          
              updateLineClasses(lineView);
              updateLineGutter(cm, lineView, lineN, dims);
              insertLineWidgets(cm, lineView, dims);
              return lineView.node;
            }
          
            // A lineView may contain multiple logical lines (when merged by
            // collapsed spans). The widgets for all of them need to be drawn.
            function insertLineWidgets(cm, lineView, dims) {
              insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
              if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
                insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
            }
          
            function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
              if (!line.widgets) return;
              var wrap = ensureLineWrapped(lineView);
              for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
                var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
                if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
                positionLineWidget(widget, node, lineView, dims);
                cm.display.input.setUneditable(node);
                if (allowAbove && widget.above)
                  wrap.insertBefore(node, lineView.gutter || lineView.text);
                else
                  wrap.appendChild(node);
                signalLater(widget, "redraw");
              }
            }
          
            function positionLineWidget(widget, node, lineView, dims) {
              if (widget.noHScroll) {
                (lineView.alignable || (lineView.alignable = [])).push(node);
                var width = dims.wrapperWidth;
                node.style.left = dims.fixedPos + "px";
                if (!widget.coverGutter) {
                  width -= dims.gutterTotalWidth;
                  node.style.paddingLeft = dims.gutterTotalWidth + "px";
                }
                node.style.width = width + "px";
              }
              if (widget.coverGutter) {
                node.style.zIndex = 5;
                node.style.position = "relative";
                if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
              }
            }
          
            // POSITION OBJECT
          
            // A Pos instance represents a position within the text.
            var Pos = CodeMirror.Pos = function(line, ch) {
              if (!(this instanceof Pos)) return new Pos(line, ch);
              this.line = line; this.ch = ch;
            };
          
            // Compare two positions, return 0 if they are the same, a negative
            // number when a is less, and a positive number otherwise.
            var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
          
            function copyPos(x) {return Pos(x.line, x.ch);}
            function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
            function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
          
            // INPUT HANDLING
          
            function ensureFocus(cm) {
              if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
            }
          
            function isReadOnly(cm) {
              return cm.options.readOnly || cm.doc.cantEdit;
            }
          
            // This will be set to an array of strings when copying, so that,
            // when pasting, we know what kind of selections the copied text
            // was made out of.
            var lastCopied = null;
          
            function applyTextInput(cm, inserted, deleted, sel) {
              var doc = cm.doc;
              cm.display.shift = false;
              if (!sel) sel = doc.sel;
          
              var textLines = splitLines(inserted), multiPaste = null;
              // When pasing N lines into N selections, insert one line per selection
              if (cm.state.pasteIncoming && sel.ranges.length > 1) {
                if (lastCopied && lastCopied.join("\n") == inserted)
                  multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
                else if (textLines.length == sel.ranges.length)
                  multiPaste = map(textLines, function(l) { return [l]; });
              }
          
              // Normal behavior is to insert the new text into every selection
              for (var i = sel.ranges.length - 1; i >= 0; i--) {
                var range = sel.ranges[i];
                var from = range.from(), to = range.to();
                if (range.empty()) {
                  if (deleted && deleted > 0) // Handle deletion
                    from = Pos(from.line, from.ch - deleted);
                  else if (cm.state.overwrite && !cm.state.pasteIncoming) // Handle overwrite
                    to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
                }
                var updateInput = cm.curOp.updateInput;
                var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
                                   origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
                makeChange(cm.doc, changeEvent);
                signalLater(cm, "inputRead", cm, changeEvent);
                // When an 'electric' character is inserted, immediately trigger a reindent
                if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
                    cm.options.smartIndent && range.head.ch < 100 &&
                    (!i || sel.ranges[i - 1].head.line != range.head.line)) {
                  var mode = cm.getModeAt(range.head);
                  var end = changeEnd(changeEvent);
                  if (mode.electricChars) {
                    for (var j = 0; j < mode.electricChars.length; j++)
                      if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
                        indentLine(cm, end.line, "smart");
                        break;
                      }
                  } else if (mode.electricInput) {
                    if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
                      indentLine(cm, end.line, "smart");
                  }
                }
              }
              ensureCursorVisible(cm);
              cm.curOp.updateInput = updateInput;
              cm.curOp.typing = true;
              cm.state.pasteIncoming = cm.state.cutIncoming = false;
            }
          
            function copyableRanges(cm) {
              var text = [], ranges = [];
              for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
                var line = cm.doc.sel.ranges[i].head.line;
                var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
                ranges.push(lineRange);
                text.push(cm.getRange(lineRange.anchor, lineRange.head));
              }
              return {text: text, ranges: ranges};
            }
          
            function disableBrowserMagic(field) {
              field.setAttribute("autocorrect", "off");
              field.setAttribute("autocapitalize", "off");
              field.setAttribute("spellcheck", "false");
            }
          
            // TEXTAREA INPUT STYLE
          
            function TextareaInput(cm) {
              this.cm = cm;
              // See input.poll and input.reset
              this.prevInput = "";
          
              // Flag that indicates whether we expect input to appear real soon
              // now (after some event like 'keypress' or 'input') and are
              // polling intensively.
              this.pollingFast = false;
              // Self-resetting timeout for the poller
              this.polling = new Delayed();
              // Tracks when input.reset has punted to just putting a short
              // string into the textarea instead of the full selection.
              this.inaccurateSelection = false;
              // Used to work around IE issue with selection being forgotten when focus moves away from textarea
              this.hasSelection = false;
            };
          
            function hiddenTextarea() {
              var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
              var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
              // The textarea is kept positioned near the cursor to prevent the
              // fact that it'll be scrolled into view on input from scrolling
              // our fake cursor out of view. On webkit, when wrap=off, paste is
              // very slow. So make the area wide instead.
              if (webkit) te.style.width = "1000px";
              else te.setAttribute("wrap", "off");
              // If border: 0; -- iOS fails to open keyboard (issue #1287)
              if (ios) te.style.border = "1px solid black";
              disableBrowserMagic(te);
              return div;
            }
          
            TextareaInput.prototype = copyObj({
              init: function(display) {
                var input = this, cm = this.cm;
          
                // Wraps and hides input textarea
                var div = this.wrapper = hiddenTextarea();
                // The semihidden textarea that is focused when the editor is
                // focused, and receives input.
                var te = this.textarea = div.firstChild;
                display.wrapper.insertBefore(div, display.wrapper.firstChild);
          
                // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
                if (ios) te.style.width = "0px";
          
                on(te, "input", function() {
                  if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
                  input.poll();
                });
          
                on(te, "paste", function() {
                  // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
                  // Add a char to the end of textarea before paste occur so that
                  // selection doesn't span to the end of textarea.
                  if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
                    var start = te.selectionStart, end = te.selectionEnd;
                    te.value += "$";
                    // The selection end needs to be set before the start, otherwise there
                    // can be an intermediate non-empty selection between the two, which
                    // can override the middle-click paste buffer on linux and cause the
                    // wrong thing to get pasted.
                    te.selectionEnd = end;
                    te.selectionStart = start;
                    cm.state.fakedLastChar = true;
                  }
                  cm.state.pasteIncoming = true;
                  input.fastPoll();
                });
          
                function prepareCopyCut(e) {
                  if (cm.somethingSelected()) {
                    lastCopied = cm.getSelections();
                    if (input.inaccurateSelection) {
                      input.prevInput = "";
                      input.inaccurateSelection = false;
                      te.value = lastCopied.join("\n");
                      selectInput(te);
                    }
                  } else {
                    var ranges = copyableRanges(cm);
                    lastCopied = ranges.text;
                    if (e.type == "cut") {
                      cm.setSelections(ranges.ranges, null, sel_dontScroll);
                    } else {
                      input.prevInput = "";
                      te.value = ranges.text.join("\n");
                      selectInput(te);
                    }
                  }
                  if (e.type == "cut") cm.state.cutIncoming = true;
                }
                on(te, "cut", prepareCopyCut);
                on(te, "copy", prepareCopyCut);
          
                on(display.scroller, "paste", function(e) {
                  if (eventInWidget(display, e)) return;
                  cm.state.pasteIncoming = true;
                  input.focus();
                });
          
                // Prevent normal selection in the editor (we handle our own)
                on(display.lineSpace, "selectstart", function(e) {
                  if (!eventInWidget(display, e)) e_preventDefault(e);
                });
              },
          
              prepareSelection: function() {
                // Redraw the selection and/or cursor
                var cm = this.cm, display = cm.display, doc = cm.doc;
                var result = prepareSelection(cm);
          
                // Move the hidden textarea near the cursor to prevent scrolling artifacts
                if (cm.options.moveInputWithCursor) {
                  var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
                  var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
                  result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
                                                      headPos.top + lineOff.top - wrapOff.top));
                  result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
                                                       headPos.left + lineOff.left - wrapOff.left));
                }
          
                return result;
              },
          
              showSelection: function(drawn) {
                var cm = this.cm, display = cm.display;
                removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
                removeChildrenAndAdd(display.selectionDiv, drawn.selection);
                if (drawn.teTop != null) {
                  this.wrapper.style.top = drawn.teTop + "px";
                  this.wrapper.style.left = drawn.teLeft + "px";
                }
              },
          
              // Reset the input to correspond to the selection (or to be empty,
              // when not typing and nothing is selected)
              reset: function(typing) {
                if (this.contextMenuPending) return;
                var minimal, selected, cm = this.cm, doc = cm.doc;
                if (cm.somethingSelected()) {
                  this.prevInput = "";
                  var range = doc.sel.primary();
                  minimal = hasCopyEvent &&
                    (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
                  var content = minimal ? "-" : selected || cm.getSelection();
                  this.textarea.value = content;
                  if (cm.state.focused) selectInput(this.textarea);
                  if (ie && ie_version >= 9) this.hasSelection = content;
                } else if (!typing) {
                  this.prevInput = this.textarea.value = "";
                  if (ie && ie_version >= 9) this.hasSelection = null;
                }
                this.inaccurateSelection = minimal;
              },
          
              getField: function() { return this.textarea; },
          
              supportsTouch: function() { return false; },
          
              focus: function() {
                if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
                  try { this.textarea.focus(); }
                  catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
                }
              },
          
              blur: function() { this.textarea.blur(); },
          
              resetPosition: function() {
                this.wrapper.style.top = this.wrapper.style.left = 0;
              },
          
              receivedFocus: function() { this.slowPoll(); },
          
              // Poll for input changes, using the normal rate of polling. This
              // runs as long as the editor is focused.
              slowPoll: function() {
                var input = this;
                if (input.pollingFast) return;
                input.polling.set(this.cm.options.pollInterval, function() {
                  input.poll();
                  if (input.cm.state.focused) input.slowPoll();
                });
              },
          
              // When an event has just come in that is likely to add or change
              // something in the input textarea, we poll faster, to ensure that
              // the change appears on the screen quickly.
              fastPoll: function() {
                var missed = false, input = this;
                input.pollingFast = true;
                function p() {
                  var changed = input.poll();
                  if (!changed && !missed) {missed = true; input.polling.set(60, p);}
                  else {input.pollingFast = false; input.slowPoll();}
                }
                input.polling.set(20, p);
              },
          
              // Read input from the textarea, and update the document to match.
              // When something is selected, it is present in the textarea, and
              // selected (unless it is huge, in which case a placeholder is
              // used). When nothing is selected, the cursor sits after previously
              // seen text (can be empty), which is stored in prevInput (we must
              // not reset the textarea when typing, because that breaks IME).
              poll: function() {
                var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
                // Since this is called a *lot*, try to bail out as cheaply as
                // possible when it is clear that nothing happened. hasSelection
                // will be the case when there is a lot of text in the textarea,
                // in which case reading its value would be expensive.
                if (!cm.state.focused || (hasSelection(input) && !prevInput) ||
                    isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
                  return false;
                // See paste handler for more on the fakedLastChar kludge
                if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
                  input.value = input.value.substring(0, input.value.length - 1);
                  cm.state.fakedLastChar = false;
                }
                var text = input.value;
                // If nothing changed, bail.
                if (text == prevInput && !cm.somethingSelected()) return false;
                // Work around nonsensical selection resetting in IE9/10, and
                // inexplicable appearance of private area unicode characters on
                // some key combos in Mac (#2689).
                if (ie && ie_version >= 9 && this.hasSelection === text ||
                    mac && /[\uf700-\uf7ff]/.test(text)) {
                  cm.display.input.reset();
                  return false;
                }
          
                if (text.charCodeAt(0) == 0x200b && cm.doc.sel == cm.display.selForContextMenu && !prevInput)
                  prevInput = "\u200b";
                // Find the part of the input that is actually new
                var same = 0, l = Math.min(prevInput.length, text.length);
                while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
          
                var self = this;
                runInOp(cm, function() {
                  applyTextInput(cm, text.slice(same), prevInput.length - same);
          
                  // Don't leave long text in the textarea, since it makes further polling slow
                  if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
                  else self.prevInput = text;
                });
                return true;
              },
          
              ensurePolled: function() {
                if (this.pollingFast && this.poll()) this.pollingFast = false;
              },
          
              onKeyPress: function() {
                if (ie && ie_version >= 9) this.hasSelection = null;
                this.fastPoll();
              },
          
              onContextMenu: function(e) {
                var input = this, cm = input.cm, display = cm.display, te = input.textarea;
                var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
                if (!pos || presto) return; // Opera is difficult.
          
                // Reset the current text selection only if the click is done outside of the selection
                // and 'resetSelectionOnContextMenu' option is true.
                var reset = cm.options.resetSelectionOnContextMenu;
                if (reset && cm.doc.sel.contains(pos) == -1)
                  operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
          
                var oldCSS = te.style.cssText;
                input.wrapper.style.position = "absolute";
                te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
                  "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
                  (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
                  "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
                if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
                display.input.focus();
                if (webkit) window.scrollTo(null, oldScrollY);
                display.input.reset();
                // Adds "Select all" to context menu in FF
                if (!cm.somethingSelected()) te.value = input.prevInput = " ";
                input.contextMenuPending = true;
                display.selForContextMenu = cm.doc.sel;
                clearTimeout(display.detectingSelectAll);
          
                // Select-all will be greyed out if there's nothing to select, so
                // this adds a zero-width space so that we can later check whether
                // it got selected.
                function prepareSelectAllHack() {
                  if (te.selectionStart != null) {
                    var selected = cm.somethingSelected();
                    var extval = te.value = "\u200b" + (selected ? te.value : "");
                    input.prevInput = selected ? "" : "\u200b";
                    te.selectionStart = 1; te.selectionEnd = extval.length;
                    // Re-set this, in case some other handler touched the
                    // selection in the meantime.
                    display.selForContextMenu = cm.doc.sel;
                  }
                }
                function rehide() {
                  input.contextMenuPending = false;
                  input.wrapper.style.position = "relative";
                  te.style.cssText = oldCSS;
                  if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
          
                  // Try to detect the user choosing select-all
                  if (te.selectionStart != null) {
                    if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
                    var i = 0, poll = function() {
                      if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0)
                        operation(cm, commands.selectAll)(cm);
                      else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
                      else display.input.reset();
                    };
                    display.detectingSelectAll = setTimeout(poll, 200);
                  }
                }
          
                if (ie && ie_version >= 9) prepareSelectAllHack();
                if (captureRightClick) {
                  e_stop(e);
                  var mouseup = function() {
                    off(window, "mouseup", mouseup);
                    setTimeout(rehide, 20);
                  };
                  on(window, "mouseup", mouseup);
                } else {
                  setTimeout(rehide, 50);
                }
              },
          
              setUneditable: nothing,
          
              needsContentAttribute: false
            }, TextareaInput.prototype);
          
            // CONTENTEDITABLE INPUT STYLE
          
            function ContentEditableInput(cm) {
              this.cm = cm;
              this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
              this.polling = new Delayed();
            }
          
            ContentEditableInput.prototype = copyObj({
              init: function(display) {
                var input = this, cm = input.cm;
                var div = input.div = display.lineDiv;
                div.contentEditable = "true";
                disableBrowserMagic(div);
          
                on(div, "paste", function(e) {
                  var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
                  if (pasted) {
                    e.preventDefault();
                    cm.replaceSelection(pasted, null, "paste");
                  }
                });
          
                on(div, "compositionstart", function(e) {
                  var data = e.data;
                  input.composing = {sel: cm.doc.sel, data: data, startData: data};
                  if (!data) return;
                  var prim = cm.doc.sel.primary();
                  var line = cm.getLine(prim.head.line);
                  var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
                  if (found > -1 && found <= prim.head.ch)
                    input.composing.sel = simpleSelection(Pos(prim.head.line, found),
                                                          Pos(prim.head.line, found + data.length));
                });
                on(div, "compositionupdate", function(e) {
                  input.composing.data = e.data;
                });
                on(div, "compositionend", function(e) {
                  var ours = input.composing;
                  if (!ours) return;
                  if (e.data != ours.startData && !/\u200b/.test(e.data))
                    ours.data = e.data;
                  // Need a small delay to prevent other code (input event,
                  // selection polling) from doing damage when fired right after
                  // compositionend.
                  setTimeout(function() {
                    if (!ours.handled)
                      input.applyComposition(ours);
                    if (input.composing == ours)
                      input.composing = null;
                  }, 50);
                });
          
                on(div, "touchstart", function() {
                  input.forceCompositionEnd();
                });
          
                on(div, "input", function() {
                  if (input.composing) return;
                  if (!input.pollContent())
                    runInOp(input.cm, function() {regChange(cm);});
                });
          
                function onCopyCut(e) {
                  if (cm.somethingSelected()) {
                    lastCopied = cm.getSelections();
                    if (e.type == "cut") cm.replaceSelection("", null, "cut");
                  } else {
                    var ranges = copyableRanges(cm);
                    lastCopied = ranges.text;
                    if (e.type == "cut") {
                      cm.operation(function() {
                        cm.setSelections(ranges.ranges, 0, sel_dontScroll);
                        cm.replaceSelection("", null, "cut");
                      });
                    }
                  }
                  // iOS exposes the clipboard API, but seems to discard content inserted into it
                  if (e.clipboardData && !ios) {
                    e.preventDefault();
                    e.clipboardData.clearData();
                    e.clipboardData.setData("text/plain", lastCopied.join("\n"));
                  } else {
                    // Old-fashioned briefly-focus-a-textarea hack
                    var kludge = hiddenTextarea(), te = kludge.firstChild;
                    cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
                    te.value = lastCopied.join("\n");
                    var hadFocus = document.activeElement;
                    selectInput(te);
                    setTimeout(function() {
                      cm.display.lineSpace.removeChild(kludge);
                      hadFocus.focus();
                    }, 50);
                  }
                }
                on(div, "copy", onCopyCut);
                on(div, "cut", onCopyCut);
              },
          
              prepareSelection: function() {
                var result = prepareSelection(this.cm, false);
                result.focus = this.cm.state.focused;
                return result;
              },
          
              showSelection: function(info) {
                if (!info || !this.cm.display.view.length) return;
                if (info.focus) this.showPrimarySelection();
                this.showMultipleSelections(info);
              },
          
              showPrimarySelection: function() {
                var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
                var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
                var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
                if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
                    cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
                    cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
                  return;
          
                var start = posToDOM(this.cm, prim.from());
                var end = posToDOM(this.cm, prim.to());
                if (!start && !end) return;
          
                var view = this.cm.display.view;
                var old = sel.rangeCount && sel.getRangeAt(0);
                if (!start) {
                  start = {node: view[0].measure.map[2], offset: 0};
                } else if (!end) { // FIXME dangerously hacky
                  var measure = view[view.length - 1].measure;
                  var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
                  end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
                }
          
                try { var rng = range(start.node, start.offset, end.offset, end.node); }
                catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
                if (rng) {
                  sel.removeAllRanges();
                  sel.addRange(rng);
                  if (old && sel.anchorNode == null) sel.addRange(old);
                }
                this.rememberSelection();
              },
          
              showMultipleSelections: function(info) {
                removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
                removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
              },
          
              rememberSelection: function() {
                var sel = window.getSelection();
                this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
                this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
              },
          
              selectionInEditor: function() {
                var sel = window.getSelection();
                if (!sel.rangeCount) return false;
                var node = sel.getRangeAt(0).commonAncestorContainer;
                return contains(this.div, node);
              },
          
              focus: function() {
                if (this.cm.options.readOnly != "nocursor") this.div.focus();
              },
              blur: function() { this.div.blur(); },
              getField: function() { return this.div; },
          
              supportsTouch: function() { return true; },
          
              receivedFocus: function() {
                var input = this;
                if (this.selectionInEditor())
                  this.pollSelection();
                else
                  runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
          
                function poll() {
                  if (input.cm.state.focused) {
                    input.pollSelection();
                    input.polling.set(input.cm.options.pollInterval, poll);
                  }
                }
                this.polling.set(this.cm.options.pollInterval, poll);
              },
          
              pollSelection: function() {
                if (this.composing) return;
          
                var sel = window.getSelection(), cm = this.cm;
                if (sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
                    sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset) {
                  this.rememberSelection();
                  var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
                  var head = domToPos(cm, sel.focusNode, sel.focusOffset);
                  if (anchor && head) runInOp(cm, function() {
                    setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
                    if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
                  });
                }
              },
          
              pollContent: function() {
                var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
                var from = sel.from(), to = sel.to();
                if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
          
                var fromIndex;
                if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
                  var fromLine = lineNo(display.view[0].line);
                  var fromNode = display.view[0].node;
                } else {
                  var fromLine = lineNo(display.view[fromIndex].line);
                  var fromNode = display.view[fromIndex - 1].node.nextSibling;
                }
                var toIndex = findViewIndex(cm, to.line);
                if (toIndex == display.view.length - 1) {
                  var toLine = display.viewTo - 1;
                  var toNode = display.view[toIndex].node;
                } else {
                  var toLine = lineNo(display.view[toIndex + 1].line) - 1;
                  var toNode = display.view[toIndex + 1].node.previousSibling;
                }
          
                var newText = splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
                var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
                while (newText.length > 1 && oldText.length > 1) {
                  if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
                  else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
                  else break;
                }
          
                var cutFront = 0, cutEnd = 0;
                var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
                while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
                  ++cutFront;
                var newBot = lst(newText), oldBot = lst(oldText);
                var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
                                         oldBot.length - (oldText.length == 1 ? cutFront : 0));
                while (cutEnd < maxCutEnd &&
                       newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
                  ++cutEnd;
          
                newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
                newText[0] = newText[0].slice(cutFront);
          
                var chFrom = Pos(fromLine, cutFront);
                var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
                if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
                  replaceRange(cm.doc, newText, chFrom, chTo, "+input");
                  return true;
                }
              },
          
              ensurePolled: function() {
                this.forceCompositionEnd();
              },
              reset: function() {
                this.forceCompositionEnd();
              },
              forceCompositionEnd: function() {
                if (!this.composing || this.composing.handled) return;
                this.applyComposition(this.composing);
                this.composing.handled = true;
                this.div.blur();
                this.div.focus();
              },
              applyComposition: function(composing) {
                if (composing.data && composing.data != composing.startData)
                  operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
              },
          
              setUneditable: function(node) {
                node.setAttribute("contenteditable", "false");
              },
          
              onKeyPress: function(e) {
                e.preventDefault();
                operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
              },
          
              onContextMenu: nothing,
              resetPosition: nothing,
          
              needsContentAttribute: true
            }, ContentEditableInput.prototype);
          
            function posToDOM(cm, pos) {
              var view = findViewForLine(cm, pos.line);
              if (!view || view.hidden) return null;
              var line = getLine(cm.doc, pos.line);
              var info = mapFromLineView(view, line, pos.line);
          
              var order = getOrder(line), side = "left";
              if (order) {
                var partPos = getBidiPartAt(order, pos.ch);
                side = partPos % 2 ? "right" : "left";
              }
              var result = nodeAndOffsetInLineMap(info.map, pos.ch, "left");
              result.offset = result.collapse == "right" ? result.end : result.start;
              return result;
            }
          
            function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
          
            function domToPos(cm, node, offset) {
              var lineNode;
              if (node == cm.display.lineDiv) {
                lineNode = cm.display.lineDiv.childNodes[offset];
                if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
                node = null; offset = 0;
              } else {
                for (lineNode = node;; lineNode = lineNode.parentNode) {
                  if (!lineNode || lineNode == cm.display.lineDiv) return null;
                  if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
                }
              }
              for (var i = 0; i < cm.display.view.length; i++) {
                var lineView = cm.display.view[i];
                if (lineView.node == lineNode)
                  return locateNodeInLineView(lineView, node, offset);
              }
            }
          
            function locateNodeInLineView(lineView, node, offset) {
              var wrapper = lineView.text.firstChild, bad = false;
              if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
              if (node == wrapper) {
                bad = true;
                node = wrapper.childNodes[offset];
                offset = 0;
                if (!node) {
                  var line = lineView.rest ? lst(lineView.rest) : lineView.line;
                  return badPos(Pos(lineNo(line), line.text.length), bad);
                }
              }
          
              var textNode = node.nodeType == 3 ? node : null, topNode = node;
              if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
                textNode = node.firstChild;
                if (offset) offset = textNode.nodeValue.length;
              }
              while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
              var measure = lineView.measure, maps = measure.maps;
          
              function find(textNode, topNode, offset) {
                for (var i = -1; i < (maps ? maps.length : 0); i++) {
                  var map = i < 0 ? measure.map : maps[i];
                  for (var j = 0; j < map.length; j += 3) {
                    var curNode = map[j + 2];
                    if (curNode == textNode || curNode == topNode) {
                      var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
                      var ch = map[j] + offset;
                      if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
                      return Pos(line, ch);
                    }
                  }
                }
              }
              var found = find(textNode, topNode, offset);
              if (found) return badPos(found, bad);
          
              // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
              for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
                found = find(after, after.firstChild, 0);
                if (found)
                  return badPos(Pos(found.line, found.ch - dist), bad);
                else
                  dist += after.textContent.length;
              }
              for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
                found = find(before, before.firstChild, -1);
                if (found)
                  return badPos(Pos(found.line, found.ch + dist), bad);
                else
                  dist += after.textContent.length;
              }
            }
          
            function domTextBetween(cm, from, to, fromLine, toLine) {
              var text = "", closing = false;
              function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
              function walk(node) {
                if (node.nodeType == 1) {
                  var cmText = node.getAttribute("cm-text");
                  if (cmText != null) {
                    if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
                    text += cmText;
                    return;
                  }
                  var markerID = node.getAttribute("cm-marker"), range;
                  if (markerID) {
                    var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
                    if (found.length && (range = found[0].find()))
                      text += getBetween(cm.doc, range.from, range.to).join("\n");
                    return;
                  }
                  if (node.getAttribute("contenteditable") == "false") return;
                  for (var i = 0; i < node.childNodes.length; i++)
                    walk(node.childNodes[i]);
                  if (/^(pre|div|p)$/i.test(node.nodeName))
                    closing = true;
                } else if (node.nodeType == 3) {
                  var val = node.nodeValue;
                  if (!val) return;
                  if (closing) {
                    text += "\n";
                    closing = false;
                  }
                  text += val;
                }
              }
              for (;;) {
                walk(from);
                if (from == to) break;
                from = from.nextSibling;
              }
              return text;
            }
          
            CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
          
            // SELECTION / CURSOR
          
            // Selection objects are immutable. A new one is created every time
            // the selection changes. A selection is one or more non-overlapping
            // (and non-touching) ranges, sorted, and an integer that indicates
            // which one is the primary selection (the one that's scrolled into
            // view, that getCursor returns, etc).
            function Selection(ranges, primIndex) {
              this.ranges = ranges;
              this.primIndex = primIndex;
            }
          
            Selection.prototype = {
              primary: function() { return this.ranges[this.primIndex]; },
              equals: function(other) {
                if (other == this) return true;
                if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
                for (var i = 0; i < this.ranges.length; i++) {
                  var here = this.ranges[i], there = other.ranges[i];
                  if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
                }
                return true;
              },
              deepCopy: function() {
                for (var out = [], i = 0; i < this.ranges.length; i++)
                  out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
                return new Selection(out, this.primIndex);
              },
              somethingSelected: function() {
                for (var i = 0; i < this.ranges.length; i++)
                  if (!this.ranges[i].empty()) return true;
                return false;
              },
              contains: function(pos, end) {
                if (!end) end = pos;
                for (var i = 0; i < this.ranges.length; i++) {
                  var range = this.ranges[i];
                  if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
                    return i;
                }
                return -1;
              }
            };
          
            function Range(anchor, head) {
              this.anchor = anchor; this.head = head;
            }
          
            Range.prototype = {
              from: function() { return minPos(this.anchor, this.head); },
              to: function() { return maxPos(this.anchor, this.head); },
              empty: function() {
                return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
              }
            };
          
            // Take an unsorted, potentially overlapping set of ranges, and
            // build a selection out of it. 'Consumes' ranges array (modifying
            // it).
            function normalizeSelection(ranges, primIndex) {
              var prim = ranges[primIndex];
              ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
              primIndex = indexOf(ranges, prim);
              for (var i = 1; i < ranges.length; i++) {
                var cur = ranges[i], prev = ranges[i - 1];
                if (cmp(prev.to(), cur.from()) >= 0) {
                  var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
                  var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
                  if (i <= primIndex) --primIndex;
                  ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
                }
              }
              return new Selection(ranges, primIndex);
            }
          
            function simpleSelection(anchor, head) {
              return new Selection([new Range(anchor, head || anchor)], 0);
            }
          
            // Most of the external API clips given positions to make sure they
            // actually exist within the document.
            function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
            function clipPos(doc, pos) {
              if (pos.line < doc.first) return Pos(doc.first, 0);
              var last = doc.first + doc.size - 1;
              if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
              return clipToLen(pos, getLine(doc, pos.line).text.length);
            }
            function clipToLen(pos, linelen) {
              var ch = pos.ch;
              if (ch == null || ch > linelen) return Pos(pos.line, linelen);
              else if (ch < 0) return Pos(pos.line, 0);
              else return pos;
            }
            function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
            function clipPosArray(doc, array) {
              for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
              return out;
            }
          
            // SELECTION UPDATES
          
            // The 'scroll' parameter given to many of these indicated whether
            // the new cursor position should be scrolled into view after
            // modifying the selection.
          
            // If shift is held or the extend flag is set, extends a range to
            // include a given position (and optionally a second position).
            // Otherwise, simply returns the range between the given positions.
            // Used for cursor motion and such.
            function extendRange(doc, range, head, other) {
              if (doc.cm && doc.cm.display.shift || doc.extend) {
                var anchor = range.anchor;
                if (other) {
                  var posBefore = cmp(head, anchor) < 0;
                  if (posBefore != (cmp(other, anchor) < 0)) {
                    anchor = head;
                    head = other;
                  } else if (posBefore != (cmp(head, other) < 0)) {
                    head = other;
                  }
                }
                return new Range(anchor, head);
              } else {
                return new Range(other || head, head);
              }
            }
          
            // Extend the primary selection range, discard the rest.
            function extendSelection(doc, head, other, options) {
              setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
            }
          
            // Extend all selections (pos is an array of selections with length
            // equal the number of selections)
            function extendSelections(doc, heads, options) {
              for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
                out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
              var newSel = normalizeSelection(out, doc.sel.primIndex);
              setSelection(doc, newSel, options);
            }
          
            // Updates a single range in the selection.
            function replaceOneSelection(doc, i, range, options) {
              var ranges = doc.sel.ranges.slice(0);
              ranges[i] = range;
              setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
            }
          
            // Reset the selection to a single range.
            function setSimpleSelection(doc, anchor, head, options) {
              setSelection(doc, simpleSelection(anchor, head), options);
            }
          
            // Give beforeSelectionChange handlers a change to influence a
            // selection update.
            function filterSelectionChange(doc, sel) {
              var obj = {
                ranges: sel.ranges,
                update: function(ranges) {
                  this.ranges = [];
                  for (var i = 0; i < ranges.length; i++)
                    this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
                                               clipPos(doc, ranges[i].head));
                }
              };
              signal(doc, "beforeSelectionChange", doc, obj);
              if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
              if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
              else return sel;
            }
          
            function setSelectionReplaceHistory(doc, sel, options) {
              var done = doc.history.done, last = lst(done);
              if (last && last.ranges) {
                done[done.length - 1] = sel;
                setSelectionNoUndo(doc, sel, options);
              } else {
                setSelection(doc, sel, options);
              }
            }
          
            // Set a new selection.
            function setSelection(doc, sel, options) {
              setSelectionNoUndo(doc, sel, options);
              addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
            }
          
            function setSelectionNoUndo(doc, sel, options) {
              if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
                sel = filterSelectionChange(doc, sel);
          
              var bias = options && options.bias ||
                (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
              setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
          
              if (!(options && options.scroll === false) && doc.cm)
                ensureCursorVisible(doc.cm);
            }
          
            function setSelectionInner(doc, sel) {
              if (sel.equals(doc.sel)) return;
          
              doc.sel = sel;
          
              if (doc.cm) {
                doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
                signalCursorActivity(doc.cm);
              }
              signalLater(doc, "cursorActivity", doc);
            }
          
            // Verify that the selection does not partially select any atomic
            // marked ranges.
            function reCheckSelection(doc) {
              setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
            }
          
            // Return a selection that does not partially select any atomic
            // ranges.
            function skipAtomicInSelection(doc, sel, bias, mayClear) {
              var out;
              for (var i = 0; i < sel.ranges.length; i++) {
                var range = sel.ranges[i];
                var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
                var newHead = skipAtomic(doc, range.head, bias, mayClear);
                if (out || newAnchor != range.anchor || newHead != range.head) {
                  if (!out) out = sel.ranges.slice(0, i);
                  out[i] = new Range(newAnchor, newHead);
                }
              }
              return out ? normalizeSelection(out, sel.primIndex) : sel;
            }
          
            // Ensure a given position is not inside an atomic range.
            function skipAtomic(doc, pos, bias, mayClear) {
              var flipped = false, curPos = pos;
              var dir = bias || 1;
              doc.cantEdit = false;
              search: for (;;) {
                var line = getLine(doc, curPos.line);
                if (line.markedSpans) {
                  for (var i = 0; i < line.markedSpans.length; ++i) {
                    var sp = line.markedSpans[i], m = sp.marker;
                    if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
                        (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
                      if (mayClear) {
                        signal(m, "beforeCursorEnter");
                        if (m.explicitlyCleared) {
                          if (!line.markedSpans) break;
                          else {--i; continue;}
                        }
                      }
                      if (!m.atomic) continue;
                      var newPos = m.find(dir < 0 ? -1 : 1);
                      if (cmp(newPos, curPos) == 0) {
                        newPos.ch += dir;
                        if (newPos.ch < 0) {
                          if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
                          else newPos = null;
                        } else if (newPos.ch > line.text.length) {
                          if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
                          else newPos = null;
                        }
                        if (!newPos) {
                          if (flipped) {
                            // Driven in a corner -- no valid cursor position found at all
                            // -- try again *with* clearing, if we didn't already
                            if (!mayClear) return skipAtomic(doc, pos, bias, true);
                            // Otherwise, turn off editing until further notice, and return the start of the doc
                            doc.cantEdit = true;
                            return Pos(doc.first, 0);
                          }
                          flipped = true; newPos = pos; dir = -dir;
                        }
                      }
                      curPos = newPos;
                      continue search;
                    }
                  }
                }
                return curPos;
              }
            }
          
            // SELECTION DRAWING
          
            function updateSelection(cm) {
              cm.display.input.showSelection(cm.display.input.prepareSelection());
            }
          
            function prepareSelection(cm, primary) {
              var doc = cm.doc, result = {};
              var curFragment = result.cursors = document.createDocumentFragment();
              var selFragment = result.selection = document.createDocumentFragment();
          
              for (var i = 0; i < doc.sel.ranges.length; i++) {
                if (primary === false && i == doc.sel.primIndex) continue;
                var range = doc.sel.ranges[i];
                var collapsed = range.empty();
                if (collapsed || cm.options.showCursorWhenSelecting)
                  drawSelectionCursor(cm, range, curFragment);
                if (!collapsed)
                  drawSelectionRange(cm, range, selFragment);
              }
              return result;
            }
          
            // Draws a cursor for the given range
            function drawSelectionCursor(cm, range, output) {
              var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);
          
              var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
              cursor.style.left = pos.left + "px";
              cursor.style.top = pos.top + "px";
              cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
          
              if (pos.other) {
                // Secondary cursor, shown when on a 'jump' in bi-directional text
                var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
                otherCursor.style.display = "";
                otherCursor.style.left = pos.other.left + "px";
                otherCursor.style.top = pos.other.top + "px";
                otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
              }
            }
          
            // Draws the given range as a highlighted selection
            function drawSelectionRange(cm, range, output) {
              var display = cm.display, doc = cm.doc;
              var fragment = document.createDocumentFragment();
              var padding = paddingH(cm.display), leftSide = padding.left;
              var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
          
              function add(left, top, width, bottom) {
                if (top < 0) top = 0;
                top = Math.round(top);
                bottom = Math.round(bottom);
                fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
                                         "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
                                         "px; height: " + (bottom - top) + "px"));
              }
          
              function drawForLine(line, fromArg, toArg) {
                var lineObj = getLine(doc, line);
                var lineLen = lineObj.text.length;
                var start, end;
                function coords(ch, bias) {
                  return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
                }
          
                iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
                  var leftPos = coords(from, "left"), rightPos, left, right;
                  if (from == to) {
                    rightPos = leftPos;
                    left = right = leftPos.left;
                  } else {
                    rightPos = coords(to - 1, "right");
                    if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
                    left = leftPos.left;
                    right = rightPos.right;
                  }
                  if (fromArg == null && from == 0) left = leftSide;
                  if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
                    add(left, leftPos.top, null, leftPos.bottom);
                    left = leftSide;
                    if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
                  }
                  if (toArg == null && to == lineLen) right = rightSide;
                  if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
                    start = leftPos;
                  if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
                    end = rightPos;
                  if (left < leftSide + 1) left = leftSide;
                  add(left, rightPos.top, right - left, rightPos.bottom);
                });
                return {start: start, end: end};
              }
          
              var sFrom = range.from(), sTo = range.to();
              if (sFrom.line == sTo.line) {
                drawForLine(sFrom.line, sFrom.ch, sTo.ch);
              } else {
                var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
                var singleVLine = visualLine(fromLine) == visualLine(toLine);
                var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
                var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
                if (singleVLine) {
                  if (leftEnd.top < rightStart.top - 2) {
                    add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
                    add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
                  } else {
                    add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
                  }
                }
                if (leftEnd.bottom < rightStart.top)
                  add(leftSide, leftEnd.bottom, null, rightStart.top);
              }
          
              output.appendChild(fragment);
            }
          
            // Cursor-blinking
            function restartBlink(cm) {
              if (!cm.state.focused) return;
              var display = cm.display;
              clearInterval(display.blinker);
              var on = true;
              display.cursorDiv.style.visibility = "";
              if (cm.options.cursorBlinkRate > 0)
                display.blinker = setInterval(function() {
                  display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
                }, cm.options.cursorBlinkRate);
              else if (cm.options.cursorBlinkRate < 0)
                display.cursorDiv.style.visibility = "hidden";
            }
          
            // HIGHLIGHT WORKER
          
            function startWorker(cm, time) {
              if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
                cm.state.highlight.set(time, bind(highlightWorker, cm));
            }
          
            function highlightWorker(cm) {
              var doc = cm.doc;
              if (doc.frontier < doc.first) doc.frontier = doc.first;
              if (doc.frontier >= cm.display.viewTo) return;
              var end = +new Date + cm.options.workTime;
              var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
              var changedLines = [];
          
              doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
                if (doc.frontier >= cm.display.viewFrom) { // Visible
                  var oldStyles = line.styles;
                  var highlighted = highlightLine(cm, line, state, true);
                  line.styles = highlighted.styles;
                  var oldCls = line.styleClasses, newCls = highlighted.classes;
                  if (newCls) line.styleClasses = newCls;
                  else if (oldCls) line.styleClasses = null;
                  var ischange = !oldStyles || oldStyles.length != line.styles.length ||
                    oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
                  for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
                  if (ischange) changedLines.push(doc.frontier);
                  line.stateAfter = copyState(doc.mode, state);
                } else {
                  processLine(cm, line.text, state);
                  line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
                }
                ++doc.frontier;
                if (+new Date > end) {
                  startWorker(cm, cm.options.workDelay);
                  return true;
                }
              });
              if (changedLines.length) runInOp(cm, function() {
                for (var i = 0; i < changedLines.length; i++)
                  regLineChange(cm, changedLines[i], "text");
              });
            }
          
            // Finds the line to start with when starting a parse. Tries to
            // find a line with a stateAfter, so that it can start with a
            // valid state. If that fails, it returns the line with the
            // smallest indentation, which tends to need the least context to
            // parse correctly.
            function findStartLine(cm, n, precise) {
              var minindent, minline, doc = cm.doc;
              var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
              for (var search = n; search > lim; --search) {
                if (search <= doc.first) return doc.first;
                var line = getLine(doc, search - 1);
                if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
                var indented = countColumn(line.text, null, cm.options.tabSize);
                if (minline == null || minindent > indented) {
                  minline = search - 1;
                  minindent = indented;
                }
              }
              return minline;
            }
          
            function getStateBefore(cm, n, precise) {
              var doc = cm.doc, display = cm.display;
              if (!doc.mode.startState) return true;
              var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
              if (!state) state = startState(doc.mode);
              else state = copyState(doc.mode, state);
              doc.iter(pos, n, function(line) {
                processLine(cm, line.text, state);
                var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
                line.stateAfter = save ? copyState(doc.mode, state) : null;
                ++pos;
              });
              if (precise) doc.frontier = pos;
              return state;
            }
          
            // POSITION MEASUREMENT
          
            function paddingTop(display) {return display.lineSpace.offsetTop;}
            function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
            function paddingH(display) {
              if (display.cachedPaddingH) return display.cachedPaddingH;
              var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
              var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
              var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
              if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
              return data;
            }
          
            function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
            function displayWidth(cm) {
              return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
            }
            function displayHeight(cm) {
              return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
            }
          
            // Ensure the lineView.wrapping.heights array is populated. This is
            // an array of bottom offsets for the lines that make up a drawn
            // line. When lineWrapping is on, there might be more than one
            // height.
            function ensureLineHeights(cm, lineView, rect) {
              var wrapping = cm.options.lineWrapping;
              var curWidth = wrapping && displayWidth(cm);
              if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
                var heights = lineView.measure.heights = [];
                if (wrapping) {
                  lineView.measure.width = curWidth;
                  var rects = lineView.text.firstChild.getClientRects();
                  for (var i = 0; i < rects.length - 1; i++) {
                    var cur = rects[i], next = rects[i + 1];
                    if (Math.abs(cur.bottom - next.bottom) > 2)
                      heights.push((cur.bottom + next.top) / 2 - rect.top);
                  }
                }
                heights.push(rect.bottom - rect.top);
              }
            }
          
            // Find a line map (mapping character offsets to text nodes) and a
            // measurement cache for the given line number. (A line view might
            // contain multiple lines when collapsed ranges are present.)
            function mapFromLineView(lineView, line, lineN) {
              if (lineView.line == line)
                return {map: lineView.measure.map, cache: lineView.measure.cache};
              for (var i = 0; i < lineView.rest.length; i++)
                if (lineView.rest[i] == line)
                  return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
              for (var i = 0; i < lineView.rest.length; i++)
                if (lineNo(lineView.rest[i]) > lineN)
                  return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
            }
          
            // Render a line into the hidden node display.externalMeasured. Used
            // when measurement is needed for a line that's not in the viewport.
            function updateExternalMeasurement(cm, line) {
              line = visualLine(line);
              var lineN = lineNo(line);
              var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
              view.lineN = lineN;
              var built = view.built = buildLineContent(cm, view);
              view.text = built.pre;
              removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
              return view;
            }
          
            // Get a {top, bottom, left, right} box (in line-local coordinates)
            // for a given character.
            function measureChar(cm, line, ch, bias) {
              return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
            }
          
            // Find a line view that corresponds to the given line number.
            function findViewForLine(cm, lineN) {
              if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
                return cm.display.view[findViewIndex(cm, lineN)];
              var ext = cm.display.externalMeasured;
              if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
                return ext;
            }
          
            // Measurement can be split in two steps, the set-up work that
            // applies to the whole line, and the measurement of the actual
            // character. Functions like coordsChar, that need to do a lot of
            // measurements in a row, can thus ensure that the set-up work is
            // only done once.
            function prepareMeasureForLine(cm, line) {
              var lineN = lineNo(line);
              var view = findViewForLine(cm, lineN);
              if (view && !view.text)
                view = null;
              else if (view && view.changes)
                updateLineForChanges(cm, view, lineN, getDimensions(cm));
              if (!view)
                view = updateExternalMeasurement(cm, line);
          
              var info = mapFromLineView(view, line, lineN);
              return {
                line: line, view: view, rect: null,
                map: info.map, cache: info.cache, before: info.before,
                hasHeights: false
              };
            }
          
            // Given a prepared measurement object, measures the position of an
            // actual character (or fetches it from the cache).
            function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
              if (prepared.before) ch = -1;
              var key = ch + (bias || ""), found;
              if (prepared.cache.hasOwnProperty(key)) {
                found = prepared.cache[key];
              } else {
                if (!prepared.rect)
                  prepared.rect = prepared.view.text.getBoundingClientRect();
                if (!prepared.hasHeights) {
                  ensureLineHeights(cm, prepared.view, prepared.rect);
                  prepared.hasHeights = true;
                }
                found = measureCharInner(cm, prepared, ch, bias);
                if (!found.bogus) prepared.cache[key] = found;
              }
              return {left: found.left, right: found.right,
                      top: varHeight ? found.rtop : found.top,
                      bottom: varHeight ? found.rbottom : found.bottom};
            }
          
            var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
          
            function nodeAndOffsetInLineMap(map, ch, bias) {
              var node, start, end, collapse;
              // First, search the line map for the text node corresponding to,
              // or closest to, the target character.
              for (var i = 0; i < map.length; i += 3) {
                var mStart = map[i], mEnd = map[i + 1];
                if (ch < mStart) {
                  start = 0; end = 1;
                  collapse = "left";
                } else if (ch < mEnd) {
                  start = ch - mStart;
                  end = start + 1;
                } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
                  end = mEnd - mStart;
                  start = end - 1;
                  if (ch >= mEnd) collapse = "right";
                }
                if (start != null) {
                  node = map[i + 2];
                  if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
                    collapse = bias;
                  if (bias == "left" && start == 0)
                    while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
                      node = map[(i -= 3) + 2];
                      collapse = "left";
                    }
                  if (bias == "right" && start == mEnd - mStart)
                    while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
                      node = map[(i += 3) + 2];
                      collapse = "right";
                    }
                  break;
                }
              }
              return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
            }
          
            function measureCharInner(cm, prepared, ch, bias) {
              var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
              var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
          
              var rect;
              if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
                for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
                  while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
                  while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
                  if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
                    rect = node.parentNode.getBoundingClientRect();
                  } else if (ie && cm.options.lineWrapping) {
                    var rects = range(node, start, end).getClientRects();
                    if (rects.length)
                      rect = rects[bias == "right" ? rects.length - 1 : 0];
                    else
                      rect = nullRect;
                  } else {
                    rect = range(node, start, end).getBoundingClientRect() || nullRect;
                  }
                  if (rect.left || rect.right || start == 0) break;
                  end = start;
                  start = start - 1;
                  collapse = "right";
                }
                if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
              } else { // If it is a widget, simply get the box for the whole widget.
                if (start > 0) collapse = bias = "right";
                var rects;
                if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
                  rect = rects[bias == "right" ? rects.length - 1 : 0];
                else
                  rect = node.getBoundingClientRect();
              }
              if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
                var rSpan = node.parentNode.getClientRects()[0];
                if (rSpan)
                  rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
                else
                  rect = nullRect;
              }
          
              var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
              var mid = (rtop + rbot) / 2;
              var heights = prepared.view.measure.heights;
              for (var i = 0; i < heights.length - 1; i++)
                if (mid < heights[i]) break;
              var top = i ? heights[i - 1] : 0, bot = heights[i];
              var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
                            right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
                            top: top, bottom: bot};
              if (!rect.left && !rect.right) result.bogus = true;
              if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
          
              return result;
            }
          
            // Work around problem with bounding client rects on ranges being
            // returned incorrectly when zoomed on IE10 and below.
            function maybeUpdateRectForZooming(measure, rect) {
              if (!window.screen || screen.logicalXDPI == null ||
                  screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
                return rect;
              var scaleX = screen.logicalXDPI / screen.deviceXDPI;
              var scaleY = screen.logicalYDPI / screen.deviceYDPI;
              return {left: rect.left * scaleX, right: rect.right * scaleX,
                      top: rect.top * scaleY, bottom: rect.bottom * scaleY};
            }
          
            function clearLineMeasurementCacheFor(lineView) {
              if (lineView.measure) {
                lineView.measure.cache = {};
                lineView.measure.heights = null;
                if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
                  lineView.measure.caches[i] = {};
              }
            }
          
            function clearLineMeasurementCache(cm) {
              cm.display.externalMeasure = null;
              removeChildren(cm.display.lineMeasure);
              for (var i = 0; i < cm.display.view.length; i++)
                clearLineMeasurementCacheFor(cm.display.view[i]);
            }
          
            function clearCaches(cm) {
              clearLineMeasurementCache(cm);
              cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
              if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
              cm.display.lineNumChars = null;
            }
          
            function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
            function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
          
            // Converts a {top, bottom, left, right} box from line-local
            // coordinates into another coordinate system. Context may be one of
            // "line", "div" (display.lineDiv), "local"/null (editor), "window",
            // or "page".
            function intoCoordSystem(cm, lineObj, rect, context) {
              if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
                var size = widgetHeight(lineObj.widgets[i]);
                rect.top += size; rect.bottom += size;
              }
              if (context == "line") return rect;
              if (!context) context = "local";
              var yOff = heightAtLine(lineObj);
              if (context == "local") yOff += paddingTop(cm.display);
              else yOff -= cm.display.viewOffset;
              if (context == "page" || context == "window") {
                var lOff = cm.display.lineSpace.getBoundingClientRect();
                yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
                var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
                rect.left += xOff; rect.right += xOff;
              }
              rect.top += yOff; rect.bottom += yOff;
              return rect;
            }
          
            // Coverts a box from "div" coords to another coordinate system.
            // Context may be "window", "page", "div", or "local"/null.
            function fromCoordSystem(cm, coords, context) {
              if (context == "div") return coords;
              var left = coords.left, top = coords.top;
              // First move into "page" coordinate system
              if (context == "page") {
                left -= pageScrollX();
                top -= pageScrollY();
              } else if (context == "local" || !context) {
                var localBox = cm.display.sizer.getBoundingClientRect();
                left += localBox.left;
                top += localBox.top;
              }
          
              var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
              return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
            }
          
            function charCoords(cm, pos, context, lineObj, bias) {
              if (!lineObj) lineObj = getLine(cm.doc, pos.line);
              return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
            }
          
            // Returns a box for a given cursor position, which may have an
            // 'other' property containing the position of the secondary cursor
            // on a bidi boundary.
            function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
              lineObj = lineObj || getLine(cm.doc, pos.line);
              if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
              function get(ch, right) {
                var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
                if (right) m.left = m.right; else m.right = m.left;
                return intoCoordSystem(cm, lineObj, m, context);
              }
              function getBidi(ch, partPos) {
                var part = order[partPos], right = part.level % 2;
                if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
                  part = order[--partPos];
                  ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
                  right = true;
                } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
                  part = order[++partPos];
                  ch = bidiLeft(part) - part.level % 2;
                  right = false;
                }
                if (right && ch == part.to && ch > part.from) return get(ch - 1);
                return get(ch, right);
              }
              var order = getOrder(lineObj), ch = pos.ch;
              if (!order) return get(ch);
              var partPos = getBidiPartAt(order, ch);
              var val = getBidi(ch, partPos);
              if (bidiOther != null) val.other = getBidi(ch, bidiOther);
              return val;
            }
          
            // Used to cheaply estimate the coordinates for a position. Used for
            // intermediate scroll updates.
            function estimateCoords(cm, pos) {
              var left = 0, pos = clipPos(cm.doc, pos);
              if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
              var lineObj = getLine(cm.doc, pos.line);
              var top = heightAtLine(lineObj) + paddingTop(cm.display);
              return {left: left, right: left, top: top, bottom: top + lineObj.height};
            }
          
            // Positions returned by coordsChar contain some extra information.
            // xRel is the relative x position of the input coordinates compared
            // to the found position (so xRel > 0 means the coordinates are to
            // the right of the character position, for example). When outside
            // is true, that means the coordinates lie outside the line's
            // vertical range.
            function PosWithInfo(line, ch, outside, xRel) {
              var pos = Pos(line, ch);
              pos.xRel = xRel;
              if (outside) pos.outside = true;
              return pos;
            }
          
            // Compute the character position closest to the given coordinates.
            // Input must be lineSpace-local ("div" coordinate system).
            function coordsChar(cm, x, y) {
              var doc = cm.doc;
              y += cm.display.viewOffset;
              if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
              var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
              if (lineN > last)
                return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
              if (x < 0) x = 0;
          
              var lineObj = getLine(doc, lineN);
              for (;;) {
                var found = coordsCharInner(cm, lineObj, lineN, x, y);
                var merged = collapsedSpanAtEnd(lineObj);
                var mergedPos = merged && merged.find(0, true);
                if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
                  lineN = lineNo(lineObj = mergedPos.to.line);
                else
                  return found;
              }
            }
          
            function coordsCharInner(cm, lineObj, lineNo, x, y) {
              var innerOff = y - heightAtLine(lineObj);
              var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
              var preparedMeasure = prepareMeasureForLine(cm, lineObj);
          
              function getX(ch) {
                var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
                wrongLine = true;
                if (innerOff > sp.bottom) return sp.left - adjust;
                else if (innerOff < sp.top) return sp.left + adjust;
                else wrongLine = false;
                return sp.left;
              }
          
              var bidi = getOrder(lineObj), dist = lineObj.text.length;
              var from = lineLeft(lineObj), to = lineRight(lineObj);
              var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
          
              if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
              // Do a binary search between these bounds.
              for (;;) {
                if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
                  var ch = x < fromX || x - fromX <= toX - x ? from : to;
                  var xDiff = x - (ch == from ? fromX : toX);
                  while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
                  var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
                                        xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
                  return pos;
                }
                var step = Math.ceil(dist / 2), middle = from + step;
                if (bidi) {
                  middle = from;
                  for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
                }
                var middleX = getX(middle);
                if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
                else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
              }
            }
          
            var measureText;
            // Compute the default text height.
            function textHeight(display) {
              if (display.cachedTextHeight != null) return display.cachedTextHeight;
              if (measureText == null) {
                measureText = elt("pre");
                // Measure a bunch of lines, for browsers that compute
                // fractional heights.
                for (var i = 0; i < 49; ++i) {
                  measureText.appendChild(document.createTextNode("x"));
                  measureText.appendChild(elt("br"));
                }
                measureText.appendChild(document.createTextNode("x"));
              }
              removeChildrenAndAdd(display.measure, measureText);
              var height = measureText.offsetHeight / 50;
              if (height > 3) display.cachedTextHeight = height;
              removeChildren(display.measure);
              return height || 1;
            }
          
            // Compute the default character width.
            function charWidth(display) {
              if (display.cachedCharWidth != null) return display.cachedCharWidth;
              var anchor = elt("span", "xxxxxxxxxx");
              var pre = elt("pre", [anchor]);
              removeChildrenAndAdd(display.measure, pre);
              var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
              if (width > 2) display.cachedCharWidth = width;
              return width || 10;
            }
          
            // OPERATIONS
          
            // Operations are used to wrap a series of changes to the editor
            // state in such a way that each change won't have to update the
            // cursor and display (which would be awkward, slow, and
            // error-prone). Instead, display updates are batched and then all
            // combined and executed at once.
          
            var operationGroup = null;
          
            var nextOpId = 0;
            // Start a new operation.
            function startOperation(cm) {
              cm.curOp = {
                cm: cm,
                viewChanged: false,      // Flag that indicates that lines might need to be redrawn
                startHeight: cm.doc.height, // Used to detect need to update scrollbar
                forceUpdate: false,      // Used to force a redraw
                updateInput: null,       // Whether to reset the input textarea
                typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
                changeObjs: null,        // Accumulated changes, for firing change events
                cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
                cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
                selectionChanged: false, // Whether the selection needs to be redrawn
                updateMaxLine: false,    // Set when the widest line needs to be determined anew
                scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
                scrollToPos: null,       // Used to scroll to a specific position
                id: ++nextOpId           // Unique ID
              };
              if (operationGroup) {
                operationGroup.ops.push(cm.curOp);
              } else {
                cm.curOp.ownsGroup = operationGroup = {
                  ops: [cm.curOp],
                  delayedCallbacks: []
                };
              }
            }
          
            function fireCallbacksForOps(group) {
              // Calls delayed callbacks and cursorActivity handlers until no
              // new ones appear
              var callbacks = group.delayedCallbacks, i = 0;
              do {
                for (; i < callbacks.length; i++)
                  callbacks[i]();
                for (var j = 0; j < group.ops.length; j++) {
                  var op = group.ops[j];
                  if (op.cursorActivityHandlers)
                    while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
                      op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
                }
              } while (i < callbacks.length);
            }
          
            // Finish an operation, updating the display and signalling delayed events
            function endOperation(cm) {
              var op = cm.curOp, group = op.ownsGroup;
              if (!group) return;
          
              try { fireCallbacksForOps(group); }
              finally {
                operationGroup = null;
                for (var i = 0; i < group.ops.length; i++)
                  group.ops[i].cm.curOp = null;
                endOperations(group);
              }
            }
          
            // The DOM updates done when an operation finishes are batched so
            // that the minimum number of relayouts are required.
            function endOperations(group) {
              var ops = group.ops;
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_R1(ops[i]);
              for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
                endOperation_W1(ops[i]);
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_R2(ops[i]);
              for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
                endOperation_W2(ops[i]);
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_finish(ops[i]);
            }
          
            function endOperation_R1(op) {
              var cm = op.cm, display = cm.display;
              maybeClipScrollbars(cm);
              if (op.updateMaxLine) findMaxLine(cm);
          
              op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
                op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
                                   op.scrollToPos.to.line >= display.viewTo) ||
                display.maxLineChanged && cm.options.lineWrapping;
              op.update = op.mustUpdate &&
                new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
            }
          
            function endOperation_W1(op) {
              op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
            }
          
            function endOperation_R2(op) {
              var cm = op.cm, display = cm.display;
              if (op.updatedDisplay) updateHeightsInViewport(cm);
          
              op.barMeasure = measureForScrollbars(cm);
          
              // If the max line changed since it was last measured, measure it,
              // and ensure the document's width matches it.
              // updateDisplay_W2 will use these properties to do the actual resizing
              if (display.maxLineChanged && !cm.options.lineWrapping) {
                op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
                cm.display.sizerWidth = op.adjustWidthTo;
                op.barMeasure.scrollWidth =
                  Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
                op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
              }
          
              if (op.updatedDisplay || op.selectionChanged)
                op.preparedSelection = display.input.prepareSelection();
            }
          
            function endOperation_W2(op) {
              var cm = op.cm;
          
              if (op.adjustWidthTo != null) {
                cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
                if (op.maxScrollLeft < cm.doc.scrollLeft)
                  setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
                cm.display.maxLineChanged = false;
              }
          
              if (op.preparedSelection)
                cm.display.input.showSelection(op.preparedSelection);
              if (op.updatedDisplay)
                setDocumentHeight(cm, op.barMeasure);
              if (op.updatedDisplay || op.startHeight != cm.doc.height)
                updateScrollbars(cm, op.barMeasure);
          
              if (op.selectionChanged) restartBlink(cm);
          
              if (cm.state.focused && op.updateInput)
                cm.display.input.reset(op.typing);
            }
          
            function endOperation_finish(op) {
              var cm = op.cm, display = cm.display, doc = cm.doc;
          
              if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
          
              // Abort mouse wheel delta measurement, when scrolling explicitly
              if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
                display.wheelStartX = display.wheelStartY = null;
          
              // Propagate the scroll position to the actual DOM scroller
              if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
                doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
                display.scrollbars.setScrollTop(doc.scrollTop);
                display.scroller.scrollTop = doc.scrollTop;
              }
              if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
                doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
                display.scrollbars.setScrollLeft(doc.scrollLeft);
                display.scroller.scrollLeft = doc.scrollLeft;
                alignHorizontally(cm);
              }
              // If we need to scroll a specific position into view, do so.
              if (op.scrollToPos) {
                var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
                                               clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
                if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
              }
          
              // Fire events for markers that are hidden/unidden by editing or
              // undoing
              var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
              if (hidden) for (var i = 0; i < hidden.length; ++i)
                if (!hidden[i].lines.length) signal(hidden[i], "hide");
              if (unhidden) for (var i = 0; i < unhidden.length; ++i)
                if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
          
              if (display.wrapper.offsetHeight)
                doc.scrollTop = cm.display.scroller.scrollTop;
          
              // Fire change events, and delayed event handlers
              if (op.changeObjs)
                signal(cm, "changes", cm, op.changeObjs);
              if (op.update)
                op.update.finish();
            }
          
            // Run the given function in an operation
            function runInOp(cm, f) {
              if (cm.curOp) return f();
              startOperation(cm);
              try { return f(); }
              finally { endOperation(cm); }
            }
            // Wraps a function in an operation. Returns the wrapped function.
            function operation(cm, f) {
              return function() {
                if (cm.curOp) return f.apply(cm, arguments);
                startOperation(cm);
                try { return f.apply(cm, arguments); }
                finally { endOperation(cm); }
              };
            }
            // Used to add methods to editor and doc instances, wrapping them in
            // operations.
            function methodOp(f) {
              return function() {
                if (this.curOp) return f.apply(this, arguments);
                startOperation(this);
                try { return f.apply(this, arguments); }
                finally { endOperation(this); }
              };
            }
            function docMethodOp(f) {
              return function() {
                var cm = this.cm;
                if (!cm || cm.curOp) return f.apply(this, arguments);
                startOperation(cm);
                try { return f.apply(this, arguments); }
                finally { endOperation(cm); }
              };
            }
          
            // VIEW TRACKING
          
            // These objects are used to represent the visible (currently drawn)
            // part of the document. A LineView may correspond to multiple
            // logical lines, if those are connected by collapsed ranges.
            function LineView(doc, line, lineN) {
              // The starting line
              this.line = line;
              // Continuing lines, if any
              this.rest = visualLineContinued(line);
              // Number of logical lines in this visual line
              this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
              this.node = this.text = null;
              this.hidden = lineIsHidden(doc, line);
            }
          
            // Create a range of LineView objects for the given lines.
            function buildViewArray(cm, from, to) {
              var array = [], nextPos;
              for (var pos = from; pos < to; pos = nextPos) {
                var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
                nextPos = pos + view.size;
                array.push(view);
              }
              return array;
            }
          
            // Updates the display.view data structure for a given change to the
            // document. From and to are in pre-change coordinates. Lendiff is
            // the amount of lines added or subtracted by the change. This is
            // used for changes that span multiple lines, or change the way
            // lines are divided into visual lines. regLineChange (below)
            // registers single-line changes.
            function regChange(cm, from, to, lendiff) {
              if (from == null) from = cm.doc.first;
              if (to == null) to = cm.doc.first + cm.doc.size;
              if (!lendiff) lendiff = 0;
          
              var display = cm.display;
              if (lendiff && to < display.viewTo &&
                  (display.updateLineNumbers == null || display.updateLineNumbers > from))
                display.updateLineNumbers = from;
          
              cm.curOp.viewChanged = true;
          
              if (from >= display.viewTo) { // Change after
                if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
                  resetView(cm);
              } else if (to <= display.viewFrom) { // Change before
                if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
                  resetView(cm);
                } else {
                  display.viewFrom += lendiff;
                  display.viewTo += lendiff;
                }
              } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
                resetView(cm);
              } else if (from <= display.viewFrom) { // Top overlap
                var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
                if (cut) {
                  display.view = display.view.slice(cut.index);
                  display.viewFrom = cut.lineN;
                  display.viewTo += lendiff;
                } else {
                  resetView(cm);
                }
              } else if (to >= display.viewTo) { // Bottom overlap
                var cut = viewCuttingPoint(cm, from, from, -1);
                if (cut) {
                  display.view = display.view.slice(0, cut.index);
                  display.viewTo = cut.lineN;
                } else {
                  resetView(cm);
                }
              } else { // Gap in the middle
                var cutTop = viewCuttingPoint(cm, from, from, -1);
                var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
                if (cutTop && cutBot) {
                  display.view = display.view.slice(0, cutTop.index)
                    .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
                    .concat(display.view.slice(cutBot.index));
                  display.viewTo += lendiff;
                } else {
                  resetView(cm);
                }
              }
          
              var ext = display.externalMeasured;
              if (ext) {
                if (to < ext.lineN)
                  ext.lineN += lendiff;
                else if (from < ext.lineN + ext.size)
                  display.externalMeasured = null;
              }
            }
          
            // Register a change to a single line. Type must be one of "text",
            // "gutter", "class", "widget"
            function regLineChange(cm, line, type) {
              cm.curOp.viewChanged = true;
              var display = cm.display, ext = cm.display.externalMeasured;
              if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
                display.externalMeasured = null;
          
              if (line < display.viewFrom || line >= display.viewTo) return;
              var lineView = display.view[findViewIndex(cm, line)];
              if (lineView.node == null) return;
              var arr = lineView.changes || (lineView.changes = []);
              if (indexOf(arr, type) == -1) arr.push(type);
            }
          
            // Clear the view.
            function resetView(cm) {
              cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
              cm.display.view = [];
              cm.display.viewOffset = 0;
            }
          
            // Find the view element corresponding to a given line. Return null
            // when the line isn't visible.
            function findViewIndex(cm, n) {
              if (n >= cm.display.viewTo) return null;
              n -= cm.display.viewFrom;
              if (n < 0) return null;
              var view = cm.display.view;
              for (var i = 0; i < view.length; i++) {
                n -= view[i].size;
                if (n < 0) return i;
              }
            }
          
            function viewCuttingPoint(cm, oldN, newN, dir) {
              var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
              if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
                return {index: index, lineN: newN};
              for (var i = 0, n = cm.display.viewFrom; i < index; i++)
                n += view[i].size;
              if (n != oldN) {
                if (dir > 0) {
                  if (index == view.length - 1) return null;
                  diff = (n + view[index].size) - oldN;
                  index++;
                } else {
                  diff = n - oldN;
                }
                oldN += diff; newN += diff;
              }
              while (visualLineNo(cm.doc, newN) != newN) {
                if (index == (dir < 0 ? 0 : view.length - 1)) return null;
                newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
                index += dir;
              }
              return {index: index, lineN: newN};
            }
          
            // Force the view to cover a given range, adding empty view element
            // or clipping off existing ones as needed.
            function adjustView(cm, from, to) {
              var display = cm.display, view = display.view;
              if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
                display.view = buildViewArray(cm, from, to);
                display.viewFrom = from;
              } else {
                if (display.viewFrom > from)
                  display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
                else if (display.viewFrom < from)
                  display.view = display.view.slice(findViewIndex(cm, from));
                display.viewFrom = from;
                if (display.viewTo < to)
                  display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
                else if (display.viewTo > to)
                  display.view = display.view.slice(0, findViewIndex(cm, to));
              }
              display.viewTo = to;
            }
          
            // Count the number of lines in the view whose DOM representation is
            // out of date (or nonexistent).
            function countDirtyView(cm) {
              var view = cm.display.view, dirty = 0;
              for (var i = 0; i < view.length; i++) {
                var lineView = view[i];
                if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
              }
              return dirty;
            }
          
            // EVENT HANDLERS
          
            // Attach the necessary event handlers when initializing the editor
            function registerEventHandlers(cm) {
              var d = cm.display;
              on(d.scroller, "mousedown", operation(cm, onMouseDown));
              // Older IE's will not fire a second mousedown for a double click
              if (ie && ie_version < 11)
                on(d.scroller, "dblclick", operation(cm, function(e) {
                  if (signalDOMEvent(cm, e)) return;
                  var pos = posFromMouse(cm, e);
                  if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
                  e_preventDefault(e);
                  var word = cm.findWordAt(pos);
                  extendSelection(cm.doc, word.anchor, word.head);
                }));
              else
                on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
              // Some browsers fire contextmenu *after* opening the menu, at
              // which point we can't mess with it anymore. Context menu is
              // handled in onMouseDown for these browsers.
              if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
          
              // Used to suppress mouse event handling when a touch happens
              var touchFinished, prevTouch = {end: 0};
              function finishTouch() {
                if (d.activeTouch) {
                  touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
                  prevTouch = d.activeTouch;
                  prevTouch.end = +new Date;
                }
              };
              function isMouseLikeTouchEvent(e) {
                if (e.touches.length != 1) return false;
                var touch = e.touches[0];
                return touch.radiusX <= 1 && touch.radiusY <= 1;
              }
              function farAway(touch, other) {
                if (other.left == null) return true;
                var dx = other.left - touch.left, dy = other.top - touch.top;
                return dx * dx + dy * dy > 20 * 20;
              }
              on(d.scroller, "touchstart", function(e) {
                if (!isMouseLikeTouchEvent(e)) {
                  clearTimeout(touchFinished);
                  var now = +new Date;
                  d.activeTouch = {start: now, moved: false,
                                   prev: now - prevTouch.end <= 300 ? prevTouch : null};
                  if (e.touches.length == 1) {
                    d.activeTouch.left = e.touches[0].pageX;
                    d.activeTouch.top = e.touches[0].pageY;
                  }
                }
              });
              on(d.scroller, "touchmove", function() {
                if (d.activeTouch) d.activeTouch.moved = true;
              });
              on(d.scroller, "touchend", function(e) {
                var touch = d.activeTouch;
                if (touch && !eventInWidget(d, e) && touch.left != null &&
                    !touch.moved && new Date - touch.start < 300) {
                  var pos = cm.coordsChar(d.activeTouch, "page"), range;
                  if (!touch.prev || farAway(touch, touch.prev)) // Single tap
                    range = new Range(pos, pos);
                  else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
                    range = cm.findWordAt(pos);
                  else // Triple tap
                    range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
                  cm.setSelection(range.anchor, range.head);
                  cm.focus();
                  e_preventDefault(e);
                }
                finishTouch();
              });
              on(d.scroller, "touchcancel", finishTouch);
          
              // Sync scrolling between fake scrollbars and real scrollable
              // area, ensure viewport is updated when scrolling.
              on(d.scroller, "scroll", function() {
                if (d.scroller.clientHeight) {
                  setScrollTop(cm, d.scroller.scrollTop);
                  setScrollLeft(cm, d.scroller.scrollLeft, true);
                  signal(cm, "scroll", cm);
                }
              });
          
              // Listen to wheel events in order to try and update the viewport on time.
              on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
              on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
          
              // Prevent wrapper from ever scrolling
              on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
          
              function drag_(e) {
                if (!signalDOMEvent(cm, e)) e_stop(e);
              }
              if (cm.options.dragDrop) {
                on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
                on(d.scroller, "dragenter", drag_);
                on(d.scroller, "dragover", drag_);
                on(d.scroller, "drop", operation(cm, onDrop));
              }
          
              var inp = d.input.getField();
              on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
              on(inp, "keydown", operation(cm, onKeyDown));
              on(inp, "keypress", operation(cm, onKeyPress));
              on(inp, "focus", bind(onFocus, cm));
              on(inp, "blur", bind(onBlur, cm));
            }
          
            // Called when the window resizes
            function onResize(cm) {
              var d = cm.display;
              if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
                return;
              // Might be a text scaling operation, clear size caches.
              d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
              d.scrollbarsClipped = false;
              cm.setSize();
            }
          
            // MOUSE EVENTS
          
            // Return true when the given mouse event happened in a widget
            function eventInWidget(display, e) {
              for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
                if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
                    (n.parentNode == display.sizer && n != display.mover))
                  return true;
              }
            }
          
            // Given a mouse event, find the corresponding position. If liberal
            // is false, it checks whether a gutter or scrollbar was clicked,
            // and returns null if it was. forRect is used by rectangular
            // selections, and tries to estimate a character position even for
            // coordinates beyond the right of the text.
            function posFromMouse(cm, e, liberal, forRect) {
              var display = cm.display;
              if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
          
              var x, y, space = display.lineSpace.getBoundingClientRect();
              // Fails unpredictably on IE[67] when mouse is dragged around quickly.
              try { x = e.clientX - space.left; y = e.clientY - space.top; }
              catch (e) { return null; }
              var coords = coordsChar(cm, x, y), line;
              if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
                var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
                coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
              }
              return coords;
            }
          
            // A mouse down can be a single click, double click, triple click,
            // start of selection drag, start of text drag, new cursor
            // (ctrl-click), rectangle drag (alt-drag), or xwin
            // middle-click-paste. Or it might be a click on something we should
            // not interfere with, such as a scrollbar or widget.
            function onMouseDown(e) {
              var cm = this, display = cm.display;
              if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
              display.shift = e.shiftKey;
          
              if (eventInWidget(display, e)) {
                if (!webkit) {
                  // Briefly turn off draggability, to allow widgets to do
                  // normal dragging things.
                  display.scroller.draggable = false;
                  setTimeout(function(){display.scroller.draggable = true;}, 100);
                }
                return;
              }
              if (clickInGutter(cm, e)) return;
              var start = posFromMouse(cm, e);
              window.focus();
          
              switch (e_button(e)) {
              case 1:
                if (start)
                  leftButtonDown(cm, e, start);
                else if (e_target(e) == display.scroller)
                  e_preventDefault(e);
                break;
              case 2:
                if (webkit) cm.state.lastMiddleDown = +new Date;
                if (start) extendSelection(cm.doc, start);
                setTimeout(function() {display.input.focus();}, 20);
                e_preventDefault(e);
                break;
              case 3:
                if (captureRightClick) onContextMenu(cm, e);
                break;
              }
            }
          
            var lastClick, lastDoubleClick;
            function leftButtonDown(cm, e, start) {
              if (ie) setTimeout(bind(ensureFocus, cm), 0);
              else ensureFocus(cm);
          
              var now = +new Date, type;
              if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
                type = "triple";
              } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
                type = "double";
                lastDoubleClick = {time: now, pos: start};
              } else {
                type = "single";
                lastClick = {time: now, pos: start};
              }
          
              var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
              if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
                  type == "single" && (contained = sel.contains(start)) > -1 &&
                  !sel.ranges[contained].empty())
                leftButtonStartDrag(cm, e, start, modifier);
              else
                leftButtonSelect(cm, e, start, type, modifier);
            }
          
            // Start a text drag. When it ends, see if any dragging actually
            // happen, and treat as a click if it didn't.
            function leftButtonStartDrag(cm, e, start, modifier) {
              var display = cm.display;
              var dragEnd = operation(cm, function(e2) {
                if (webkit) display.scroller.draggable = false;
                cm.state.draggingText = false;
                off(document, "mouseup", dragEnd);
                off(display.scroller, "drop", dragEnd);
                if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
                  e_preventDefault(e2);
                  if (!modifier)
                    extendSelection(cm.doc, start);
                  display.input.focus();
                  // Work around unexplainable focus problem in IE9 (#2127)
                  if (ie && ie_version == 9)
                    setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
                }
              });
              // Let the drag handler handle this.
              if (webkit) display.scroller.draggable = true;
              cm.state.draggingText = dragEnd;
              // IE's approach to draggable
              if (display.scroller.dragDrop) display.scroller.dragDrop();
              on(document, "mouseup", dragEnd);
              on(display.scroller, "drop", dragEnd);
            }
          
            // Normal selection, as opposed to text dragging.
            function leftButtonSelect(cm, e, start, type, addNew) {
              var display = cm.display, doc = cm.doc;
              e_preventDefault(e);
          
              var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
              if (addNew && !e.shiftKey) {
                ourIndex = doc.sel.contains(start);
                if (ourIndex > -1)
                  ourRange = ranges[ourIndex];
                else
                  ourRange = new Range(start, start);
              } else {
                ourRange = doc.sel.primary();
              }
          
              if (e.altKey) {
                type = "rect";
                if (!addNew) ourRange = new Range(start, start);
                start = posFromMouse(cm, e, true, true);
                ourIndex = -1;
              } else if (type == "double") {
                var word = cm.findWordAt(start);
                if (cm.display.shift || doc.extend)
                  ourRange = extendRange(doc, ourRange, word.anchor, word.head);
                else
                  ourRange = word;
              } else if (type == "triple") {
                var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
                if (cm.display.shift || doc.extend)
                  ourRange = extendRange(doc, ourRange, line.anchor, line.head);
                else
                  ourRange = line;
              } else {
                ourRange = extendRange(doc, ourRange, start);
              }
          
              if (!addNew) {
                ourIndex = 0;
                setSelection(doc, new Selection([ourRange], 0), sel_mouse);
                startSel = doc.sel;
              } else if (ourIndex == -1) {
                ourIndex = ranges.length;
                setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
                             {scroll: false, origin: "*mouse"});
              } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
                setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
                startSel = doc.sel;
              } else {
                replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
              }
          
              var lastPos = start;
              function extendTo(pos) {
                if (cmp(lastPos, pos) == 0) return;
                lastPos = pos;
          
                if (type == "rect") {
                  var ranges = [], tabSize = cm.options.tabSize;
                  var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
                  var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
                  var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
                  for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
                       line <= end; line++) {
                    var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
                    if (left == right)
                      ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
                    else if (text.length > leftPos)
                      ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
                  }
                  if (!ranges.length) ranges.push(new Range(start, start));
                  setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
                               {origin: "*mouse", scroll: false});
                  cm.scrollIntoView(pos);
                } else {
                  var oldRange = ourRange;
                  var anchor = oldRange.anchor, head = pos;
                  if (type != "single") {
                    if (type == "double")
                      var range = cm.findWordAt(pos);
                    else
                      var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
                    if (cmp(range.anchor, anchor) > 0) {
                      head = range.head;
                      anchor = minPos(oldRange.from(), range.anchor);
                    } else {
                      head = range.anchor;
                      anchor = maxPos(oldRange.to(), range.head);
                    }
                  }
                  var ranges = startSel.ranges.slice(0);
                  ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
                  setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
                }
              }
          
              var editorSize = display.wrapper.getBoundingClientRect();
              // Used to ensure timeout re-tries don't fire when another extend
              // happened in the meantime (clearTimeout isn't reliable -- at
              // least on Chrome, the timeouts still happen even when cleared,
              // if the clear happens after their scheduled firing time).
              var counter = 0;
          
              function extend(e) {
                var curCount = ++counter;
                var cur = posFromMouse(cm, e, true, type == "rect");
                if (!cur) return;
                if (cmp(cur, lastPos) != 0) {
                  ensureFocus(cm);
                  extendTo(cur);
                  var visible = visibleLines(display, doc);
                  if (cur.line >= visible.to || cur.line < visible.from)
                    setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
                } else {
                  var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
                  if (outside) setTimeout(operation(cm, function() {
                    if (counter != curCount) return;
                    display.scroller.scrollTop += outside;
                    extend(e);
                  }), 50);
                }
              }
          
              function done(e) {
                counter = Infinity;
                e_preventDefault(e);
                display.input.focus();
                off(document, "mousemove", move);
                off(document, "mouseup", up);
                doc.history.lastSelOrigin = null;
              }
          
              var move = operation(cm, function(e) {
                if (!e_button(e)) done(e);
                else extend(e);
              });
              var up = operation(cm, done);
              on(document, "mousemove", move);
              on(document, "mouseup", up);
            }
          
            // Determines whether an event happened in the gutter, and fires the
            // handlers for the corresponding event.
            function gutterEvent(cm, e, type, prevent, signalfn) {
              try { var mX = e.clientX, mY = e.clientY; }
              catch(e) { return false; }
              if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
              if (prevent) e_preventDefault(e);
          
              var display = cm.display;
              var lineBox = display.lineDiv.getBoundingClientRect();
          
              if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
              mY -= lineBox.top - display.viewOffset;
          
              for (var i = 0; i < cm.options.gutters.length; ++i) {
                var g = display.gutters.childNodes[i];
                if (g && g.getBoundingClientRect().right >= mX) {
                  var line = lineAtHeight(cm.doc, mY);
                  var gutter = cm.options.gutters[i];
                  signalfn(cm, type, cm, line, gutter, e);
                  return e_defaultPrevented(e);
                }
              }
            }
          
            function clickInGutter(cm, e) {
              return gutterEvent(cm, e, "gutterClick", true, signalLater);
            }
          
            // Kludge to work around strange IE behavior where it'll sometimes
            // re-fire a series of drag-related events right after the drop (#1551)
            var lastDrop = 0;
          
            function onDrop(e) {
              var cm = this;
              if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
                return;
              e_preventDefault(e);
              if (ie) lastDrop = +new Date;
              var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
              if (!pos || isReadOnly(cm)) return;
              // Might be a file drop, in which case we simply extract the text
              // and insert it.
              if (files && files.length && window.FileReader && window.File) {
                var n = files.length, text = Array(n), read = 0;
                var loadFile = function(file, i) {
                  var reader = new FileReader;
                  reader.onload = operation(cm, function() {
                    text[i] = reader.result;
                    if (++read == n) {
                      pos = clipPos(cm.doc, pos);
                      var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
                      makeChange(cm.doc, change);
                      setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
                    }
                  });
                  reader.readAsText(file);
                };
                for (var i = 0; i < n; ++i) loadFile(files[i], i);
              } else { // Normal drop
                // Don't do a replace if the drop happened inside of the selected text.
                if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
                  cm.state.draggingText(e);
                  // Ensure the editor is re-focused
                  setTimeout(function() {cm.display.input.focus();}, 20);
                  return;
                }
                try {
                  var text = e.dataTransfer.getData("Text");
                  if (text) {
                    if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
                      var selected = cm.listSelections();
                    setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
                    if (selected) for (var i = 0; i < selected.length; ++i)
                      replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
                    cm.replaceSelection(text, "around", "paste");
                    cm.display.input.focus();
                  }
                }
                catch(e){}
              }
            }
          
            function onDragStart(cm, e) {
              if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
              if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
          
              e.dataTransfer.setData("Text", cm.getSelection());
          
              // Use dummy image instead of default browsers image.
              // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
              if (e.dataTransfer.setDragImage && !safari) {
                var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
                img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
                if (presto) {
                  img.width = img.height = 1;
                  cm.display.wrapper.appendChild(img);
                  // Force a relayout, or Opera won't use our image for some obscure reason
                  img._top = img.offsetTop;
                }
                e.dataTransfer.setDragImage(img, 0, 0);
                if (presto) img.parentNode.removeChild(img);
              }
            }
          
            // SCROLL EVENTS
          
            // Sync the scrollable area and scrollbars, ensure the viewport
            // covers the visible area.
            function setScrollTop(cm, val) {
              if (Math.abs(cm.doc.scrollTop - val) < 2) return;
              cm.doc.scrollTop = val;
              if (!gecko) updateDisplaySimple(cm, {top: val});
              if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
              cm.display.scrollbars.setScrollTop(val);
              if (gecko) updateDisplaySimple(cm);
              startWorker(cm, 100);
            }
            // Sync scroller and scrollbar, ensure the gutter elements are
            // aligned.
            function setScrollLeft(cm, val, isScroller) {
              if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
              val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
              cm.doc.scrollLeft = val;
              alignHorizontally(cm);
              if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
              cm.display.scrollbars.setScrollLeft(val);
            }
          
            // Since the delta values reported on mouse wheel events are
            // unstandardized between browsers and even browser versions, and
            // generally horribly unpredictable, this code starts by measuring
            // the scroll effect that the first few mouse wheel events have,
            // and, from that, detects the way it can convert deltas to pixel
            // offsets afterwards.
            //
            // The reason we want to know the amount a wheel event will scroll
            // is that it gives us a chance to update the display before the
            // actual scrolling happens, reducing flickering.
          
            var wheelSamples = 0, wheelPixelsPerUnit = null;
            // Fill in a browser-detected starting value on browsers where we
            // know one. These don't have to be accurate -- the result of them
            // being wrong would just be a slight flicker on the first wheel
            // scroll (if it is large enough).
            if (ie) wheelPixelsPerUnit = -.53;
            else if (gecko) wheelPixelsPerUnit = 15;
            else if (chrome) wheelPixelsPerUnit = -.7;
            else if (safari) wheelPixelsPerUnit = -1/3;
          
            var wheelEventDelta = function(e) {
              var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
              if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
              if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
              else if (dy == null) dy = e.wheelDelta;
              return {x: dx, y: dy};
            };
            CodeMirror.wheelEventPixels = function(e) {
              var delta = wheelEventDelta(e);
              delta.x *= wheelPixelsPerUnit;
              delta.y *= wheelPixelsPerUnit;
              return delta;
            };
          
            function onScrollWheel(cm, e) {
              var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
          
              var display = cm.display, scroll = display.scroller;
              // Quit if there's nothing to scroll here
              if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
                    dy && scroll.scrollHeight > scroll.clientHeight)) return;
          
              // Webkit browsers on OS X abort momentum scrolls when the target
              // of the scroll event is removed from the scrollable element.
              // This hack (see related code in patchDisplay) makes sure the
              // element is kept around.
              if (dy && mac && webkit) {
                outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
                  for (var i = 0; i < view.length; i++) {
                    if (view[i].node == cur) {
                      cm.display.currentWheelTarget = cur;
                      break outer;
                    }
                  }
                }
              }
          
              // On some browsers, horizontal scrolling will cause redraws to
              // happen before the gutter has been realigned, causing it to
              // wriggle around in a most unseemly way. When we have an
              // estimated pixels/delta value, we just handle horizontal
              // scrolling entirely here. It'll be slightly off from native, but
              // better than glitching out.
              if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
                if (dy)
                  setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
                setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
                e_preventDefault(e);
                display.wheelStartX = null; // Abort measurement, if in progress
                return;
              }
          
              // 'Project' the visible viewport to cover the area that is being
              // scrolled into view (if we know enough to estimate it).
              if (dy && wheelPixelsPerUnit != null) {
                var pixels = dy * wheelPixelsPerUnit;
                var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
                if (pixels < 0) top = Math.max(0, top + pixels - 50);
                else bot = Math.min(cm.doc.height, bot + pixels + 50);
                updateDisplaySimple(cm, {top: top, bottom: bot});
              }
          
              if (wheelSamples < 20) {
                if (display.wheelStartX == null) {
                  display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
                  display.wheelDX = dx; display.wheelDY = dy;
                  setTimeout(function() {
                    if (display.wheelStartX == null) return;
                    var movedX = scroll.scrollLeft - display.wheelStartX;
                    var movedY = scroll.scrollTop - display.wheelStartY;
                    var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
                      (movedX && display.wheelDX && movedX / display.wheelDX);
                    display.wheelStartX = display.wheelStartY = null;
                    if (!sample) return;
                    wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
                    ++wheelSamples;
                  }, 200);
                } else {
                  display.wheelDX += dx; display.wheelDY += dy;
                }
              }
            }
          
            // KEY EVENTS
          
            // Run a handler that was bound to a key.
            function doHandleBinding(cm, bound, dropShift) {
              if (typeof bound == "string") {
                bound = commands[bound];
                if (!bound) return false;
              }
              // Ensure previous input has been read, so that the handler sees a
              // consistent view of the document
              cm.display.input.ensurePolled();
              var prevShift = cm.display.shift, done = false;
              try {
                if (isReadOnly(cm)) cm.state.suppressEdits = true;
                if (dropShift) cm.display.shift = false;
                done = bound(cm) != Pass;
              } finally {
                cm.display.shift = prevShift;
                cm.state.suppressEdits = false;
              }
              return done;
            }
          
            function lookupKeyForEditor(cm, name, handle) {
              for (var i = 0; i < cm.state.keyMaps.length; i++) {
                var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
                if (result) return result;
              }
              return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
                || lookupKey(name, cm.options.keyMap, handle, cm);
            }
          
            var stopSeq = new Delayed;
            function dispatchKey(cm, name, e, handle) {
              var seq = cm.state.keySeq;
              if (seq) {
                if (isModifierKey(name)) return "handled";
                stopSeq.set(50, function() {
                  if (cm.state.keySeq == seq) {
                    cm.state.keySeq = null;
                    cm.display.input.reset();
                  }
                });
                name = seq + " " + name;
              }
              var result = lookupKeyForEditor(cm, name, handle);
          
              if (result == "multi")
                cm.state.keySeq = name;
              if (result == "handled")
                signalLater(cm, "keyHandled", cm, name, e);
          
              if (result == "handled" || result == "multi") {
                e_preventDefault(e);
                restartBlink(cm);
              }
          
              if (seq && !result && /\'$/.test(name)) {
                e_preventDefault(e);
                return true;
              }
              return !!result;
            }
          
            // Handle a key from the keydown event.
            function handleKeyBinding(cm, e) {
              var name = keyName(e, true);
              if (!name) return false;
          
              if (e.shiftKey && !cm.state.keySeq) {
                // First try to resolve full name (including 'Shift-'). Failing
                // that, see if there is a cursor-motion command (starting with
                // 'go') bound to the keyname without 'Shift-'.
                return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
                    || dispatchKey(cm, name, e, function(b) {
                         if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
                           return doHandleBinding(cm, b);
                       });
              } else {
                return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
              }
            }
          
            // Handle a key from the keypress event
            function handleCharBinding(cm, e, ch) {
              return dispatchKey(cm, "'" + ch + "'", e,
                                 function(b) { return doHandleBinding(cm, b, true); });
            }
          
            var lastStoppedKey = null;
            function onKeyDown(e) {
              var cm = this;
              ensureFocus(cm);
              if (signalDOMEvent(cm, e)) return;
              // IE does strange things with escape.
              if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
              var code = e.keyCode;
              cm.display.shift = code == 16 || e.shiftKey;
              var handled = handleKeyBinding(cm, e);
              if (presto) {
                lastStoppedKey = handled ? code : null;
                // Opera has no cut event... we try to at least catch the key combo
                if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
                  cm.replaceSelection("", null, "cut");
              }
          
              // Turn mouse into crosshair when Alt is held on Mac.
              if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
                showCrossHair(cm);
            }
          
            function showCrossHair(cm) {
              var lineDiv = cm.display.lineDiv;
              addClass(lineDiv, "CodeMirror-crosshair");
          
              function up(e) {
                if (e.keyCode == 18 || !e.altKey) {
                  rmClass(lineDiv, "CodeMirror-crosshair");
                  off(document, "keyup", up);
                  off(document, "mouseover", up);
                }
              }
              on(document, "keyup", up);
              on(document, "mouseover", up);
            }
          
            function onKeyUp(e) {
              if (e.keyCode == 16) this.doc.sel.shift = false;
              signalDOMEvent(this, e);
            }
          
            function onKeyPress(e) {
              var cm = this;
              if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
              var keyCode = e.keyCode, charCode = e.charCode;
              if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
              if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
              var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
              if (handleCharBinding(cm, e, ch)) return;
              cm.display.input.onKeyPress(e);
            }
          
            // FOCUS/BLUR EVENTS
          
            function onFocus(cm) {
              if (cm.options.readOnly == "nocursor") return;
              if (!cm.state.focused) {
                signal(cm, "focus", cm);
                cm.state.focused = true;
                addClass(cm.display.wrapper, "CodeMirror-focused");
                // This test prevents this from firing when a context
                // menu is closed (since the input reset would kill the
                // select-all detection hack)
                if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
                  cm.display.input.reset();
                  if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
                }
                cm.display.input.receivedFocus();
              }
              restartBlink(cm);
            }
            function onBlur(cm) {
              if (cm.state.focused) {
                signal(cm, "blur", cm);
                cm.state.focused = false;
                rmClass(cm.display.wrapper, "CodeMirror-focused");
              }
              clearInterval(cm.display.blinker);
              setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
            }
          
            // CONTEXT MENU HANDLING
          
            // To make the context menu work, we need to briefly unhide the
            // textarea (making it as unobtrusive as possible) to let the
            // right-click take effect on it.
            function onContextMenu(cm, e) {
              if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
              cm.display.input.onContextMenu(e);
            }
          
            function contextMenuInGutter(cm, e) {
              if (!hasHandler(cm, "gutterContextMenu")) return false;
              return gutterEvent(cm, e, "gutterContextMenu", false, signal);
            }
          
            // UPDATING
          
            // Compute the position of the end of a change (its 'to' property
            // refers to the pre-change end).
            var changeEnd = CodeMirror.changeEnd = function(change) {
              if (!change.text) return change.to;
              return Pos(change.from.line + change.text.length - 1,
                         lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
            };
          
            // Adjust a position to refer to the post-change position of the
            // same text, or the end of the change if the change covers it.
            function adjustForChange(pos, change) {
              if (cmp(pos, change.from) < 0) return pos;
              if (cmp(pos, change.to) <= 0) return changeEnd(change);
          
              var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
              if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
              return Pos(line, ch);
            }
          
            function computeSelAfterChange(doc, change) {
              var out = [];
              for (var i = 0; i < doc.sel.ranges.length; i++) {
                var range = doc.sel.ranges[i];
                out.push(new Range(adjustForChange(range.anchor, change),
                                   adjustForChange(range.head, change)));
              }
              return normalizeSelection(out, doc.sel.primIndex);
            }
          
            function offsetPos(pos, old, nw) {
              if (pos.line == old.line)
                return Pos(nw.line, pos.ch - old.ch + nw.ch);
              else
                return Pos(nw.line + (pos.line - old.line), pos.ch);
            }
          
            // Used by replaceSelections to allow moving the selection to the
            // start or around the replaced test. Hint may be "start" or "around".
            function computeReplacedSel(doc, changes, hint) {
              var out = [];
              var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
              for (var i = 0; i < changes.length; i++) {
                var change = changes[i];
                var from = offsetPos(change.from, oldPrev, newPrev);
                var to = offsetPos(changeEnd(change), oldPrev, newPrev);
                oldPrev = change.to;
                newPrev = to;
                if (hint == "around") {
                  var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
                  out[i] = new Range(inv ? to : from, inv ? from : to);
                } else {
                  out[i] = new Range(from, from);
                }
              }
              return new Selection(out, doc.sel.primIndex);
            }
          
            // Allow "beforeChange" event handlers to influence a change
            function filterChange(doc, change, update) {
              var obj = {
                canceled: false,
                from: change.from,
                to: change.to,
                text: change.text,
                origin: change.origin,
                cancel: function() { this.canceled = true; }
              };
              if (update) obj.update = function(from, to, text, origin) {
                if (from) this.from = clipPos(doc, from);
                if (to) this.to = clipPos(doc, to);
                if (text) this.text = text;
                if (origin !== undefined) this.origin = origin;
              };
              signal(doc, "beforeChange", doc, obj);
              if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
          
              if (obj.canceled) return null;
              return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
            }
          
            // Apply a change to a document, and add it to the document's
            // history, and propagating it to all linked documents.
            function makeChange(doc, change, ignoreReadOnly) {
              if (doc.cm) {
                if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
                if (doc.cm.state.suppressEdits) return;
              }
          
              if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
                change = filterChange(doc, change, true);
                if (!change) return;
              }
          
              // Possibly split or suppress the update based on the presence
              // of read-only spans in its range.
              var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
              if (split) {
                for (var i = split.length - 1; i >= 0; --i)
                  makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
              } else {
                makeChangeInner(doc, change);
              }
            }
          
            function makeChangeInner(doc, change) {
              if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
              var selAfter = computeSelAfterChange(doc, change);
              addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
          
              makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
              var rebased = [];
          
              linkedDocs(doc, function(doc, sharedHist) {
                if (!sharedHist && indexOf(rebased, doc.history) == -1) {
                  rebaseHist(doc.history, change);
                  rebased.push(doc.history);
                }
                makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
              });
            }
          
            // Revert a change stored in a document's history.
            function makeChangeFromHistory(doc, type, allowSelectionOnly) {
              if (doc.cm && doc.cm.state.suppressEdits) return;
          
              var hist = doc.history, event, selAfter = doc.sel;
              var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
          
              // Verify that there is a useable event (so that ctrl-z won't
              // needlessly clear selection events)
              for (var i = 0; i < source.length; i++) {
                event = source[i];
                if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
                  break;
              }
              if (i == source.length) return;
              hist.lastOrigin = hist.lastSelOrigin = null;
          
              for (;;) {
                event = source.pop();
                if (event.ranges) {
                  pushSelectionToHistory(event, dest);
                  if (allowSelectionOnly && !event.equals(doc.sel)) {
                    setSelection(doc, event, {clearRedo: false});
                    return;
                  }
                  selAfter = event;
                }
                else break;
              }
          
              // Build up a reverse change object to add to the opposite history
              // stack (redo when undoing, and vice versa).
              var antiChanges = [];
              pushSelectionToHistory(selAfter, dest);
              dest.push({changes: antiChanges, generation: hist.generation});
              hist.generation = event.generation || ++hist.maxGeneration;
          
              var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
          
              for (var i = event.changes.length - 1; i >= 0; --i) {
                var change = event.changes[i];
                change.origin = type;
                if (filter && !filterChange(doc, change, false)) {
                  source.length = 0;
                  return;
                }
          
                antiChanges.push(historyChangeFromChange(doc, change));
          
                var after = i ? computeSelAfterChange(doc, change) : lst(source);
                makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
                if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
                var rebased = [];
          
                // Propagate to the linked documents
                linkedDocs(doc, function(doc, sharedHist) {
                  if (!sharedHist && indexOf(rebased, doc.history) == -1) {
                    rebaseHist(doc.history, change);
                    rebased.push(doc.history);
                  }
                  makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
                });
              }
            }
          
            // Sub-views need their line numbers shifted when text is added
            // above or below them in the parent document.
            function shiftDoc(doc, distance) {
              if (distance == 0) return;
              doc.first += distance;
              doc.sel = new Selection(map(doc.sel.ranges, function(range) {
                return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
                                 Pos(range.head.line + distance, range.head.ch));
              }), doc.sel.primIndex);
              if (doc.cm) {
                regChange(doc.cm, doc.first, doc.first - distance, distance);
                for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
                  regLineChange(doc.cm, l, "gutter");
              }
            }
          
            // More lower-level change function, handling only a single document
            // (not linked ones).
            function makeChangeSingleDoc(doc, change, selAfter, spans) {
              if (doc.cm && !doc.cm.curOp)
                return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
          
              if (change.to.line < doc.first) {
                shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
                return;
              }
              if (change.from.line > doc.lastLine()) return;
          
              // Clip the change to the size of this doc
              if (change.from.line < doc.first) {
                var shift = change.text.length - 1 - (doc.first - change.from.line);
                shiftDoc(doc, shift);
                change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
                          text: [lst(change.text)], origin: change.origin};
              }
              var last = doc.lastLine();
              if (change.to.line > last) {
                change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
                          text: [change.text[0]], origin: change.origin};
              }
          
              change.removed = getBetween(doc, change.from, change.to);
          
              if (!selAfter) selAfter = computeSelAfterChange(doc, change);
              if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
              else updateDoc(doc, change, spans);
              setSelectionNoUndo(doc, selAfter, sel_dontScroll);
            }
          
            // Handle the interaction of a change to a document with the editor
            // that this document is part of.
            function makeChangeSingleDocInEditor(cm, change, spans) {
              var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
          
              var recomputeMaxLength = false, checkWidthStart = from.line;
              if (!cm.options.lineWrapping) {
                checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
                doc.iter(checkWidthStart, to.line + 1, function(line) {
                  if (line == display.maxLine) {
                    recomputeMaxLength = true;
                    return true;
                  }
                });
              }
          
              if (doc.sel.contains(change.from, change.to) > -1)
                signalCursorActivity(cm);
          
              updateDoc(doc, change, spans, estimateHeight(cm));
          
              if (!cm.options.lineWrapping) {
                doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
                  var len = lineLength(line);
                  if (len > display.maxLineLength) {
                    display.maxLine = line;
                    display.maxLineLength = len;
                    display.maxLineChanged = true;
                    recomputeMaxLength = false;
                  }
                });
                if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
              }
          
              // Adjust frontier, schedule worker
              doc.frontier = Math.min(doc.frontier, from.line);
              startWorker(cm, 400);
          
              var lendiff = change.text.length - (to.line - from.line) - 1;
              // Remember that these lines changed, for updating the display
              if (change.full)
                regChange(cm);
              else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
                regLineChange(cm, from.line, "text");
              else
                regChange(cm, from.line, to.line + 1, lendiff);
          
              var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
              if (changeHandler || changesHandler) {
                var obj = {
                  from: from, to: to,
                  text: change.text,
                  removed: change.removed,
                  origin: change.origin
                };
                if (changeHandler) signalLater(cm, "change", cm, obj);
                if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
              }
              cm.display.selForContextMenu = null;
            }
          
            function replaceRange(doc, code, from, to, origin) {
              if (!to) to = from;
              if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
              if (typeof code == "string") code = splitLines(code);
              makeChange(doc, {from: from, to: to, text: code, origin: origin});
            }
          
            // SCROLLING THINGS INTO VIEW
          
            // If an editor sits on the top or bottom of the window, partially
            // scrolled out of view, this ensures that the cursor is visible.
            function maybeScrollWindow(cm, coords) {
              if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
          
              var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
              if (coords.top + box.top < 0) doScroll = true;
              else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
              if (doScroll != null && !phantom) {
                var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
                                     (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
                                     (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
                                     coords.left + "px; width: 2px;");
                cm.display.lineSpace.appendChild(scrollNode);
                scrollNode.scrollIntoView(doScroll);
                cm.display.lineSpace.removeChild(scrollNode);
              }
            }
          
            // Scroll a given position into view (immediately), verifying that
            // it actually became visible (as line heights are accurately
            // measured, the position of something may 'drift' during drawing).
            function scrollPosIntoView(cm, pos, end, margin) {
              if (margin == null) margin = 0;
              for (var limit = 0; limit < 5; limit++) {
                var changed = false, coords = cursorCoords(cm, pos);
                var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
                var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
                                                   Math.min(coords.top, endCoords.top) - margin,
                                                   Math.max(coords.left, endCoords.left),
                                                   Math.max(coords.bottom, endCoords.bottom) + margin);
                var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
                if (scrollPos.scrollTop != null) {
                  setScrollTop(cm, scrollPos.scrollTop);
                  if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
                }
                if (scrollPos.scrollLeft != null) {
                  setScrollLeft(cm, scrollPos.scrollLeft);
                  if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
                }
                if (!changed) break;
              }
              return coords;
            }
          
            // Scroll a given set of coordinates into view (immediately).
            function scrollIntoView(cm, x1, y1, x2, y2) {
              var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
              if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
              if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
            }
          
            // Calculate a new scroll position needed to scroll the given
            // rectangle into view. Returns an object with scrollTop and
            // scrollLeft properties. When these are undefined, the
            // vertical/horizontal position does not need to be adjusted.
            function calculateScrollPos(cm, x1, y1, x2, y2) {
              var display = cm.display, snapMargin = textHeight(cm.display);
              if (y1 < 0) y1 = 0;
              var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
              var screen = displayHeight(cm), result = {};
              if (y2 - y1 > screen) y2 = y1 + screen;
              var docBottom = cm.doc.height + paddingVert(display);
              var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
              if (y1 < screentop) {
                result.scrollTop = atTop ? 0 : y1;
              } else if (y2 > screentop + screen) {
                var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
                if (newTop != screentop) result.scrollTop = newTop;
              }
          
              var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
              var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
              var tooWide = x2 - x1 > screenw;
              if (tooWide) x2 = x1 + screenw;
              if (x1 < 10)
                result.scrollLeft = 0;
              else if (x1 < screenleft)
                result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
              else if (x2 > screenw + screenleft - 3)
                result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
              return result;
            }
          
            // Store a relative adjustment to the scroll position in the current
            // operation (to be applied when the operation finishes).
            function addToScrollPos(cm, left, top) {
              if (left != null || top != null) resolveScrollToPos(cm);
              if (left != null)
                cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
              if (top != null)
                cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
            }
          
            // Make sure that at the end of the operation the current cursor is
            // shown.
            function ensureCursorVisible(cm) {
              resolveScrollToPos(cm);
              var cur = cm.getCursor(), from = cur, to = cur;
              if (!cm.options.lineWrapping) {
                from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
                to = Pos(cur.line, cur.ch + 1);
              }
              cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
            }
          
            // When an operation has its scrollToPos property set, and another
            // scroll action is applied before the end of the operation, this
            // 'simulates' scrolling that position into view in a cheap way, so
            // that the effect of intermediate scroll commands is not ignored.
            function resolveScrollToPos(cm) {
              var range = cm.curOp.scrollToPos;
              if (range) {
                cm.curOp.scrollToPos = null;
                var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
                var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
                                              Math.min(from.top, to.top) - range.margin,
                                              Math.max(from.right, to.right),
                                              Math.max(from.bottom, to.bottom) + range.margin);
                cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
              }
            }
          
            // API UTILITIES
          
            // Indent the given line. The how parameter can be "smart",
            // "add"/null, "subtract", or "prev". When aggressive is false
            // (typically set to true for forced single-line indents), empty
            // lines are not indented, and places where the mode returns Pass
            // are left alone.
            function indentLine(cm, n, how, aggressive) {
              var doc = cm.doc, state;
              if (how == null) how = "add";
              if (how == "smart") {
                // Fall back to "prev" when the mode doesn't have an indentation
                // method.
                if (!doc.mode.indent) how = "prev";
                else state = getStateBefore(cm, n);
              }
          
              var tabSize = cm.options.tabSize;
              var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
              if (line.stateAfter) line.stateAfter = null;
              var curSpaceString = line.text.match(/^\s*/)[0], indentation;
              if (!aggressive && !/\S/.test(line.text)) {
                indentation = 0;
                how = "not";
              } else if (how == "smart") {
                indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
                if (indentation == Pass || indentation > 150) {
                  if (!aggressive) return;
                  how = "prev";
                }
              }
              if (how == "prev") {
                if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
                else indentation = 0;
              } else if (how == "add") {
                indentation = curSpace + cm.options.indentUnit;
              } else if (how == "subtract") {
                indentation = curSpace - cm.options.indentUnit;
              } else if (typeof how == "number") {
                indentation = curSpace + how;
              }
              indentation = Math.max(0, indentation);
          
              var indentString = "", pos = 0;
              if (cm.options.indentWithTabs)
                for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
              if (pos < indentation) indentString += spaceStr(indentation - pos);
          
              if (indentString != curSpaceString) {
                replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
              } else {
                // Ensure that, if the cursor was in the whitespace at the start
                // of the line, it is moved to the end of that space.
                for (var i = 0; i < doc.sel.ranges.length; i++) {
                  var range = doc.sel.ranges[i];
                  if (range.head.line == n && range.head.ch < curSpaceString.length) {
                    var pos = Pos(n, curSpaceString.length);
                    replaceOneSelection(doc, i, new Range(pos, pos));
                    break;
                  }
                }
              }
              line.stateAfter = null;
            }
          
            // Utility for applying a change to a line by handle or number,
            // returning the number and optionally registering the line as
            // changed.
            function changeLine(doc, handle, changeType, op) {
              var no = handle, line = handle;
              if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
              else no = lineNo(handle);
              if (no == null) return null;
              if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
              return line;
            }
          
            // Helper for deleting text near the selection(s), used to implement
            // backspace, delete, and similar functionality.
            function deleteNearSelection(cm, compute) {
              var ranges = cm.doc.sel.ranges, kill = [];
              // Build up a set of ranges to kill first, merging overlapping
              // ranges.
              for (var i = 0; i < ranges.length; i++) {
                var toKill = compute(ranges[i]);
                while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
                  var replaced = kill.pop();
                  if (cmp(replaced.from, toKill.from) < 0) {
                    toKill.from = replaced.from;
                    break;
                  }
                }
                kill.push(toKill);
              }
              // Next, remove those actual ranges.
              runInOp(cm, function() {
                for (var i = kill.length - 1; i >= 0; i--)
                  replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
                ensureCursorVisible(cm);
              });
            }
          
            // Used for horizontal relative motion. Dir is -1 or 1 (left or
            // right), unit can be "char", "column" (like char, but doesn't
            // cross line boundaries), "word" (across next word), or "group" (to
            // the start of next group of word or non-word-non-whitespace
            // chars). The visually param controls whether, in right-to-left
            // text, direction 1 means to move towards the next index in the
            // string, or towards the character to the right of the current
            // position. The resulting position will have a hitSide=true
            // property if it reached the end of the document.
            function findPosH(doc, pos, dir, unit, visually) {
              var line = pos.line, ch = pos.ch, origDir = dir;
              var lineObj = getLine(doc, line);
              var possible = true;
              function findNextLine() {
                var l = line + dir;
                if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
                line = l;
                return lineObj = getLine(doc, l);
              }
              function moveOnce(boundToLine) {
                var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
                if (next == null) {
                  if (!boundToLine && findNextLine()) {
                    if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
                    else ch = dir < 0 ? lineObj.text.length : 0;
                  } else return (possible = false);
                } else ch = next;
                return true;
              }
          
              if (unit == "char") moveOnce();
              else if (unit == "column") moveOnce(true);
              else if (unit == "word" || unit == "group") {
                var sawType = null, group = unit == "group";
                var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
                for (var first = true;; first = false) {
                  if (dir < 0 && !moveOnce(!first)) break;
                  var cur = lineObj.text.charAt(ch) || "\n";
                  var type = isWordChar(cur, helper) ? "w"
                    : group && cur == "\n" ? "n"
                    : !group || /\s/.test(cur) ? null
                    : "p";
                  if (group && !first && !type) type = "s";
                  if (sawType && sawType != type) {
                    if (dir < 0) {dir = 1; moveOnce();}
                    break;
                  }
          
                  if (type) sawType = type;
                  if (dir > 0 && !moveOnce(!first)) break;
                }
              }
              var result = skipAtomic(doc, Pos(line, ch), origDir, true);
              if (!possible) result.hitSide = true;
              return result;
            }
          
            // For relative vertical movement. Dir may be -1 or 1. Unit can be
            // "page" or "line". The resulting position will have a hitSide=true
            // property if it reached the end of the document.
            function findPosV(cm, pos, dir, unit) {
              var doc = cm.doc, x = pos.left, y;
              if (unit == "page") {
                var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
                y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
              } else if (unit == "line") {
                y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
              }
              for (;;) {
                var target = coordsChar(cm, x, y);
                if (!target.outside) break;
                if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
                y += dir * 5;
              }
              return target;
            }
          
            // EDITOR METHODS
          
            // The publicly visible API. Note that methodOp(f) means
            // 'wrap f in an operation, performed on its `this` parameter'.
          
            // This is not the complete set of editor methods. Most of the
            // methods defined on the Doc type are also injected into
            // CodeMirror.prototype, for backwards compatibility and
            // convenience.
          
            CodeMirror.prototype = {
              constructor: CodeMirror,
              focus: function(){window.focus(); this.display.input.focus();},
          
              setOption: function(option, value) {
                var options = this.options, old = options[option];
                if (options[option] == value && option != "mode") return;
                options[option] = value;
                if (optionHandlers.hasOwnProperty(option))
                  operation(this, optionHandlers[option])(this, value, old);
              },
          
              getOption: function(option) {return this.options[option];},
              getDoc: function() {return this.doc;},
          
              addKeyMap: function(map, bottom) {
                this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
              },
              removeKeyMap: function(map) {
                var maps = this.state.keyMaps;
                for (var i = 0; i < maps.length; ++i)
                  if (maps[i] == map || maps[i].name == map) {
                    maps.splice(i, 1);
                    return true;
                  }
              },
          
              addOverlay: methodOp(function(spec, options) {
                var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
                if (mode.startState) throw new Error("Overlays may not be stateful.");
                this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
                this.state.modeGen++;
                regChange(this);
              }),
              removeOverlay: methodOp(function(spec) {
                var overlays = this.state.overlays;
                for (var i = 0; i < overlays.length; ++i) {
                  var cur = overlays[i].modeSpec;
                  if (cur == spec || typeof spec == "string" && cur.name == spec) {
                    overlays.splice(i, 1);
                    this.state.modeGen++;
                    regChange(this);
                    return;
                  }
                }
              }),
          
              indentLine: methodOp(function(n, dir, aggressive) {
                if (typeof dir != "string" && typeof dir != "number") {
                  if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
                  else dir = dir ? "add" : "subtract";
                }
                if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
              }),
              indentSelection: methodOp(function(how) {
                var ranges = this.doc.sel.ranges, end = -1;
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (!range.empty()) {
                    var from = range.from(), to = range.to();
                    var start = Math.max(end, from.line);
                    end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
                    for (var j = start; j < end; ++j)
                      indentLine(this, j, how);
                    var newRanges = this.doc.sel.ranges;
                    if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
                      replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
                  } else if (range.head.line > end) {
                    indentLine(this, range.head.line, how, true);
                    end = range.head.line;
                    if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
                  }
                }
              }),
          
              // Fetch the parser token for a given character. Useful for hacks
              // that want to inspect the mode state (say, for completion).
              getTokenAt: function(pos, precise) {
                return takeToken(this, pos, precise);
              },
          
              getLineTokens: function(line, precise) {
                return takeToken(this, Pos(line), precise, true);
              },
          
              getTokenTypeAt: function(pos) {
                pos = clipPos(this.doc, pos);
                var styles = getLineStyles(this, getLine(this.doc, pos.line));
                var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
                var type;
                if (ch == 0) type = styles[2];
                else for (;;) {
                  var mid = (before + after) >> 1;
                  if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
                  else if (styles[mid * 2 + 1] < ch) before = mid + 1;
                  else { type = styles[mid * 2 + 2]; break; }
                }
                var cut = type ? type.indexOf("cm-overlay ") : -1;
                return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
              },
          
              getModeAt: function(pos) {
                var mode = this.doc.mode;
                if (!mode.innerMode) return mode;
                return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
              },
          
              getHelper: function(pos, type) {
                return this.getHelpers(pos, type)[0];
              },
          
              getHelpers: function(pos, type) {
                var found = [];
                if (!helpers.hasOwnProperty(type)) return helpers;
                var help = helpers[type], mode = this.getModeAt(pos);
                if (typeof mode[type] == "string") {
                  if (help[mode[type]]) found.push(help[mode[type]]);
                } else if (mode[type]) {
                  for (var i = 0; i < mode[type].length; i++) {
                    var val = help[mode[type][i]];
                    if (val) found.push(val);
                  }
                } else if (mode.helperType && help[mode.helperType]) {
                  found.push(help[mode.helperType]);
                } else if (help[mode.name]) {
                  found.push(help[mode.name]);
                }
                for (var i = 0; i < help._global.length; i++) {
                  var cur = help._global[i];
                  if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
                    found.push(cur.val);
                }
                return found;
              },
          
              getStateAfter: function(line, precise) {
                var doc = this.doc;
                line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
                return getStateBefore(this, line + 1, precise);
              },
          
              cursorCoords: function(start, mode) {
                var pos, range = this.doc.sel.primary();
                if (start == null) pos = range.head;
                else if (typeof start == "object") pos = clipPos(this.doc, start);
                else pos = start ? range.from() : range.to();
                return cursorCoords(this, pos, mode || "page");
              },
          
              charCoords: function(pos, mode) {
                return charCoords(this, clipPos(this.doc, pos), mode || "page");
              },
          
              coordsChar: function(coords, mode) {
                coords = fromCoordSystem(this, coords, mode || "page");
                return coordsChar(this, coords.left, coords.top);
              },
          
              lineAtHeight: function(height, mode) {
                height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
                return lineAtHeight(this.doc, height + this.display.viewOffset);
              },
              heightAtLine: function(line, mode) {
                var end = false, last = this.doc.first + this.doc.size - 1;
                if (line < this.doc.first) line = this.doc.first;
                else if (line > last) { line = last; end = true; }
                var lineObj = getLine(this.doc, line);
                return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
                  (end ? this.doc.height - heightAtLine(lineObj) : 0);
              },
          
              defaultTextHeight: function() { return textHeight(this.display); },
              defaultCharWidth: function() { return charWidth(this.display); },
          
              setGutterMarker: methodOp(function(line, gutterID, value) {
                return changeLine(this.doc, line, "gutter", function(line) {
                  var markers = line.gutterMarkers || (line.gutterMarkers = {});
                  markers[gutterID] = value;
                  if (!value && isEmpty(markers)) line.gutterMarkers = null;
                  return true;
                });
              }),
          
              clearGutter: methodOp(function(gutterID) {
                var cm = this, doc = cm.doc, i = doc.first;
                doc.iter(function(line) {
                  if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
                    line.gutterMarkers[gutterID] = null;
                    regLineChange(cm, i, "gutter");
                    if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
                  }
                  ++i;
                });
              }),
          
              addLineWidget: methodOp(function(handle, node, options) {
                return addLineWidget(this, handle, node, options);
              }),
          
              removeLineWidget: function(widget) { widget.clear(); },
          
              lineInfo: function(line) {
                if (typeof line == "number") {
                  if (!isLine(this.doc, line)) return null;
                  var n = line;
                  line = getLine(this.doc, line);
                  if (!line) return null;
                } else {
                  var n = lineNo(line);
                  if (n == null) return null;
                }
                return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
                        textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
                        widgets: line.widgets};
              },
          
              getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
          
              addWidget: function(pos, node, scroll, vert, horiz) {
                var display = this.display;
                pos = cursorCoords(this, clipPos(this.doc, pos));
                var top = pos.bottom, left = pos.left;
                node.style.position = "absolute";
                node.setAttribute("cm-ignore-events", "true");
                this.display.input.setUneditable(node);
                display.sizer.appendChild(node);
                if (vert == "over") {
                  top = pos.top;
                } else if (vert == "above" || vert == "near") {
                  var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
                  hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
                  // Default to positioning above (if specified and possible); otherwise default to positioning below
                  if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
                    top = pos.top - node.offsetHeight;
                  else if (pos.bottom + node.offsetHeight <= vspace)
                    top = pos.bottom;
                  if (left + node.offsetWidth > hspace)
                    left = hspace - node.offsetWidth;
                }
                node.style.top = top + "px";
                node.style.left = node.style.right = "";
                if (horiz == "right") {
                  left = display.sizer.clientWidth - node.offsetWidth;
                  node.style.right = "0px";
                } else {
                  if (horiz == "left") left = 0;
                  else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
                  node.style.left = left + "px";
                }
                if (scroll)
                  scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
              },
          
              triggerOnKeyDown: methodOp(onKeyDown),
              triggerOnKeyPress: methodOp(onKeyPress),
              triggerOnKeyUp: onKeyUp,
          
              execCommand: function(cmd) {
                if (commands.hasOwnProperty(cmd))
                  return commands[cmd](this);
              },
          
              findPosH: function(from, amount, unit, visually) {
                var dir = 1;
                if (amount < 0) { dir = -1; amount = -amount; }
                for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
                  cur = findPosH(this.doc, cur, dir, unit, visually);
                  if (cur.hitSide) break;
                }
                return cur;
              },
          
              moveH: methodOp(function(dir, unit) {
                var cm = this;
                cm.extendSelectionsBy(function(range) {
                  if (cm.display.shift || cm.doc.extend || range.empty())
                    return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
                  else
                    return dir < 0 ? range.from() : range.to();
                }, sel_move);
              }),
          
              deleteH: methodOp(function(dir, unit) {
                var sel = this.doc.sel, doc = this.doc;
                if (sel.somethingSelected())
                  doc.replaceSelection("", null, "+delete");
                else
                  deleteNearSelection(this, function(range) {
                    var other = findPosH(doc, range.head, dir, unit, false);
                    return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
                  });
              }),
          
              findPosV: function(from, amount, unit, goalColumn) {
                var dir = 1, x = goalColumn;
                if (amount < 0) { dir = -1; amount = -amount; }
                for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
                  var coords = cursorCoords(this, cur, "div");
                  if (x == null) x = coords.left;
                  else coords.left = x;
                  cur = findPosV(this, coords, dir, unit);
                  if (cur.hitSide) break;
                }
                return cur;
              },
          
              moveV: methodOp(function(dir, unit) {
                var cm = this, doc = this.doc, goals = [];
                var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
                doc.extendSelectionsBy(function(range) {
                  if (collapse)
                    return dir < 0 ? range.from() : range.to();
                  var headPos = cursorCoords(cm, range.head, "div");
                  if (range.goalColumn != null) headPos.left = range.goalColumn;
                  goals.push(headPos.left);
                  var pos = findPosV(cm, headPos, dir, unit);
                  if (unit == "page" && range == doc.sel.primary())
                    addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
                  return pos;
                }, sel_move);
                if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
                  doc.sel.ranges[i].goalColumn = goals[i];
              }),
          
              // Find the word at the given position (as returned by coordsChar).
              findWordAt: function(pos) {
                var doc = this.doc, line = getLine(doc, pos.line).text;
                var start = pos.ch, end = pos.ch;
                if (line) {
                  var helper = this.getHelper(pos, "wordChars");
                  if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
                  var startChar = line.charAt(start);
                  var check = isWordChar(startChar, helper)
                    ? function(ch) { return isWordChar(ch, helper); }
                    : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
                    : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
                  while (start > 0 && check(line.charAt(start - 1))) --start;
                  while (end < line.length && check(line.charAt(end))) ++end;
                }
                return new Range(Pos(pos.line, start), Pos(pos.line, end));
              },
          
              toggleOverwrite: function(value) {
                if (value != null && value == this.state.overwrite) return;
                if (this.state.overwrite = !this.state.overwrite)
                  addClass(this.display.cursorDiv, "CodeMirror-overwrite");
                else
                  rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
          
                signal(this, "overwriteToggle", this, this.state.overwrite);
              },
              hasFocus: function() { return this.display.input.getField() == activeElt(); },
          
              scrollTo: methodOp(function(x, y) {
                if (x != null || y != null) resolveScrollToPos(this);
                if (x != null) this.curOp.scrollLeft = x;
                if (y != null) this.curOp.scrollTop = y;
              }),
              getScrollInfo: function() {
                var scroller = this.display.scroller;
                return {left: scroller.scrollLeft, top: scroller.scrollTop,
                        height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
                        width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
                        clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
              },
          
              scrollIntoView: methodOp(function(range, margin) {
                if (range == null) {
                  range = {from: this.doc.sel.primary().head, to: null};
                  if (margin == null) margin = this.options.cursorScrollMargin;
                } else if (typeof range == "number") {
                  range = {from: Pos(range, 0), to: null};
                } else if (range.from == null) {
                  range = {from: range, to: null};
                }
                if (!range.to) range.to = range.from;
                range.margin = margin || 0;
          
                if (range.from.line != null) {
                  resolveScrollToPos(this);
                  this.curOp.scrollToPos = range;
                } else {
                  var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
                                                Math.min(range.from.top, range.to.top) - range.margin,
                                                Math.max(range.from.right, range.to.right),
                                                Math.max(range.from.bottom, range.to.bottom) + range.margin);
                  this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
                }
              }),
          
              setSize: methodOp(function(width, height) {
                var cm = this;
                function interpret(val) {
                  return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
                }
                if (width != null) cm.display.wrapper.style.width = interpret(width);
                if (height != null) cm.display.wrapper.style.height = interpret(height);
                if (cm.options.lineWrapping) clearLineMeasurementCache(this);
                var lineNo = cm.display.viewFrom;
                cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
                  if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
                    if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
                  ++lineNo;
                });
                cm.curOp.forceUpdate = true;
                signal(cm, "refresh", this);
              }),
          
              operation: function(f){return runInOp(this, f);},
          
              refresh: methodOp(function() {
                var oldHeight = this.display.cachedTextHeight;
                regChange(this);
                this.curOp.forceUpdate = true;
                clearCaches(this);
                this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
                updateGutterSpace(this);
                if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
                  estimateLineHeights(this);
                signal(this, "refresh", this);
              }),
          
              swapDoc: methodOp(function(doc) {
                var old = this.doc;
                old.cm = null;
                attachDoc(this, doc);
                clearCaches(this);
                this.display.input.reset();
                this.scrollTo(doc.scrollLeft, doc.scrollTop);
                this.curOp.forceScroll = true;
                signalLater(this, "swapDoc", this, old);
                return old;
              }),
          
              getInputField: function(){return this.display.input.getField();},
              getWrapperElement: function(){return this.display.wrapper;},
              getScrollerElement: function(){return this.display.scroller;},
              getGutterElement: function(){return this.display.gutters;}
            };
            eventMixin(CodeMirror);
          
            // OPTION DEFAULTS
          
            // The default configuration options.
            var defaults = CodeMirror.defaults = {};
            // Functions to run when options are changed.
            var optionHandlers = CodeMirror.optionHandlers = {};
          
            function option(name, deflt, handle, notOnInit) {
              CodeMirror.defaults[name] = deflt;
              if (handle) optionHandlers[name] =
                notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
            }
          
            // Passed to option handlers when there is no old value.
            var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
          
            // These two are, on init, called from the constructor because they
            // have to be initialized before the editor can start at all.
            option("value", "", function(cm, val) {
              cm.setValue(val);
            }, true);
            option("mode", null, function(cm, val) {
              cm.doc.modeOption = val;
              loadMode(cm);
            }, true);
          
            option("indentUnit", 2, loadMode, true);
            option("indentWithTabs", false);
            option("smartIndent", true);
            option("tabSize", 4, function(cm) {
              resetModeState(cm);
              clearCaches(cm);
              regChange(cm);
            }, true);
            option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) {
              cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
              cm.refresh();
            }, true);
            option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
            option("electricChars", true);
            option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
              throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
            }, true);
            option("rtlMoveVisually", !windows);
            option("wholeLineUpdateBefore", true);
          
            option("theme", "default", function(cm) {
              themeChanged(cm);
              guttersChanged(cm);
            }, true);
            option("keyMap", "default", function(cm, val, old) {
              var next = getKeyMap(val);
              var prev = old != CodeMirror.Init && getKeyMap(old);
              if (prev && prev.detach) prev.detach(cm, next);
              if (next.attach) next.attach(cm, prev || null);
            });
            option("extraKeys", null);
          
            option("lineWrapping", false, wrappingChanged, true);
            option("gutters", [], function(cm) {
              setGuttersForLineNumbers(cm.options);
              guttersChanged(cm);
            }, true);
            option("fixedGutter", true, function(cm, val) {
              cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
              cm.refresh();
            }, true);
            option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
            option("scrollbarStyle", "native", function(cm) {
              initScrollbars(cm);
              updateScrollbars(cm);
              cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
              cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
            }, true);
            option("lineNumbers", false, function(cm) {
              setGuttersForLineNumbers(cm.options);
              guttersChanged(cm);
            }, true);
            option("firstLineNumber", 1, guttersChanged, true);
            option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
            option("showCursorWhenSelecting", false, updateSelection, true);
          
            option("resetSelectionOnContextMenu", true);
          
            option("readOnly", false, function(cm, val) {
              if (val == "nocursor") {
                onBlur(cm);
                cm.display.input.blur();
                cm.display.disabled = true;
              } else {
                cm.display.disabled = false;
                if (!val) cm.display.input.reset();
              }
            });
            option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
            option("dragDrop", true);
          
            option("cursorBlinkRate", 530);
            option("cursorScrollMargin", 0);
            option("cursorHeight", 1, updateSelection, true);
            option("singleCursorHeightPerLine", true, updateSelection, true);
            option("workTime", 100);
            option("workDelay", 100);
            option("flattenSpans", true, resetModeState, true);
            option("addModeClass", false, resetModeState, true);
            option("pollInterval", 100);
            option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
            option("historyEventDelay", 1250);
            option("viewportMargin", 10, function(cm){cm.refresh();}, true);
            option("maxHighlightLength", 10000, resetModeState, true);
            option("moveInputWithCursor", true, function(cm, val) {
              if (!val) cm.display.input.resetPosition();
            });
          
            option("tabindex", null, function(cm, val) {
              cm.display.input.getField().tabIndex = val || "";
            });
            option("autofocus", null);
          
            // MODE DEFINITION AND QUERYING
          
            // Known modes, by name and by MIME
            var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
          
            // Extra arguments are stored as the mode's dependencies, which is
            // used by (legacy) mechanisms like loadmode.js to automatically
            // load a mode. (Preferred mechanism is the require/define calls.)
            CodeMirror.defineMode = function(name, mode) {
              if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
          
            CodeMirror.defineMIME = function(mime, spec) {
              mimeModes[mime] = spec;
            };
          
            // Given a MIME type, a {name, ...options} config object, or a name
            // string, return a mode config object.
            CodeMirror.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                var found = mimeModes[spec.name];
                if (typeof found == "string") found = {name: found};
                spec = createObj(found, spec);
                spec.name = found.name;
              } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
                return CodeMirror.resolveMode("application/xml");
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
          
            // Given a mode spec (anything that resolveMode accepts), find and
            // initialize an actual mode object.
            CodeMirror.getMode = function(options, spec) {
              var spec = CodeMirror.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) return CodeMirror.getMode(options, "text/plain");
              var modeObj = mfactory(options, spec);
              if (modeExtensions.hasOwnProperty(spec.name)) {
                var exts = modeExtensions[spec.name];
                for (var prop in exts) {
                  if (!exts.hasOwnProperty(prop)) continue;
                  if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
                  modeObj[prop] = exts[prop];
                }
              }
              modeObj.name = spec.name;
              if (spec.helperType) modeObj.helperType = spec.helperType;
              if (spec.modeProps) for (var prop in spec.modeProps)
                modeObj[prop] = spec.modeProps[prop];
          
              return modeObj;
            };
          
            // Minimal default mode.
            CodeMirror.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            CodeMirror.defineMIME("text/plain", "null");
          
            // This can be used to attach properties to mode objects from
            // outside the actual mode definition.
            var modeExtensions = CodeMirror.modeExtensions = {};
            CodeMirror.extendMode = function(mode, properties) {
              var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
              copyObj(properties, exts);
            };
          
            // EXTENSIONS
          
            CodeMirror.defineExtension = function(name, func) {
              CodeMirror.prototype[name] = func;
            };
            CodeMirror.defineDocExtension = function(name, func) {
              Doc.prototype[name] = func;
            };
            CodeMirror.defineOption = option;
          
            var initHooks = [];
            CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
          
            var helpers = CodeMirror.helpers = {};
            CodeMirror.registerHelper = function(type, name, value) {
              if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
              helpers[type][name] = value;
            };
            CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
              CodeMirror.registerHelper(type, name, value);
              helpers[type]._global.push({pred: predicate, val: value});
            };
          
            // MODE STATE HANDLING
          
            // Utility functions for working with state. Exported because nested
            // modes need to do this for their inner modes.
          
            var copyState = CodeMirror.copyState = function(mode, state) {
              if (state === true) return state;
              if (mode.copyState) return mode.copyState(state);
              var nstate = {};
              for (var n in state) {
                var val = state[n];
                if (val instanceof Array) val = val.concat([]);
                nstate[n] = val;
              }
              return nstate;
            };
          
            var startState = CodeMirror.startState = function(mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
          
            // Given a mode and a state (for that mode), find the inner mode and
            // state at the position that the state refers to.
            CodeMirror.innerMode = function(mode, state) {
              while (mode.innerMode) {
                var info = mode.innerMode(state);
                if (!info || info.mode == mode) break;
                state = info.state;
                mode = info.mode;
              }
              return info || {mode: mode, state: state};
            };
          
            // STANDARD COMMANDS
          
            // Commands are parameter-less actions that can be performed on an
            // editor, mostly used for keybindings.
            var commands = CodeMirror.commands = {
              selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
              singleSelection: function(cm) {
                cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
              },
              killLine: function(cm) {
                deleteNearSelection(cm, function(range) {
                  if (range.empty()) {
                    var len = getLine(cm.doc, range.head.line).text.length;
                    if (range.head.ch == len && range.head.line < cm.lastLine())
                      return {from: range.head, to: Pos(range.head.line + 1, 0)};
                    else
                      return {from: range.head, to: Pos(range.head.line, len)};
                  } else {
                    return {from: range.from(), to: range.to()};
                  }
                });
              },
              deleteLine: function(cm) {
                deleteNearSelection(cm, function(range) {
                  return {from: Pos(range.from().line, 0),
                          to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
                });
              },
              delLineLeft: function(cm) {
                deleteNearSelection(cm, function(range) {
                  return {from: Pos(range.from().line, 0), to: range.from()};
                });
              },
              delWrappedLineLeft: function(cm) {
                deleteNearSelection(cm, function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var leftPos = cm.coordsChar({left: 0, top: top}, "div");
                  return {from: leftPos, to: range.from()};
                });
              },
              delWrappedLineRight: function(cm) {
                deleteNearSelection(cm, function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
                  return {from: range.from(), to: rightPos };
                });
              },
              undo: function(cm) {cm.undo();},
              redo: function(cm) {cm.redo();},
              undoSelection: function(cm) {cm.undoSelection();},
              redoSelection: function(cm) {cm.redoSelection();},
              goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
              goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
              goLineStart: function(cm) {
                cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
                                      {origin: "+move", bias: 1});
              },
              goLineStartSmart: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  return lineStartSmart(cm, range.head);
                }, {origin: "+move", bias: 1});
              },
              goLineEnd: function(cm) {
                cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
                                      {origin: "+move", bias: -1});
              },
              goLineRight: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
                }, sel_move);
              },
              goLineLeft: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  return cm.coordsChar({left: 0, top: top}, "div");
                }, sel_move);
              },
              goLineLeftSmart: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var pos = cm.coordsChar({left: 0, top: top}, "div");
                  if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
                  return pos;
                }, sel_move);
              },
              goLineUp: function(cm) {cm.moveV(-1, "line");},
              goLineDown: function(cm) {cm.moveV(1, "line");},
              goPageUp: function(cm) {cm.moveV(-1, "page");},
              goPageDown: function(cm) {cm.moveV(1, "page");},
              goCharLeft: function(cm) {cm.moveH(-1, "char");},
              goCharRight: function(cm) {cm.moveH(1, "char");},
              goColumnLeft: function(cm) {cm.moveH(-1, "column");},
              goColumnRight: function(cm) {cm.moveH(1, "column");},
              goWordLeft: function(cm) {cm.moveH(-1, "word");},
              goGroupRight: function(cm) {cm.moveH(1, "group");},
              goGroupLeft: function(cm) {cm.moveH(-1, "group");},
              goWordRight: function(cm) {cm.moveH(1, "word");},
              delCharBefore: function(cm) {cm.deleteH(-1, "char");},
              delCharAfter: function(cm) {cm.deleteH(1, "char");},
              delWordBefore: function(cm) {cm.deleteH(-1, "word");},
              delWordAfter: function(cm) {cm.deleteH(1, "word");},
              delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
              delGroupAfter: function(cm) {cm.deleteH(1, "group");},
              indentAuto: function(cm) {cm.indentSelection("smart");},
              indentMore: function(cm) {cm.indentSelection("add");},
              indentLess: function(cm) {cm.indentSelection("subtract");},
              insertTab: function(cm) {cm.replaceSelection("\t");},
              insertSoftTab: function(cm) {
                var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].from();
                  var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
                  spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
                }
                cm.replaceSelections(spaces);
              },
              defaultTab: function(cm) {
                if (cm.somethingSelected()) cm.indentSelection("add");
                else cm.execCommand("insertTab");
              },
              transposeChars: function(cm) {
                runInOp(cm, function() {
                  var ranges = cm.listSelections(), newSel = [];
                  for (var i = 0; i < ranges.length; i++) {
                    var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
                    if (line) {
                      if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
                      if (cur.ch > 0) {
                        cur = new Pos(cur.line, cur.ch + 1);
                        cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
                                        Pos(cur.line, cur.ch - 2), cur, "+transpose");
                      } else if (cur.line > cm.doc.first) {
                        var prev = getLine(cm.doc, cur.line - 1).text;
                        if (prev)
                          cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
                                          Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
                      }
                    }
                    newSel.push(new Range(cur, cur));
                  }
                  cm.setSelections(newSel);
                });
              },
              newlineAndIndent: function(cm) {
                runInOp(cm, function() {
                  var len = cm.listSelections().length;
                  for (var i = 0; i < len; i++) {
                    var range = cm.listSelections()[i];
                    cm.replaceRange("\n", range.anchor, range.head, "+input");
                    cm.indentLine(range.from().line + 1, null, true);
                    ensureCursorVisible(cm);
                  }
                });
              },
              toggleOverwrite: function(cm) {cm.toggleOverwrite();}
            };
          
          
            // STANDARD KEYMAPS
          
            var keyMap = CodeMirror.keyMap = {};
          
            keyMap.basic = {
              "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
              "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
              "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
              "Tab": "defaultTab", "Shift-Tab": "indentAuto",
              "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
              "Esc": "singleSelection"
            };
            // Note that the save and find-related commands aren't defined by
            // default. User code or addons can define them. Unknown commands
            // are simply ignored.
            keyMap.pcDefault = {
              "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
              "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
              "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
              "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
              "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
              "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
              "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
              fallthrough: "basic"
            };
            // Very basic readline/emacs-style bindings, which are standard on Mac.
            keyMap.emacsy = {
              "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
              "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
              "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
              "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
            };
            keyMap.macDefault = {
              "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
              "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
              "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
              "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
              "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
              "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
              "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
              fallthrough: ["basic", "emacsy"]
            };
            keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
          
            // KEYMAP DISPATCH
          
            function normalizeKeyName(name) {
              var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
              var alt, ctrl, shift, cmd;
              for (var i = 0; i < parts.length - 1; i++) {
                var mod = parts[i];
                if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
                else if (/^a(lt)?$/i.test(mod)) alt = true;
                else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
                else if (/^s(hift)$/i.test(mod)) shift = true;
                else throw new Error("Unrecognized modifier name: " + mod);
              }
              if (alt) name = "Alt-" + name;
              if (ctrl) name = "Ctrl-" + name;
              if (cmd) name = "Cmd-" + name;
              if (shift) name = "Shift-" + name;
              return name;
            }
          
            // This is a kludge to keep keymaps mostly working as raw objects
            // (backwards compatibility) while at the same time support features
            // like normalization and multi-stroke key bindings. It compiles a
            // new normalized keymap, and then updates the old object to reflect
            // this.
            CodeMirror.normalizeKeyMap = function(keymap) {
              var copy = {};
              for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
                var value = keymap[keyname];
                if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
                if (value == "...") { delete keymap[keyname]; continue; }
          
                var keys = map(keyname.split(" "), normalizeKeyName);
                for (var i = 0; i < keys.length; i++) {
                  var val, name;
                  if (i == keys.length - 1) {
                    name = keyname;
                    val = value;
                  } else {
                    name = keys.slice(0, i + 1).join(" ");
                    val = "...";
                  }
                  var prev = copy[name];
                  if (!prev) copy[name] = val;
                  else if (prev != val) throw new Error("Inconsistent bindings for " + name);
                }
                delete keymap[keyname];
              }
              for (var prop in copy) keymap[prop] = copy[prop];
              return keymap;
            };
          
            var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
              map = getKeyMap(map);
              var found = map.call ? map.call(key, context) : map[key];
              if (found === false) return "nothing";
              if (found === "...") return "multi";
              if (found != null && handle(found)) return "handled";
          
              if (map.fallthrough) {
                if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
                  return lookupKey(key, map.fallthrough, handle, context);
                for (var i = 0; i < map.fallthrough.length; i++) {
                  var result = lookupKey(key, map.fallthrough[i], handle, context);
                  if (result) return result;
                }
              }
            };
          
            // Modifier key presses don't count as 'real' key presses for the
            // purpose of keymap fallthrough.
            var isModifierKey = CodeMirror.isModifierKey = function(value) {
              var name = typeof value == "string" ? value : keyNames[value.keyCode];
              return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
            };
          
            // Look up the name of a key as indicated by an event object.
            var keyName = CodeMirror.keyName = function(event, noShift) {
              if (presto && event.keyCode == 34 && event["char"]) return false;
              var base = keyNames[event.keyCode], name = base;
              if (name == null || event.altGraphKey) return false;
              if (event.altKey && base != "Alt") name = "Alt-" + name;
              if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
              if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
              if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
              return name;
            };
          
            function getKeyMap(val) {
              return typeof val == "string" ? keyMap[val] : val;
            }
          
            // FROMTEXTAREA
          
            CodeMirror.fromTextArea = function(textarea, options) {
              options = options ? copyObj(options) : {};
              options.value = textarea.value;
              if (!options.tabindex && textarea.tabIndex)
                options.tabindex = textarea.tabIndex;
              if (!options.placeholder && textarea.placeholder)
                options.placeholder = textarea.placeholder;
              // Set autofocus to true if this textarea is focused, or if it has
              // autofocus and no other element is focused.
              if (options.autofocus == null) {
                var hasFocus = activeElt();
                options.autofocus = hasFocus == textarea ||
                  textarea.getAttribute("autofocus") != null && hasFocus == document.body;
              }
          
              function save() {textarea.value = cm.getValue();}
              if (textarea.form) {
                on(textarea.form, "submit", save);
                // Deplorable hack to make the submit method do the right thing.
                if (!options.leaveSubmitMethodAlone) {
                  var form = textarea.form, realSubmit = form.submit;
                  try {
                    var wrappedSubmit = form.submit = function() {
                      save();
                      form.submit = realSubmit;
                      form.submit();
                      form.submit = wrappedSubmit;
                    };
                  } catch(e) {}
                }
              }
          
              options.finishInit = function(cm) {
                cm.save = save;
                cm.getTextArea = function() { return textarea; };
                cm.toTextArea = function() {
                  cm.toTextArea = isNaN; // Prevent this from being ran twice
                  save();
                  textarea.parentNode.removeChild(cm.getWrapperElement());
                  textarea.style.display = "";
                  if (textarea.form) {
                    off(textarea.form, "submit", save);
                    if (typeof textarea.form.submit == "function")
                      textarea.form.submit = realSubmit;
                  }
                };
              };
          
              textarea.style.display = "none";
              var cm = CodeMirror(function(node) {
                textarea.parentNode.insertBefore(node, textarea.nextSibling);
              }, options);
              return cm;
            };
          
            // STRING STREAM
          
            // Fed to the mode parsers, provides helper functions to make
            // parsers more succinct.
          
            var StringStream = CodeMirror.StringStream = function(string, tabSize) {
              this.pos = this.start = 0;
              this.string = string;
              this.tabSize = tabSize || 8;
              this.lastColumnPos = this.lastColumnValue = 0;
              this.lineStart = 0;
            };
          
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == this.lineStart;},
              peek: function() {return this.string.charAt(this.pos) || undefined;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {
                if (this.lastColumnPos < this.start) {
                  this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
                  this.lastColumnPos = this.start;
                }
                return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
              },
              indentation: function() {
                return countColumn(this.string, null, this.tabSize) -
                  (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
              },
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
          
            // TEXTMARKERS
          
            // Created with markText and setBookmark methods. A TextMarker is a
            // handle that can be used to clear or find a marked position in the
            // document. Line objects hold arrays (markedSpans) containing
            // {from, to, marker} object pointing to such marker objects, and
            // indicating that such a marker is present on that line. Multiple
            // lines may point to the same marker when it spans across lines.
            // The spans will have null for their from/to properties when the
            // marker continues beyond the start/end of the line. Markers have
            // links back to the lines they currently touch.
          
            var nextMarkerId = 0;
          
            var TextMarker = CodeMirror.TextMarker = function(doc, type) {
              this.lines = [];
              this.type = type;
              this.doc = doc;
              this.id = ++nextMarkerId;
            };
            eventMixin(TextMarker);
          
            // Clear the marker.
            TextMarker.prototype.clear = function() {
              if (this.explicitlyCleared) return;
              var cm = this.doc.cm, withOp = cm && !cm.curOp;
              if (withOp) startOperation(cm);
              if (hasHandler(this, "clear")) {
                var found = this.find();
                if (found) signalLater(this, "clear", found.from, found.to);
              }
              var min = null, max = null;
              for (var i = 0; i < this.lines.length; ++i) {
                var line = this.lines[i];
                var span = getMarkedSpanFor(line.markedSpans, this);
                if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
                else if (cm) {
                  if (span.to != null) max = lineNo(line);
                  if (span.from != null) min = lineNo(line);
                }
                line.markedSpans = removeMarkedSpan(line.markedSpans, span);
                if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
                  updateLineHeight(line, textHeight(cm.display));
              }
              if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
                var visual = visualLine(this.lines[i]), len = lineLength(visual);
                if (len > cm.display.maxLineLength) {
                  cm.display.maxLine = visual;
                  cm.display.maxLineLength = len;
                  cm.display.maxLineChanged = true;
                }
              }
          
              if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
              this.lines.length = 0;
              this.explicitlyCleared = true;
              if (this.atomic && this.doc.cantEdit) {
                this.doc.cantEdit = false;
                if (cm) reCheckSelection(cm.doc);
              }
              if (cm) signalLater(cm, "markerCleared", cm, this);
              if (withOp) endOperation(cm);
              if (this.parent) this.parent.clear();
            };
          
            // Find the position of the marker in the document. Returns a {from,
            // to} object by default. Side can be passed to get a specific side
            // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
            // Pos objects returned contain a line object, rather than a line
            // number (used to prevent looking up the same line twice).
            TextMarker.prototype.find = function(side, lineObj) {
              if (side == null && this.type == "bookmark") side = 1;
              var from, to;
              for (var i = 0; i < this.lines.length; ++i) {
                var line = this.lines[i];
                var span = getMarkedSpanFor(line.markedSpans, this);
                if (span.from != null) {
                  from = Pos(lineObj ? line : lineNo(line), span.from);
                  if (side == -1) return from;
                }
                if (span.to != null) {
                  to = Pos(lineObj ? line : lineNo(line), span.to);
                  if (side == 1) return to;
                }
              }
              return from && {from: from, to: to};
            };
          
            // Signals that the marker's widget changed, and surrounding layout
            // should be recomputed.
            TextMarker.prototype.changed = function() {
              var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
              if (!pos || !cm) return;
              runInOp(cm, function() {
                var line = pos.line, lineN = lineNo(pos.line);
                var view = findViewForLine(cm, lineN);
                if (view) {
                  clearLineMeasurementCacheFor(view);
                  cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
                }
                cm.curOp.updateMaxLine = true;
                if (!lineIsHidden(widget.doc, line) && widget.height != null) {
                  var oldHeight = widget.height;
                  widget.height = null;
                  var dHeight = widgetHeight(widget) - oldHeight;
                  if (dHeight)
                    updateLineHeight(line, line.height + dHeight);
                }
              });
            };
          
            TextMarker.prototype.attachLine = function(line) {
              if (!this.lines.length && this.doc.cm) {
                var op = this.doc.cm.curOp;
                if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
                  (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
              }
              this.lines.push(line);
            };
            TextMarker.prototype.detachLine = function(line) {
              this.lines.splice(indexOf(this.lines, line), 1);
              if (!this.lines.length && this.doc.cm) {
                var op = this.doc.cm.curOp;
                (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
              }
            };
          
            // Collapsed markers have unique ids, in order to be able to order
            // them, which is needed for uniquely determining an outer marker
            // when they overlap (they may nest, but not partially overlap).
            var nextMarkerId = 0;
          
            // Create a marker, wire it up to the right lines, and
            function markText(doc, from, to, options, type) {
              // Shared markers (across linked documents) are handled separately
              // (markTextShared will call out to this again, once per
              // document).
              if (options && options.shared) return markTextShared(doc, from, to, options, type);
              // Ensure we are in an operation.
              if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
          
              var marker = new TextMarker(doc, type), diff = cmp(from, to);
              if (options) copyObj(options, marker, false);
              // Don't connect empty markers unless clearWhenEmpty is false
              if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
                return marker;
              if (marker.replacedWith) {
                // Showing up as a widget implies collapsed (widget replaces text)
                marker.collapsed = true;
                marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
                if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
                if (options.insertLeft) marker.widgetNode.insertLeft = true;
              }
              if (marker.collapsed) {
                if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
                    from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
                  throw new Error("Inserting collapsed marker partially overlapping an existing one");
                sawCollapsedSpans = true;
              }
          
              if (marker.addToHistory)
                addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
          
              var curLine = from.line, cm = doc.cm, updateMaxLine;
              doc.iter(curLine, to.line + 1, function(line) {
                if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
                  updateMaxLine = true;
                if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
                addMarkedSpan(line, new MarkedSpan(marker,
                                                   curLine == from.line ? from.ch : null,
                                                   curLine == to.line ? to.ch : null));
                ++curLine;
              });
              // lineIsHidden depends on the presence of the spans, so needs a second pass
              if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
                if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
              });
          
              if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
          
              if (marker.readOnly) {
                sawReadOnlySpans = true;
                if (doc.history.done.length || doc.history.undone.length)
                  doc.clearHistory();
              }
              if (marker.collapsed) {
                marker.id = ++nextMarkerId;
                marker.atomic = true;
              }
              if (cm) {
                // Sync editor state
                if (updateMaxLine) cm.curOp.updateMaxLine = true;
                if (marker.collapsed)
                  regChange(cm, from.line, to.line + 1);
                else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
                  for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
                if (marker.atomic) reCheckSelection(cm.doc);
                signalLater(cm, "markerAdded", cm, marker);
              }
              return marker;
            }
          
            // SHARED TEXTMARKERS
          
            // A shared marker spans multiple linked documents. It is
            // implemented as a meta-marker-object controlling multiple normal
            // markers.
            var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
              this.markers = markers;
              this.primary = primary;
              for (var i = 0; i < markers.length; ++i)
                markers[i].parent = this;
            };
            eventMixin(SharedTextMarker);
          
            SharedTextMarker.prototype.clear = function() {
              if (this.explicitlyCleared) return;
              this.explicitlyCleared = true;
              for (var i = 0; i < this.markers.length; ++i)
                this.markers[i].clear();
              signalLater(this, "clear");
            };
            SharedTextMarker.prototype.find = function(side, lineObj) {
              return this.primary.find(side, lineObj);
            };
          
            function markTextShared(doc, from, to, options, type) {
              options = copyObj(options);
              options.shared = false;
              var markers = [markText(doc, from, to, options, type)], primary = markers[0];
              var widget = options.widgetNode;
              linkedDocs(doc, function(doc) {
                if (widget) options.widgetNode = widget.cloneNode(true);
                markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
                for (var i = 0; i < doc.linked.length; ++i)
                  if (doc.linked[i].isParent) return;
                primary = lst(markers);
              });
              return new SharedTextMarker(markers, primary);
            }
          
            function findSharedMarkers(doc) {
              return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
                                   function(m) { return m.parent; });
            }
          
            function copySharedMarkers(doc, markers) {
              for (var i = 0; i < markers.length; i++) {
                var marker = markers[i], pos = marker.find();
                var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
                if (cmp(mFrom, mTo)) {
                  var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
                  marker.markers.push(subMark);
                  subMark.parent = marker;
                }
              }
            }
          
            function detachSharedMarkers(markers) {
              for (var i = 0; i < markers.length; i++) {
                var marker = markers[i], linked = [marker.primary.doc];;
                linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
                for (var j = 0; j < marker.markers.length; j++) {
                  var subMarker = marker.markers[j];
                  if (indexOf(linked, subMarker.doc) == -1) {
                    subMarker.parent = null;
                    marker.markers.splice(j--, 1);
                  }
                }
              }
            }
          
            // TEXTMARKER SPANS
          
            function MarkedSpan(marker, from, to) {
              this.marker = marker;
              this.from = from; this.to = to;
            }
          
            // Search an array of spans for a span matching the given marker.
            function getMarkedSpanFor(spans, marker) {
              if (spans) for (var i = 0; i < spans.length; ++i) {
                var span = spans[i];
                if (span.marker == marker) return span;
              }
            }
            // Remove a span from an array, returning undefined if no spans are
            // left (we don't store arrays for lines without spans).
            function removeMarkedSpan(spans, span) {
              for (var r, i = 0; i < spans.length; ++i)
                if (spans[i] != span) (r || (r = [])).push(spans[i]);
              return r;
            }
            // Add a span to a line.
            function addMarkedSpan(line, span) {
              line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
              span.marker.attachLine(line);
            }
          
            // Used for the algorithm that adjusts markers for a change in the
            // document. These functions cut an array of spans at a given
            // character position, returning an array of remaining chunks (or
            // undefined if nothing remains).
            function markedSpansBefore(old, startCh, isInsert) {
              if (old) for (var i = 0, nw; i < old.length; ++i) {
                var span = old[i], marker = span.marker;
                var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
                if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
                  var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
                  (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
                }
              }
              return nw;
            }
            function markedSpansAfter(old, endCh, isInsert) {
              if (old) for (var i = 0, nw; i < old.length; ++i) {
                var span = old[i], marker = span.marker;
                var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
                if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
                  var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
                  (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
                                                        span.to == null ? null : span.to - endCh));
                }
              }
              return nw;
            }
          
            // Given a change object, compute the new set of marker spans that
            // cover the line in which the change took place. Removes spans
            // entirely within the change, reconnects spans belonging to the
            // same marker that appear on both sides of the change, and cuts off
            // spans partially within the change. Returns an array of span
            // arrays with one element for each line in (after) the change.
            function stretchSpansOverChange(doc, change) {
              if (change.full) return null;
              var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
              var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
              if (!oldFirst && !oldLast) return null;
          
              var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
              // Get the spans that 'stick out' on both sides
              var first = markedSpansBefore(oldFirst, startCh, isInsert);
              var last = markedSpansAfter(oldLast, endCh, isInsert);
          
              // Next, merge those two ends
              var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
              if (first) {
                // Fix up .to properties of first
                for (var i = 0; i < first.length; ++i) {
                  var span = first[i];
                  if (span.to == null) {
                    var found = getMarkedSpanFor(last, span.marker);
                    if (!found) span.to = startCh;
                    else if (sameLine) span.to = found.to == null ? null : found.to + offset;
                  }
                }
              }
              if (last) {
                // Fix up .from in last (or move them into first in case of sameLine)
                for (var i = 0; i < last.length; ++i) {
                  var span = last[i];
                  if (span.to != null) span.to += offset;
                  if (span.from == null) {
                    var found = getMarkedSpanFor(first, span.marker);
                    if (!found) {
                      span.from = offset;
                      if (sameLine) (first || (first = [])).push(span);
                    }
                  } else {
                    span.from += offset;
                    if (sameLine) (first || (first = [])).push(span);
                  }
                }
              }
              // Make sure we didn't create any zero-length spans
              if (first) first = clearEmptySpans(first);
              if (last && last != first) last = clearEmptySpans(last);
          
              var newMarkers = [first];
              if (!sameLine) {
                // Fill gap with whole-line-spans
                var gap = change.text.length - 2, gapMarkers;
                if (gap > 0 && first)
                  for (var i = 0; i < first.length; ++i)
                    if (first[i].to == null)
                      (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
                for (var i = 0; i < gap; ++i)
                  newMarkers.push(gapMarkers);
                newMarkers.push(last);
              }
              return newMarkers;
            }
          
            // Remove spans that are empty and don't have a clearWhenEmpty
            // option of false.
            function clearEmptySpans(spans) {
              for (var i = 0; i < spans.length; ++i) {
                var span = spans[i];
                if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
                  spans.splice(i--, 1);
              }
              if (!spans.length) return null;
              return spans;
            }
          
            // Used for un/re-doing changes from the history. Combines the
            // result of computing the existing spans with the set of spans that
            // existed in the history (so that deleting around a span and then
            // undoing brings back the span).
            function mergeOldSpans(doc, change) {
              var old = getOldSpans(doc, change);
              var stretched = stretchSpansOverChange(doc, change);
              if (!old) return stretched;
              if (!stretched) return old;
          
              for (var i = 0; i < old.length; ++i) {
                var oldCur = old[i], stretchCur = stretched[i];
                if (oldCur && stretchCur) {
                  spans: for (var j = 0; j < stretchCur.length; ++j) {
                    var span = stretchCur[j];
                    for (var k = 0; k < oldCur.length; ++k)
                      if (oldCur[k].marker == span.marker) continue spans;
                    oldCur.push(span);
                  }
                } else if (stretchCur) {
                  old[i] = stretchCur;
                }
              }
              return old;
            }
          
            // Used to 'clip' out readOnly ranges when making a change.
            function removeReadOnlyRanges(doc, from, to) {
              var markers = null;
              doc.iter(from.line, to.line + 1, function(line) {
                if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
                  var mark = line.markedSpans[i].marker;
                  if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
                    (markers || (markers = [])).push(mark);
                }
              });
              if (!markers) return null;
              var parts = [{from: from, to: to}];
              for (var i = 0; i < markers.length; ++i) {
                var mk = markers[i], m = mk.find(0);
                for (var j = 0; j < parts.length; ++j) {
                  var p = parts[j];
                  if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
                  var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
                  if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
                    newParts.push({from: p.from, to: m.from});
                  if (dto > 0 || !mk.inclusiveRight && !dto)
                    newParts.push({from: m.to, to: p.to});
                  parts.splice.apply(parts, newParts);
                  j += newParts.length - 1;
                }
              }
              return parts;
            }
          
            // Connect or disconnect spans from a line.
            function detachMarkedSpans(line) {
              var spans = line.markedSpans;
              if (!spans) return;
              for (var i = 0; i < spans.length; ++i)
                spans[i].marker.detachLine(line);
              line.markedSpans = null;
            }
            function attachMarkedSpans(line, spans) {
              if (!spans) return;
              for (var i = 0; i < spans.length; ++i)
                spans[i].marker.attachLine(line);
              line.markedSpans = spans;
            }
          
            // Helpers used when computing which overlapping collapsed span
            // counts as the larger one.
            function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
            function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
          
            // Returns a number indicating which of two overlapping collapsed
            // spans is larger (and thus includes the other). Falls back to
            // comparing ids when the spans cover exactly the same range.
            function compareCollapsedMarkers(a, b) {
              var lenDiff = a.lines.length - b.lines.length;
              if (lenDiff != 0) return lenDiff;
              var aPos = a.find(), bPos = b.find();
              var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
              if (fromCmp) return -fromCmp;
              var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
              if (toCmp) return toCmp;
              return b.id - a.id;
            }
          
            // Find out whether a line ends or starts in a collapsed span. If
            // so, return the marker for that span.
            function collapsedSpanAtSide(line, start) {
              var sps = sawCollapsedSpans && line.markedSpans, found;
              if (sps) for (var sp, i = 0; i < sps.length; ++i) {
                sp = sps[i];
                if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
                    (!found || compareCollapsedMarkers(found, sp.marker) < 0))
                  found = sp.marker;
              }
              return found;
            }
            function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
            function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
          
            // Test whether there exists a collapsed span that partially
            // overlaps (covers the start or end, but not both) of a new span.
            // Such overlap is not allowed.
            function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
              var line = getLine(doc, lineNo);
              var sps = sawCollapsedSpans && line.markedSpans;
              if (sps) for (var i = 0; i < sps.length; ++i) {
                var sp = sps[i];
                if (!sp.marker.collapsed) continue;
                var found = sp.marker.find(0);
                var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
                var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
                if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
                if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
                    fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
                  return true;
              }
            }
          
            // A visual line is a line as drawn on the screen. Folding, for
            // example, can cause multiple logical lines to appear on the same
            // visual line. This finds the start of the visual line that the
            // given line is part of (usually that is the line itself).
            function visualLine(line) {
              var merged;
              while (merged = collapsedSpanAtStart(line))
                line = merged.find(-1, true).line;
              return line;
            }
          
            // Returns an array of logical lines that continue the visual line
            // started by the argument, or undefined if there are no such lines.
            function visualLineContinued(line) {
              var merged, lines;
              while (merged = collapsedSpanAtEnd(line)) {
                line = merged.find(1, true).line;
                (lines || (lines = [])).push(line);
              }
              return lines;
            }
          
            // Get the line number of the start of the visual line that the
            // given line number is part of.
            function visualLineNo(doc, lineN) {
              var line = getLine(doc, lineN), vis = visualLine(line);
              if (line == vis) return lineN;
              return lineNo(vis);
            }
            // Get the line number of the start of the next visual line after
            // the given line.
            function visualLineEndNo(doc, lineN) {
              if (lineN > doc.lastLine()) return lineN;
              var line = getLine(doc, lineN), merged;
              if (!lineIsHidden(doc, line)) return lineN;
              while (merged = collapsedSpanAtEnd(line))
                line = merged.find(1, true).line;
              return lineNo(line) + 1;
            }
          
            // Compute whether a line is hidden. Lines count as hidden when they
            // are part of a visual line that starts with another line, or when
            // they are entirely covered by collapsed, non-widget span.
            function lineIsHidden(doc, line) {
              var sps = sawCollapsedSpans && line.markedSpans;
              if (sps) for (var sp, i = 0; i < sps.length; ++i) {
                sp = sps[i];
                if (!sp.marker.collapsed) continue;
                if (sp.from == null) return true;
                if (sp.marker.widgetNode) continue;
                if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
                  return true;
              }
            }
            function lineIsHiddenInner(doc, line, span) {
              if (span.to == null) {
                var end = span.marker.find(1, true);
                return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
              }
              if (span.marker.inclusiveRight && span.to == line.text.length)
                return true;
              for (var sp, i = 0; i < line.markedSpans.length; ++i) {
                sp = line.markedSpans[i];
                if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
                    (sp.to == null || sp.to != span.from) &&
                    (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
                    lineIsHiddenInner(doc, line, sp)) return true;
              }
            }
          
            // LINE WIDGETS
          
            // Line widgets are block elements displayed above or below a line.
          
            var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
              if (options) for (var opt in options) if (options.hasOwnProperty(opt))
                this[opt] = options[opt];
              this.cm = cm;
              this.node = node;
            };
            eventMixin(LineWidget);
          
            function adjustScrollWhenAboveVisible(cm, line, diff) {
              if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
                addToScrollPos(cm, null, diff);
            }
          
            LineWidget.prototype.clear = function() {
              var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
              if (no == null || !ws) return;
              for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
              if (!ws.length) line.widgets = null;
              var height = widgetHeight(this);
              runInOp(cm, function() {
                adjustScrollWhenAboveVisible(cm, line, -height);
                regLineChange(cm, no, "widget");
                updateLineHeight(line, Math.max(0, line.height - height));
              });
            };
            LineWidget.prototype.changed = function() {
              var oldH = this.height, cm = this.cm, line = this.line;
              this.height = null;
              var diff = widgetHeight(this) - oldH;
              if (!diff) return;
              runInOp(cm, function() {
                cm.curOp.forceUpdate = true;
                adjustScrollWhenAboveVisible(cm, line, diff);
                updateLineHeight(line, line.height + diff);
              });
            };
          
            function widgetHeight(widget) {
              if (widget.height != null) return widget.height;
              if (!contains(document.body, widget.node)) {
                var parentStyle = "position: relative;";
                if (widget.coverGutter)
                  parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
                if (widget.noHScroll)
                  parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";
                removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
              }
              return widget.height = widget.node.offsetHeight;
            }
          
            function addLineWidget(cm, handle, node, options) {
              var widget = new LineWidget(cm, node, options);
              if (widget.noHScroll) cm.display.alignWidgets = true;
              changeLine(cm.doc, handle, "widget", function(line) {
                var widgets = line.widgets || (line.widgets = []);
                if (widget.insertAt == null) widgets.push(widget);
                else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
                widget.line = line;
                if (!lineIsHidden(cm.doc, line)) {
                  var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
                  updateLineHeight(line, line.height + widgetHeight(widget));
                  if (aboveVisible) addToScrollPos(cm, null, widget.height);
                  cm.curOp.forceUpdate = true;
                }
                return true;
              });
              return widget;
            }
          
            // LINE DATA STRUCTURE
          
            // Line objects. These hold state related to a line, including
            // highlighting info (the styles array).
            var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
              this.text = text;
              attachMarkedSpans(this, markedSpans);
              this.height = estimateHeight ? estimateHeight(this) : 1;
            };
            eventMixin(Line);
            Line.prototype.lineNo = function() { return lineNo(this); };
          
            // Change the content (text, markers) of a line. Automatically
            // invalidates cached information and tries to re-estimate the
            // line's height.
            function updateLine(line, text, markedSpans, estimateHeight) {
              line.text = text;
              if (line.stateAfter) line.stateAfter = null;
              if (line.styles) line.styles = null;
              if (line.order != null) line.order = null;
              detachMarkedSpans(line);
              attachMarkedSpans(line, markedSpans);
              var estHeight = estimateHeight ? estimateHeight(line) : 1;
              if (estHeight != line.height) updateLineHeight(line, estHeight);
            }
          
            // Detach a line from the document tree and its markers.
            function cleanUpLine(line) {
              line.parent = null;
              detachMarkedSpans(line);
            }
          
            function extractLineClasses(type, output) {
              if (type) for (;;) {
                var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
                if (!lineClass) break;
                type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
                var prop = lineClass[1] ? "bgClass" : "textClass";
                if (output[prop] == null)
                  output[prop] = lineClass[2];
                else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
                  output[prop] += " " + lineClass[2];
              }
              return type;
            }
          
            function callBlankLine(mode, state) {
              if (mode.blankLine) return mode.blankLine(state);
              if (!mode.innerMode) return;
              var inner = CodeMirror.innerMode(mode, state);
              if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
            }
          
            function readToken(mode, stream, state, inner) {
              for (var i = 0; i < 10; i++) {
                if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
                var style = mode.token(stream, state);
                if (stream.pos > stream.start) return style;
              }
              throw new Error("Mode " + mode.name + " failed to advance stream.");
            }
          
            // Utility for getTokenAt and getLineTokens
            function takeToken(cm, pos, precise, asArray) {
              function getObj(copy) {
                return {start: stream.start, end: stream.pos,
                        string: stream.current(),
                        type: style || null,
                        state: copy ? copyState(doc.mode, state) : state};
              }
          
              var doc = cm.doc, mode = doc.mode, style;
              pos = clipPos(doc, pos);
              var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
              var stream = new StringStream(line.text, cm.options.tabSize), tokens;
              if (asArray) tokens = [];
              while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
                stream.start = stream.pos;
                style = readToken(mode, stream, state);
                if (asArray) tokens.push(getObj(true));
              }
              return asArray ? tokens : getObj();
            }
          
            // Run the given mode's parser over a line, calling f for each token.
            function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
              var flattenSpans = mode.flattenSpans;
              if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
              var curStart = 0, curStyle = null;
              var stream = new StringStream(text, cm.options.tabSize), style;
              var inner = cm.options.addModeClass && [null];
              if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
              while (!stream.eol()) {
                if (stream.pos > cm.options.maxHighlightLength) {
                  flattenSpans = false;
                  if (forceToEnd) processLine(cm, text, state, stream.pos);
                  stream.pos = text.length;
                  style = null;
                } else {
                  style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
                }
                if (inner) {
                  var mName = inner[0].name;
                  if (mName) style = "m-" + (style ? mName + " " + style : mName);
                }
                if (!flattenSpans || curStyle != style) {
                  while (curStart < stream.start) {
                    curStart = Math.min(stream.start, curStart + 50000);
                    f(curStart, curStyle);
                  }
                  curStyle = style;
                }
                stream.start = stream.pos;
              }
              while (curStart < stream.pos) {
                // Webkit seems to refuse to render text nodes longer than 57444 characters
                var pos = Math.min(stream.pos, curStart + 50000);
                f(pos, curStyle);
                curStart = pos;
              }
            }
          
            // Compute a style array (an array starting with a mode generation
            // -- for invalidation -- followed by pairs of end positions and
            // style strings), which is used to highlight the tokens on the
            // line.
            function highlightLine(cm, line, state, forceToEnd) {
              // A styles array always starts with a number identifying the
              // mode/overlays that it is based on (for easy invalidation).
              var st = [cm.state.modeGen], lineClasses = {};
              // Compute the base array of styles
              runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
                st.push(end, style);
              }, lineClasses, forceToEnd);
          
              // Run overlays, adjust style array.
              for (var o = 0; o < cm.state.overlays.length; ++o) {
                var overlay = cm.state.overlays[o], i = 1, at = 0;
                runMode(cm, line.text, overlay.mode, true, function(end, style) {
                  var start = i;
                  // Ensure there's a token end at the current position, and that i points at it
                  while (at < end) {
                    var i_end = st[i];
                    if (i_end > end)
                      st.splice(i, 1, end, st[i+1], i_end);
                    i += 2;
                    at = Math.min(end, i_end);
                  }
                  if (!style) return;
                  if (overlay.opaque) {
                    st.splice(start, i - start, end, "cm-overlay " + style);
                    i = start + 2;
                  } else {
                    for (; start < i; start += 2) {
                      var cur = st[start+1];
                      st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
                    }
                  }
                }, lineClasses);
              }
          
              return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
            }
          
            function getLineStyles(cm, line, updateFrontier) {
              if (!line.styles || line.styles[0] != cm.state.modeGen) {
                var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
                line.styles = result.styles;
                if (result.classes) line.styleClasses = result.classes;
                else if (line.styleClasses) line.styleClasses = null;
                if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
              }
              return line.styles;
            }
          
            // Lightweight form of highlight -- proceed over this line and
            // update state, but don't save a style array. Used for lines that
            // aren't currently visible.
            function processLine(cm, text, state, startAt) {
              var mode = cm.doc.mode;
              var stream = new StringStream(text, cm.options.tabSize);
              stream.start = stream.pos = startAt || 0;
              if (text == "") callBlankLine(mode, state);
              while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
                readToken(mode, stream, state);
                stream.start = stream.pos;
              }
            }
          
            // Convert a style as returned by a mode (either null, or a string
            // containing one or more styles) to a CSS style. This is cached,
            // and also looks for line-wide styles.
            var styleToClassCache = {}, styleToClassCacheWithMode = {};
            function interpretTokenStyle(style, options) {
              if (!style || /^\s*$/.test(style)) return null;
              var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
              return cache[style] ||
                (cache[style] = style.replace(/\S+/g, "cm-$&"));
            }
          
            // Render the DOM representation of the text of a line. Also builds
            // up a 'line map', which points at the DOM nodes that represent
            // specific stretches of text, and is used by the measuring code.
            // The returned object contains the DOM node, this map, and
            // information about line-wide styles that were set by the mode.
            function buildLineContent(cm, lineView) {
              // The padding-right forces the element to have a 'border', which
              // is needed on Webkit to be able to get line-level bounding
              // rectangles for it (in measureChar).
              var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
              var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};
              lineView.measure = {};
          
              // Iterate over the logical lines that make up this visual line.
              for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
                var line = i ? lineView.rest[i - 1] : lineView.line, order;
                builder.pos = 0;
                builder.addToken = buildToken;
                // Optionally wire in some hacks into the token-rendering
                // algorithm, to deal with browser quirks.
                if ((ie || webkit) && cm.getOption("lineWrapping"))
                  builder.addToken = buildTokenSplitSpaces(builder.addToken);
                if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
                  builder.addToken = buildTokenBadBidi(builder.addToken, order);
                builder.map = [];
                var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
                insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
                if (line.styleClasses) {
                  if (line.styleClasses.bgClass)
                    builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
                  if (line.styleClasses.textClass)
                    builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
                }
          
                // Ensure at least a single node is present, for measuring.
                if (builder.map.length == 0)
                  builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
          
                // Store the map and a cache object for the current logical line
                if (i == 0) {
                  lineView.measure.map = builder.map;
                  lineView.measure.cache = {};
                } else {
                  (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
                  (lineView.measure.caches || (lineView.measure.caches = [])).push({});
                }
              }
          
              // See issue #2901
              if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
                builder.content.className = "cm-tab-wrap-hack";
          
              signal(cm, "renderLine", cm, lineView.line, builder.pre);
              if (builder.pre.className)
                builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
          
              return builder;
            }
          
            function defaultSpecialCharPlaceholder(ch) {
              var token = elt("span", "\u2022", "cm-invalidchar");
              token.title = "\\u" + ch.charCodeAt(0).toString(16);
              token.setAttribute("aria-label", token.title);
              return token;
            }
          
            // Build up the DOM representation for a single token, and add it to
            // the line map. Takes care to render special characters separately.
            function buildToken(builder, text, style, startStyle, endStyle, title, css) {
              if (!text) return;
              var special = builder.cm.options.specialChars, mustWrap = false;
              if (!special.test(text)) {
                builder.col += text.length;
                var content = document.createTextNode(text);
                builder.map.push(builder.pos, builder.pos + text.length, content);
                if (ie && ie_version < 9) mustWrap = true;
                builder.pos += text.length;
              } else {
                var content = document.createDocumentFragment(), pos = 0;
                while (true) {
                  special.lastIndex = pos;
                  var m = special.exec(text);
                  var skipped = m ? m.index - pos : text.length - pos;
                  if (skipped) {
                    var txt = document.createTextNode(text.slice(pos, pos + skipped));
                    if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
                    else content.appendChild(txt);
                    builder.map.push(builder.pos, builder.pos + skipped, txt);
                    builder.col += skipped;
                    builder.pos += skipped;
                  }
                  if (!m) break;
                  pos += skipped + 1;
                  if (m[0] == "\t") {
                    var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
                    var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
                    txt.setAttribute("role", "presentation");
                    txt.setAttribute("cm-text", "\t");
                    builder.col += tabWidth;
                  } else {
                    var txt = builder.cm.options.specialCharPlaceholder(m[0]);
                    txt.setAttribute("cm-text", m[0]);
                    if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
                    else content.appendChild(txt);
                    builder.col += 1;
                  }
                  builder.map.push(builder.pos, builder.pos + 1, txt);
                  builder.pos++;
                }
              }
              if (style || startStyle || endStyle || mustWrap || css) {
                var fullStyle = style || "";
                if (startStyle) fullStyle += startStyle;
                if (endStyle) fullStyle += endStyle;
                var token = elt("span", [content], fullStyle, css);
                if (title) token.title = title;
                return builder.content.appendChild(token);
              }
              builder.content.appendChild(content);
            }
          
            function buildTokenSplitSpaces(inner) {
              function split(old) {
                var out = " ";
                for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
                out += " ";
                return out;
              }
              return function(builder, text, style, startStyle, endStyle, title) {
                inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
              };
            }
          
            // Work around nonsense dimensions being reported for stretches of
            // right-to-left text.
            function buildTokenBadBidi(inner, order) {
              return function(builder, text, style, startStyle, endStyle, title) {
                style = style ? style + " cm-force-border" : "cm-force-border";
                var start = builder.pos, end = start + text.length;
                for (;;) {
                  // Find the part that overlaps with the start of this text
                  for (var i = 0; i < order.length; i++) {
                    var part = order[i];
                    if (part.to > start && part.from <= start) break;
                  }
                  if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);
                  inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);
                  startStyle = null;
                  text = text.slice(part.to - start);
                  start = part.to;
                }
              };
            }
          
            function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
              var widget = !ignoreWidget && marker.widgetNode;
              if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
              if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
                if (!widget)
                  widget = builder.content.appendChild(document.createElement("span"));
                widget.setAttribute("cm-marker", marker.id);
              }
              if (widget) {
                builder.cm.display.input.setUneditable(widget);
                builder.content.appendChild(widget);
              }
              builder.pos += size;
            }
          
            // Outputs a number of spans to make up a line, taking highlighting
            // and marked text into account.
            function insertLineContent(line, builder, styles) {
              var spans = line.markedSpans, allText = line.text, at = 0;
              if (!spans) {
                for (var i = 1; i < styles.length; i+=2)
                  builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
                return;
              }
          
              var len = allText.length, pos = 0, i = 1, text = "", style, css;
              var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
              for (;;) {
                if (nextChange == pos) { // Update current marker set
                  spanStyle = spanEndStyle = spanStartStyle = title = css = "";
                  collapsed = null; nextChange = Infinity;
                  var foundBookmarks = [];
                  for (var j = 0; j < spans.length; ++j) {
                    var sp = spans[j], m = sp.marker;
                    if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
                      if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
                      if (m.className) spanStyle += " " + m.className;
                      if (m.css) css = m.css;
                      if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
                      if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
                      if (m.title && !title) title = m.title;
                      if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
                        collapsed = sp;
                    } else if (sp.from > pos && nextChange > sp.from) {
                      nextChange = sp.from;
                    }
                    if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
                  }
                  if (collapsed && (collapsed.from || 0) == pos) {
                    buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
                                       collapsed.marker, collapsed.from == null);
                    if (collapsed.to == null) return;
                  }
                  if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
                    buildCollapsedSpan(builder, 0, foundBookmarks[j]);
                }
                if (pos >= len) break;
          
                var upto = Math.min(len, nextChange);
                while (true) {
                  if (text) {
                    var end = pos + text.length;
                    if (!collapsed) {
                      var tokenText = end > upto ? text.slice(0, upto - pos) : text;
                      builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
                                       spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
                    }
                    if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
                    pos = end;
                    spanStartStyle = "";
                  }
                  text = allText.slice(at, at = styles[i++]);
                  style = interpretTokenStyle(styles[i++], builder.cm.options);
                }
              }
            }
          
            // DOCUMENT DATA STRUCTURE
          
            // By default, updates that start and end at the beginning of a line
            // are treated specially, in order to make the association of line
            // widgets and marker elements with the text behave more intuitive.
            function isWholeLineUpdate(doc, change) {
              return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
                (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
            }
          
            // Perform a change on the document data structure.
            function updateDoc(doc, change, markedSpans, estimateHeight) {
              function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
              function update(line, text, spans) {
                updateLine(line, text, spans, estimateHeight);
                signalLater(line, "change", line, change);
              }
              function linesFor(start, end) {
                for (var i = start, result = []; i < end; ++i)
                  result.push(new Line(text[i], spansFor(i), estimateHeight));
                return result;
              }
          
              var from = change.from, to = change.to, text = change.text;
              var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
              var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
          
              // Adjust the line structure
              if (change.full) {
                doc.insert(0, linesFor(0, text.length));
                doc.remove(text.length, doc.size - text.length);
              } else if (isWholeLineUpdate(doc, change)) {
                // This is a whole-line replace. Treated specially to make
                // sure line objects move the way they are supposed to.
                var added = linesFor(0, text.length - 1);
                update(lastLine, lastLine.text, lastSpans);
                if (nlines) doc.remove(from.line, nlines);
                if (added.length) doc.insert(from.line, added);
              } else if (firstLine == lastLine) {
                if (text.length == 1) {
                  update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
                } else {
                  var added = linesFor(1, text.length - 1);
                  added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
                  update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
                  doc.insert(from.line + 1, added);
                }
              } else if (text.length == 1) {
                update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
                doc.remove(from.line + 1, nlines);
              } else {
                update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
                update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
                var added = linesFor(1, text.length - 1);
                if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
                doc.insert(from.line + 1, added);
              }
          
              signalLater(doc, "change", doc, change);
            }
          
            // The document is represented as a BTree consisting of leaves, with
            // chunk of lines in them, and branches, with up to ten leaves or
            // other branch nodes below them. The top node is always a branch
            // node, and is the document object itself (meaning it has
            // additional methods and properties).
            //
            // All nodes have parent links. The tree is used both to go from
            // line numbers to line objects, and to go from objects to numbers.
            // It also indexes by height, and is used to convert between height
            // and line object, and to find the total height of the document.
            //
            // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
          
            function LeafChunk(lines) {
              this.lines = lines;
              this.parent = null;
              for (var i = 0, height = 0; i < lines.length; ++i) {
                lines[i].parent = this;
                height += lines[i].height;
              }
              this.height = height;
            }
          
            LeafChunk.prototype = {
              chunkSize: function() { return this.lines.length; },
              // Remove the n lines at offset 'at'.
              removeInner: function(at, n) {
                for (var i = at, e = at + n; i < e; ++i) {
                  var line = this.lines[i];
                  this.height -= line.height;
                  cleanUpLine(line);
                  signalLater(line, "delete");
                }
                this.lines.splice(at, n);
              },
              // Helper used to collapse a small branch into a single leaf.
              collapse: function(lines) {
                lines.push.apply(lines, this.lines);
              },
              // Insert the given array of lines at offset 'at', count them as
              // having the given height.
              insertInner: function(at, lines, height) {
                this.height += height;
                this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
                for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
              },
              // Used to iterate over a part of the tree.
              iterN: function(at, n, op) {
                for (var e = at + n; at < e; ++at)
                  if (op(this.lines[at])) return true;
              }
            };
          
            function BranchChunk(children) {
              this.children = children;
              var size = 0, height = 0;
              for (var i = 0; i < children.length; ++i) {
                var ch = children[i];
                size += ch.chunkSize(); height += ch.height;
                ch.parent = this;
              }
              this.size = size;
              this.height = height;
              this.parent = null;
            }
          
            BranchChunk.prototype = {
              chunkSize: function() { return this.size; },
              removeInner: function(at, n) {
                this.size -= n;
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at < sz) {
                    var rm = Math.min(n, sz - at), oldHeight = child.height;
                    child.removeInner(at, rm);
                    this.height -= oldHeight - child.height;
                    if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
                    if ((n -= rm) == 0) break;
                    at = 0;
                  } else at -= sz;
                }
                // If the result is smaller than 25 lines, ensure that it is a
                // single leaf node.
                if (this.size - n < 25 &&
                    (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
                  var lines = [];
                  this.collapse(lines);
                  this.children = [new LeafChunk(lines)];
                  this.children[0].parent = this;
                }
              },
              collapse: function(lines) {
                for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
              },
              insertInner: function(at, lines, height) {
                this.size += lines.length;
                this.height += height;
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at <= sz) {
                    child.insertInner(at, lines, height);
                    if (child.lines && child.lines.length > 50) {
                      while (child.lines.length > 50) {
                        var spilled = child.lines.splice(child.lines.length - 25, 25);
                        var newleaf = new LeafChunk(spilled);
                        child.height -= newleaf.height;
                        this.children.splice(i + 1, 0, newleaf);
                        newleaf.parent = this;
                      }
                      this.maybeSpill();
                    }
                    break;
                  }
                  at -= sz;
                }
              },
              // When a node has grown, check whether it should be split.
              maybeSpill: function() {
                if (this.children.length <= 10) return;
                var me = this;
                do {
                  var spilled = me.children.splice(me.children.length - 5, 5);
                  var sibling = new BranchChunk(spilled);
                  if (!me.parent) { // Become the parent node
                    var copy = new BranchChunk(me.children);
                    copy.parent = me;
                    me.children = [copy, sibling];
                    me = copy;
                  } else {
                    me.size -= sibling.size;
                    me.height -= sibling.height;
                    var myIndex = indexOf(me.parent.children, me);
                    me.parent.children.splice(myIndex + 1, 0, sibling);
                  }
                  sibling.parent = me.parent;
                } while (me.children.length > 10);
                me.parent.maybeSpill();
              },
              iterN: function(at, n, op) {
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at < sz) {
                    var used = Math.min(n, sz - at);
                    if (child.iterN(at, used, op)) return true;
                    if ((n -= used) == 0) break;
                    at = 0;
                  } else at -= sz;
                }
              }
            };
          
            var nextDocId = 0;
            var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
              if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
              if (firstLine == null) firstLine = 0;
          
              BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
              this.first = firstLine;
              this.scrollTop = this.scrollLeft = 0;
              this.cantEdit = false;
              this.cleanGeneration = 1;
              this.frontier = firstLine;
              var start = Pos(firstLine, 0);
              this.sel = simpleSelection(start);
              this.history = new History(null);
              this.id = ++nextDocId;
              this.modeOption = mode;
          
              if (typeof text == "string") text = splitLines(text);
              updateDoc(this, {from: start, to: start, text: text});
              setSelection(this, simpleSelection(start), sel_dontScroll);
            };
          
            Doc.prototype = createObj(BranchChunk.prototype, {
              constructor: Doc,
              // Iterate over the document. Supports two forms -- with only one
              // argument, it calls that for each line in the document. With
              // three, it iterates over the range given by the first two (with
              // the second being non-inclusive).
              iter: function(from, to, op) {
                if (op) this.iterN(from - this.first, to - from, op);
                else this.iterN(this.first, this.first + this.size, from);
              },
          
              // Non-public interface for adding and removing lines.
              insert: function(at, lines) {
                var height = 0;
                for (var i = 0; i < lines.length; ++i) height += lines[i].height;
                this.insertInner(at - this.first, lines, height);
              },
              remove: function(at, n) { this.removeInner(at - this.first, n); },
          
              // From here, the methods are part of the public interface. Most
              // are also available from CodeMirror (editor) instances.
          
              getValue: function(lineSep) {
                var lines = getLines(this, this.first, this.first + this.size);
                if (lineSep === false) return lines;
                return lines.join(lineSep || "\n");
              },
              setValue: docMethodOp(function(code) {
                var top = Pos(this.first, 0), last = this.first + this.size - 1;
                makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
                                  text: splitLines(code), origin: "setValue", full: true}, true);
                setSelection(this, simpleSelection(top));
              }),
              replaceRange: function(code, from, to, origin) {
                from = clipPos(this, from);
                to = to ? clipPos(this, to) : from;
                replaceRange(this, code, from, to, origin);
              },
              getRange: function(from, to, lineSep) {
                var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
                if (lineSep === false) return lines;
                return lines.join(lineSep || "\n");
              },
          
              getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
          
              getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
              getLineNumber: function(line) {return lineNo(line);},
          
              getLineHandleVisualStart: function(line) {
                if (typeof line == "number") line = getLine(this, line);
                return visualLine(line);
              },
          
              lineCount: function() {return this.size;},
              firstLine: function() {return this.first;},
              lastLine: function() {return this.first + this.size - 1;},
          
              clipPos: function(pos) {return clipPos(this, pos);},
          
              getCursor: function(start) {
                var range = this.sel.primary(), pos;
                if (start == null || start == "head") pos = range.head;
                else if (start == "anchor") pos = range.anchor;
                else if (start == "end" || start == "to" || start === false) pos = range.to();
                else pos = range.from();
                return pos;
              },
              listSelections: function() { return this.sel.ranges; },
              somethingSelected: function() {return this.sel.somethingSelected();},
          
              setCursor: docMethodOp(function(line, ch, options) {
                setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
              }),
              setSelection: docMethodOp(function(anchor, head, options) {
                setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
              }),
              extendSelection: docMethodOp(function(head, other, options) {
                extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
              }),
              extendSelections: docMethodOp(function(heads, options) {
                extendSelections(this, clipPosArray(this, heads, options));
              }),
              extendSelectionsBy: docMethodOp(function(f, options) {
                extendSelections(this, map(this.sel.ranges, f), options);
              }),
              setSelections: docMethodOp(function(ranges, primary, options) {
                if (!ranges.length) return;
                for (var i = 0, out = []; i < ranges.length; i++)
                  out[i] = new Range(clipPos(this, ranges[i].anchor),
                                     clipPos(this, ranges[i].head));
                if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
                setSelection(this, normalizeSelection(out, primary), options);
              }),
              addSelection: docMethodOp(function(anchor, head, options) {
                var ranges = this.sel.ranges.slice(0);
                ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
                setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
              }),
          
              getSelection: function(lineSep) {
                var ranges = this.sel.ranges, lines;
                for (var i = 0; i < ranges.length; i++) {
                  var sel = getBetween(this, ranges[i].from(), ranges[i].to());
                  lines = lines ? lines.concat(sel) : sel;
                }
                if (lineSep === false) return lines;
                else return lines.join(lineSep || "\n");
              },
              getSelections: function(lineSep) {
                var parts = [], ranges = this.sel.ranges;
                for (var i = 0; i < ranges.length; i++) {
                  var sel = getBetween(this, ranges[i].from(), ranges[i].to());
                  if (lineSep !== false) sel = sel.join(lineSep || "\n");
                  parts[i] = sel;
                }
                return parts;
              },
              replaceSelection: function(code, collapse, origin) {
                var dup = [];
                for (var i = 0; i < this.sel.ranges.length; i++)
                  dup[i] = code;
                this.replaceSelections(dup, collapse, origin || "+input");
              },
              replaceSelections: docMethodOp(function(code, collapse, origin) {
                var changes = [], sel = this.sel;
                for (var i = 0; i < sel.ranges.length; i++) {
                  var range = sel.ranges[i];
                  changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
                }
                var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
                for (var i = changes.length - 1; i >= 0; i--)
                  makeChange(this, changes[i]);
                if (newSel) setSelectionReplaceHistory(this, newSel);
                else if (this.cm) ensureCursorVisible(this.cm);
              }),
              undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
              redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
              undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
              redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
          
              setExtending: function(val) {this.extend = val;},
              getExtending: function() {return this.extend;},
          
              historySize: function() {
                var hist = this.history, done = 0, undone = 0;
                for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
                for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
                return {undo: done, redo: undone};
              },
              clearHistory: function() {this.history = new History(this.history.maxGeneration);},
          
              markClean: function() {
                this.cleanGeneration = this.changeGeneration(true);
              },
              changeGeneration: function(forceSplit) {
                if (forceSplit)
                  this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
                return this.history.generation;
              },
              isClean: function (gen) {
                return this.history.generation == (gen || this.cleanGeneration);
              },
          
              getHistory: function() {
                return {done: copyHistoryArray(this.history.done),
                        undone: copyHistoryArray(this.history.undone)};
              },
              setHistory: function(histData) {
                var hist = this.history = new History(this.history.maxGeneration);
                hist.done = copyHistoryArray(histData.done.slice(0), null, true);
                hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
              },
          
              addLineClass: docMethodOp(function(handle, where, cls) {
                return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
                  var prop = where == "text" ? "textClass"
                           : where == "background" ? "bgClass"
                           : where == "gutter" ? "gutterClass" : "wrapClass";
                  if (!line[prop]) line[prop] = cls;
                  else if (classTest(cls).test(line[prop])) return false;
                  else line[prop] += " " + cls;
                  return true;
                });
              }),
              removeLineClass: docMethodOp(function(handle, where, cls) {
                return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
                  var prop = where == "text" ? "textClass"
                           : where == "background" ? "bgClass"
                           : where == "gutter" ? "gutterClass" : "wrapClass";
                  var cur = line[prop];
                  if (!cur) return false;
                  else if (cls == null) line[prop] = null;
                  else {
                    var found = cur.match(classTest(cls));
                    if (!found) return false;
                    var end = found.index + found[0].length;
                    line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
                  }
                  return true;
                });
              }),
          
              markText: function(from, to, options) {
                return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
              },
              setBookmark: function(pos, options) {
                var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
                                insertLeft: options && options.insertLeft,
                                clearWhenEmpty: false, shared: options && options.shared};
                pos = clipPos(this, pos);
                return markText(this, pos, pos, realOpts, "bookmark");
              },
              findMarksAt: function(pos) {
                pos = clipPos(this, pos);
                var markers = [], spans = getLine(this, pos.line).markedSpans;
                if (spans) for (var i = 0; i < spans.length; ++i) {
                  var span = spans[i];
                  if ((span.from == null || span.from <= pos.ch) &&
                      (span.to == null || span.to >= pos.ch))
                    markers.push(span.marker.parent || span.marker);
                }
                return markers;
              },
              findMarks: function(from, to, filter) {
                from = clipPos(this, from); to = clipPos(this, to);
                var found = [], lineNo = from.line;
                this.iter(from.line, to.line + 1, function(line) {
                  var spans = line.markedSpans;
                  if (spans) for (var i = 0; i < spans.length; i++) {
                    var span = spans[i];
                    if (!(lineNo == from.line && from.ch > span.to ||
                          span.from == null && lineNo != from.line||
                          lineNo == to.line && span.from > to.ch) &&
                        (!filter || filter(span.marker)))
                      found.push(span.marker.parent || span.marker);
                  }
                  ++lineNo;
                });
                return found;
              },
              getAllMarks: function() {
                var markers = [];
                this.iter(function(line) {
                  var sps = line.markedSpans;
                  if (sps) for (var i = 0; i < sps.length; ++i)
                    if (sps[i].from != null) markers.push(sps[i].marker);
                });
                return markers;
              },
          
              posFromIndex: function(off) {
                var ch, lineNo = this.first;
                this.iter(function(line) {
                  var sz = line.text.length + 1;
                  if (sz > off) { ch = off; return true; }
                  off -= sz;
                  ++lineNo;
                });
                return clipPos(this, Pos(lineNo, ch));
              },
              indexFromPos: function (coords) {
                coords = clipPos(this, coords);
                var index = coords.ch;
                if (coords.line < this.first || coords.ch < 0) return 0;
                this.iter(this.first, coords.line, function (line) {
                  index += line.text.length + 1;
                });
                return index;
              },
          
              copy: function(copyHistory) {
                var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
                doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
                doc.sel = this.sel;
                doc.extend = false;
                if (copyHistory) {
                  doc.history.undoDepth = this.history.undoDepth;
                  doc.setHistory(this.getHistory());
                }
                return doc;
              },
          
              linkedDoc: function(options) {
                if (!options) options = {};
                var from = this.first, to = this.first + this.size;
                if (options.from != null && options.from > from) from = options.from;
                if (options.to != null && options.to < to) to = options.to;
                var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
                if (options.sharedHist) copy.history = this.history;
                (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
                copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
                copySharedMarkers(copy, findSharedMarkers(this));
                return copy;
              },
              unlinkDoc: function(other) {
                if (other instanceof CodeMirror) other = other.doc;
                if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
                  var link = this.linked[i];
                  if (link.doc != other) continue;
                  this.linked.splice(i, 1);
                  other.unlinkDoc(this);
                  detachSharedMarkers(findSharedMarkers(this));
                  break;
                }
                // If the histories were shared, split them again
                if (other.history == this.history) {
                  var splitIds = [other.id];
                  linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
                  other.history = new History(null);
                  other.history.done = copyHistoryArray(this.history.done, splitIds);
                  other.history.undone = copyHistoryArray(this.history.undone, splitIds);
                }
              },
              iterLinkedDocs: function(f) {linkedDocs(this, f);},
          
              getMode: function() {return this.mode;},
              getEditor: function() {return this.cm;}
            });
          
            // Public alias.
            Doc.prototype.eachLine = Doc.prototype.iter;
          
            // Set up methods on CodeMirror's prototype to redirect to the editor's document.
            var dontDelegate = "iter insert remove copy getEditor".split(" ");
            for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
              CodeMirror.prototype[prop] = (function(method) {
                return function() {return method.apply(this.doc, arguments);};
              })(Doc.prototype[prop]);
          
            eventMixin(Doc);
          
            // Call f for all linked documents.
            function linkedDocs(doc, f, sharedHistOnly) {
              function propagate(doc, skip, sharedHist) {
                if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
                  var rel = doc.linked[i];
                  if (rel.doc == skip) continue;
                  var shared = sharedHist && rel.sharedHist;
                  if (sharedHistOnly && !shared) continue;
                  f(rel.doc, shared);
                  propagate(rel.doc, doc, shared);
                }
              }
              propagate(doc, null, true);
            }
          
            // Attach a document to an editor.
            function attachDoc(cm, doc) {
              if (doc.cm) throw new Error("This document is already in use.");
              cm.doc = doc;
              doc.cm = cm;
              estimateLineHeights(cm);
              loadMode(cm);
              if (!cm.options.lineWrapping) findMaxLine(cm);
              cm.options.mode = doc.modeOption;
              regChange(cm);
            }
          
            // LINE UTILITIES
          
            // Find the line object corresponding to the given line number.
            function getLine(doc, n) {
              n -= doc.first;
              if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
              for (var chunk = doc; !chunk.lines;) {
                for (var i = 0;; ++i) {
                  var child = chunk.children[i], sz = child.chunkSize();
                  if (n < sz) { chunk = child; break; }
                  n -= sz;
                }
              }
              return chunk.lines[n];
            }
          
            // Get the part of a document between two positions, as an array of
            // strings.
            function getBetween(doc, start, end) {
              var out = [], n = start.line;
              doc.iter(start.line, end.line + 1, function(line) {
                var text = line.text;
                if (n == end.line) text = text.slice(0, end.ch);
                if (n == start.line) text = text.slice(start.ch);
                out.push(text);
                ++n;
              });
              return out;
            }
            // Get the lines between from and to, as array of strings.
            function getLines(doc, from, to) {
              var out = [];
              doc.iter(from, to, function(line) { out.push(line.text); });
              return out;
            }
          
            // Update the height of a line, propagating the height change
            // upwards to parent nodes.
            function updateLineHeight(line, height) {
              var diff = height - line.height;
              if (diff) for (var n = line; n; n = n.parent) n.height += diff;
            }
          
            // Given a line object, find its line number by walking up through
            // its parent links.
            function lineNo(line) {
              if (line.parent == null) return null;
              var cur = line.parent, no = indexOf(cur.lines, line);
              for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
                for (var i = 0;; ++i) {
                  if (chunk.children[i] == cur) break;
                  no += chunk.children[i].chunkSize();
                }
              }
              return no + cur.first;
            }
          
            // Find the line at the given vertical position, using the height
            // information in the document tree.
            function lineAtHeight(chunk, h) {
              var n = chunk.first;
              outer: do {
                for (var i = 0; i < chunk.children.length; ++i) {
                  var child = chunk.children[i], ch = child.height;
                  if (h < ch) { chunk = child; continue outer; }
                  h -= ch;
                  n += child.chunkSize();
                }
                return n;
              } while (!chunk.lines);
              for (var i = 0; i < chunk.lines.length; ++i) {
                var line = chunk.lines[i], lh = line.height;
                if (h < lh) break;
                h -= lh;
              }
              return n + i;
            }
          
          
            // Find the height above the given line.
            function heightAtLine(lineObj) {
              lineObj = visualLine(lineObj);
          
              var h = 0, chunk = lineObj.parent;
              for (var i = 0; i < chunk.lines.length; ++i) {
                var line = chunk.lines[i];
                if (line == lineObj) break;
                else h += line.height;
              }
              for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
                for (var i = 0; i < p.children.length; ++i) {
                  var cur = p.children[i];
                  if (cur == chunk) break;
                  else h += cur.height;
                }
              }
              return h;
            }
          
            // Get the bidi ordering for the given line (and cache it). Returns
            // false for lines that are fully left-to-right, and an array of
            // BidiSpan objects otherwise.
            function getOrder(line) {
              var order = line.order;
              if (order == null) order = line.order = bidiOrdering(line.text);
              return order;
            }
          
            // HISTORY
          
            function History(startGen) {
              // Arrays of change events and selections. Doing something adds an
              // event to done and clears undo. Undoing moves events from done
              // to undone, redoing moves them in the other direction.
              this.done = []; this.undone = [];
              this.undoDepth = Infinity;
              // Used to track when changes can be merged into a single undo
              // event
              this.lastModTime = this.lastSelTime = 0;
              this.lastOp = this.lastSelOp = null;
              this.lastOrigin = this.lastSelOrigin = null;
              // Used by the isClean() method
              this.generation = this.maxGeneration = startGen || 1;
            }
          
            // Create a history change event from an updateDoc-style change
            // object.
            function historyChangeFromChange(doc, change) {
              var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
              attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
              linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
              return histChange;
            }
          
            // Pop all selection events off the end of a history array. Stop at
            // a change event.
            function clearSelectionEvents(array) {
              while (array.length) {
                var last = lst(array);
                if (last.ranges) array.pop();
                else break;
              }
            }
          
            // Find the top change event in the history. Pop off selection
            // events that are in the way.
            function lastChangeEvent(hist, force) {
              if (force) {
                clearSelectionEvents(hist.done);
                return lst(hist.done);
              } else if (hist.done.length && !lst(hist.done).ranges) {
                return lst(hist.done);
              } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
                hist.done.pop();
                return lst(hist.done);
              }
            }
          
            // Register a change in the history. Merges changes that are within
            // a single operation, ore are close together with an origin that
            // allows merging (starting with "+") into a single event.
            function addChangeToHistory(doc, change, selAfter, opId) {
              var hist = doc.history;
              hist.undone.length = 0;
              var time = +new Date, cur;
          
              if ((hist.lastOp == opId ||
                   hist.lastOrigin == change.origin && change.origin &&
                   ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
                    change.origin.charAt(0) == "*")) &&
                  (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
                // Merge this change into the last event
                var last = lst(cur.changes);
                if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
                  // Optimized case for simple insertion -- don't want to add
                  // new changesets for every character typed
                  last.to = changeEnd(change);
                } else {
                  // Add new sub-event
                  cur.changes.push(historyChangeFromChange(doc, change));
                }
              } else {
                // Can not be merged, start a new event.
                var before = lst(hist.done);
                if (!before || !before.ranges)
                  pushSelectionToHistory(doc.sel, hist.done);
                cur = {changes: [historyChangeFromChange(doc, change)],
                       generation: hist.generation};
                hist.done.push(cur);
                while (hist.done.length > hist.undoDepth) {
                  hist.done.shift();
                  if (!hist.done[0].ranges) hist.done.shift();
                }
              }
              hist.done.push(selAfter);
              hist.generation = ++hist.maxGeneration;
              hist.lastModTime = hist.lastSelTime = time;
              hist.lastOp = hist.lastSelOp = opId;
              hist.lastOrigin = hist.lastSelOrigin = change.origin;
          
              if (!last) signal(doc, "historyAdded");
            }
          
            function selectionEventCanBeMerged(doc, origin, prev, sel) {
              var ch = origin.charAt(0);
              return ch == "*" ||
                ch == "+" &&
                prev.ranges.length == sel.ranges.length &&
                prev.somethingSelected() == sel.somethingSelected() &&
                new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
            }
          
            // Called whenever the selection changes, sets the new selection as
            // the pending selection in the history, and pushes the old pending
            // selection into the 'done' array when it was significantly
            // different (in number of selected ranges, emptiness, or time).
            function addSelectionToHistory(doc, sel, opId, options) {
              var hist = doc.history, origin = options && options.origin;
          
              // A new event is started when the previous origin does not match
              // the current, or the origins don't allow matching. Origins
              // starting with * are always merged, those starting with + are
              // merged when similar and close together in time.
              if (opId == hist.lastSelOp ||
                  (origin && hist.lastSelOrigin == origin &&
                   (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
                    selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
                hist.done[hist.done.length - 1] = sel;
              else
                pushSelectionToHistory(sel, hist.done);
          
              hist.lastSelTime = +new Date;
              hist.lastSelOrigin = origin;
              hist.lastSelOp = opId;
              if (options && options.clearRedo !== false)
                clearSelectionEvents(hist.undone);
            }
          
            function pushSelectionToHistory(sel, dest) {
              var top = lst(dest);
              if (!(top && top.ranges && top.equals(sel)))
                dest.push(sel);
            }
          
            // Used to store marked span information in the history.
            function attachLocalSpans(doc, change, from, to) {
              var existing = change["spans_" + doc.id], n = 0;
              doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
                if (line.markedSpans)
                  (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
                ++n;
              });
            }
          
            // When un/re-doing restores text containing marked spans, those
            // that have been explicitly cleared should not be restored.
            function removeClearedSpans(spans) {
              if (!spans) return null;
              for (var i = 0, out; i < spans.length; ++i) {
                if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
                else if (out) out.push(spans[i]);
              }
              return !out ? spans : out.length ? out : null;
            }
          
            // Retrieve and filter the old marked spans stored in a change event.
            function getOldSpans(doc, change) {
              var found = change["spans_" + doc.id];
              if (!found) return null;
              for (var i = 0, nw = []; i < change.text.length; ++i)
                nw.push(removeClearedSpans(found[i]));
              return nw;
            }
          
            // Used both to provide a JSON-safe object in .getHistory, and, when
            // detaching a document, to split the history in two
            function copyHistoryArray(events, newGroup, instantiateSel) {
              for (var i = 0, copy = []; i < events.length; ++i) {
                var event = events[i];
                if (event.ranges) {
                  copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
                  continue;
                }
                var changes = event.changes, newChanges = [];
                copy.push({changes: newChanges});
                for (var j = 0; j < changes.length; ++j) {
                  var change = changes[j], m;
                  newChanges.push({from: change.from, to: change.to, text: change.text});
                  if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
                    if (indexOf(newGroup, Number(m[1])) > -1) {
                      lst(newChanges)[prop] = change[prop];
                      delete change[prop];
                    }
                  }
                }
              }
              return copy;
            }
          
            // Rebasing/resetting history to deal with externally-sourced changes
          
            function rebaseHistSelSingle(pos, from, to, diff) {
              if (to < pos.line) {
                pos.line += diff;
              } else if (from < pos.line) {
                pos.line = from;
                pos.ch = 0;
              }
            }
          
            // Tries to rebase an array of history events given a change in the
            // document. If the change touches the same lines as the event, the
            // event, and everything 'behind' it, is discarded. If the change is
            // before the event, the event's positions are updated. Uses a
            // copy-on-write scheme for the positions, to avoid having to
            // reallocate them all on every rebase, but also avoid problems with
            // shared position objects being unsafely updated.
            function rebaseHistArray(array, from, to, diff) {
              for (var i = 0; i < array.length; ++i) {
                var sub = array[i], ok = true;
                if (sub.ranges) {
                  if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
                  for (var j = 0; j < sub.ranges.length; j++) {
                    rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
                    rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
                  }
                  continue;
                }
                for (var j = 0; j < sub.changes.length; ++j) {
                  var cur = sub.changes[j];
                  if (to < cur.from.line) {
                    cur.from = Pos(cur.from.line + diff, cur.from.ch);
                    cur.to = Pos(cur.to.line + diff, cur.to.ch);
                  } else if (from <= cur.to.line) {
                    ok = false;
                    break;
                  }
                }
                if (!ok) {
                  array.splice(0, i + 1);
                  i = 0;
                }
              }
            }
          
            function rebaseHist(hist, change) {
              var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
              rebaseHistArray(hist.done, from, to, diff);
              rebaseHistArray(hist.undone, from, to, diff);
            }
          
            // EVENT UTILITIES
          
            // Due to the fact that we still support jurassic IE versions, some
            // compatibility wrappers are needed.
          
            var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
              if (e.preventDefault) e.preventDefault();
              else e.returnValue = false;
            };
            var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
              if (e.stopPropagation) e.stopPropagation();
              else e.cancelBubble = true;
            };
            function e_defaultPrevented(e) {
              return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
            }
            var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
          
            function e_target(e) {return e.target || e.srcElement;}
            function e_button(e) {
              var b = e.which;
              if (b == null) {
                if (e.button & 1) b = 1;
                else if (e.button & 2) b = 3;
                else if (e.button & 4) b = 2;
              }
              if (mac && e.ctrlKey && b == 1) b = 3;
              return b;
            }
          
            // EVENT HANDLING
          
            // Lightweight event framework. on/off also work on DOM nodes,
            // registering native DOM handlers.
          
            var on = CodeMirror.on = function(emitter, type, f) {
              if (emitter.addEventListener)
                emitter.addEventListener(type, f, false);
              else if (emitter.attachEvent)
                emitter.attachEvent("on" + type, f);
              else {
                var map = emitter._handlers || (emitter._handlers = {});
                var arr = map[type] || (map[type] = []);
                arr.push(f);
              }
            };
          
            var off = CodeMirror.off = function(emitter, type, f) {
              if (emitter.removeEventListener)
                emitter.removeEventListener(type, f, false);
              else if (emitter.detachEvent)
                emitter.detachEvent("on" + type, f);
              else {
                var arr = emitter._handlers && emitter._handlers[type];
                if (!arr) return;
                for (var i = 0; i < arr.length; ++i)
                  if (arr[i] == f) { arr.splice(i, 1); break; }
              }
            };
          
            var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
              var arr = emitter._handlers && emitter._handlers[type];
              if (!arr) return;
              var args = Array.prototype.slice.call(arguments, 2);
              for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
            };
          
            var orphanDelayedCallbacks = null;
          
            // Often, we want to signal events at a point where we are in the
            // middle of some work, but don't want the handler to start calling
            // other methods on the editor, which might be in an inconsistent
            // state or simply not expect any other events to happen.
            // signalLater looks whether there are any handlers, and schedules
            // them to be executed when the last operation ends, or, if no
            // operation is active, when a timeout fires.
            function signalLater(emitter, type /*, values...*/) {
              var arr = emitter._handlers && emitter._handlers[type];
              if (!arr) return;
              var args = Array.prototype.slice.call(arguments, 2), list;
              if (operationGroup) {
                list = operationGroup.delayedCallbacks;
              } else if (orphanDelayedCallbacks) {
                list = orphanDelayedCallbacks;
              } else {
                list = orphanDelayedCallbacks = [];
                setTimeout(fireOrphanDelayed, 0);
              }
              function bnd(f) {return function(){f.apply(null, args);};};
              for (var i = 0; i < arr.length; ++i)
                list.push(bnd(arr[i]));
            }
          
            function fireOrphanDelayed() {
              var delayed = orphanDelayedCallbacks;
              orphanDelayedCallbacks = null;
              for (var i = 0; i < delayed.length; ++i) delayed[i]();
            }
          
            // The DOM events that CodeMirror handles can be overridden by
            // registering a (non-DOM) handler on the editor for the event name,
            // and preventDefault-ing the event in that handler.
            function signalDOMEvent(cm, e, override) {
              if (typeof e == "string")
                e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
              signal(cm, override || e.type, cm, e);
              return e_defaultPrevented(e) || e.codemirrorIgnore;
            }
          
            function signalCursorActivity(cm) {
              var arr = cm._handlers && cm._handlers.cursorActivity;
              if (!arr) return;
              var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
              for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
                set.push(arr[i]);
            }
          
            function hasHandler(emitter, type) {
              var arr = emitter._handlers && emitter._handlers[type];
              return arr && arr.length > 0;
            }
          
            // Add on and off methods to a constructor's prototype, to make
            // registering events on such objects more convenient.
            function eventMixin(ctor) {
              ctor.prototype.on = function(type, f) {on(this, type, f);};
              ctor.prototype.off = function(type, f) {off(this, type, f);};
            }
          
            // MISC UTILITIES
          
            // Number of pixels added to scroller and sizer to hide scrollbar
            var scrollerGap = 30;
          
            // Returned or thrown by various protocols to signal 'I'm not
            // handling this'.
            var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
          
            // Reused option objects for setSelection & friends
            var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
          
            function Delayed() {this.id = null;}
            Delayed.prototype.set = function(ms, f) {
              clearTimeout(this.id);
              this.id = setTimeout(f, ms);
            };
          
            // Counts the column offset in a string, taking tabs into account.
            // Used mostly to find indentation.
            var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
              if (end == null) {
                end = string.search(/[^\s\u00a0]/);
                if (end == -1) end = string.length;
              }
              for (var i = startIndex || 0, n = startValue || 0;;) {
                var nextTab = string.indexOf("\t", i);
                if (nextTab < 0 || nextTab >= end)
                  return n + (end - i);
                n += nextTab - i;
                n += tabSize - (n % tabSize);
                i = nextTab + 1;
              }
            };
          
            // The inverse of countColumn -- find the offset that corresponds to
            // a particular column.
            function findColumn(string, goal, tabSize) {
              for (var pos = 0, col = 0;;) {
                var nextTab = string.indexOf("\t", pos);
                if (nextTab == -1) nextTab = string.length;
                var skipped = nextTab - pos;
                if (nextTab == string.length || col + skipped >= goal)
                  return pos + Math.min(skipped, goal - col);
                col += nextTab - pos;
                col += tabSize - (col % tabSize);
                pos = nextTab + 1;
                if (col >= goal) return pos;
              }
            }
          
            var spaceStrs = [""];
            function spaceStr(n) {
              while (spaceStrs.length <= n)
                spaceStrs.push(lst(spaceStrs) + " ");
              return spaceStrs[n];
            }
          
            function lst(arr) { return arr[arr.length-1]; }
          
            var selectInput = function(node) { node.select(); };
            if (ios) // Mobile Safari apparently has a bug where select() is broken.
              selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
            else if (ie) // Suppress mysterious IE10 errors
              selectInput = function(node) { try { node.select(); } catch(_e) {} };
          
            function indexOf(array, elt) {
              for (var i = 0; i < array.length; ++i)
                if (array[i] == elt) return i;
              return -1;
            }
            function map(array, f) {
              var out = [];
              for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
              return out;
            }
          
            function nothing() {}
          
            function createObj(base, props) {
              var inst;
              if (Object.create) {
                inst = Object.create(base);
              } else {
                nothing.prototype = base;
                inst = new nothing();
              }
              if (props) copyObj(props, inst);
              return inst;
            };
          
            function copyObj(obj, target, overwrite) {
              if (!target) target = {};
              for (var prop in obj)
                if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
                  target[prop] = obj[prop];
              return target;
            }
          
            function bind(f) {
              var args = Array.prototype.slice.call(arguments, 1);
              return function(){return f.apply(null, args);};
            }
          
            var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
            var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
              return /\w/.test(ch) || ch > "\x80" &&
                (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
            };
            function isWordChar(ch, helper) {
              if (!helper) return isWordCharBasic(ch);
              if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
              return helper.test(ch);
            }
          
            function isEmpty(obj) {
              for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
              return true;
            }
          
            // Extending unicode characters. A series of a non-extending char +
            // any number of extending chars is treated as a single unit as far
            // as editing and measuring is concerned. This is not fully correct,
            // since some scripts/fonts/browsers also treat other configurations
            // of code points as a group.
            var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
            function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
          
            // DOM UTILITIES
          
            function elt(tag, content, className, style) {
              var e = document.createElement(tag);
              if (className) e.className = className;
              if (style) e.style.cssText = style;
              if (typeof content == "string") e.appendChild(document.createTextNode(content));
              else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
              return e;
            }
          
            var range;
            if (document.createRange) range = function(node, start, end, endNode) {
              var r = document.createRange();
              r.setEnd(endNode || node, end);
              r.setStart(node, start);
              return r;
            };
            else range = function(node, start, end) {
              var r = document.body.createTextRange();
              try { r.moveToElementText(node.parentNode); }
              catch(e) { return r; }
              r.collapse(true);
              r.moveEnd("character", end);
              r.moveStart("character", start);
              return r;
            };
          
            function removeChildren(e) {
              for (var count = e.childNodes.length; count > 0; --count)
                e.removeChild(e.firstChild);
              return e;
            }
          
            function removeChildrenAndAdd(parent, e) {
              return removeChildren(parent).appendChild(e);
            }
          
            var contains = CodeMirror.contains = function(parent, child) {
              if (child.nodeType == 3) // Android browser always returns false when child is a textnode
                child = child.parentNode;
              if (parent.contains)
                return parent.contains(child);
              do {
                if (child.nodeType == 11) child = child.host;
                if (child == parent) return true;
              } while (child = child.parentNode);
            };
          
            function activeElt() { return document.activeElement; }
            // Older versions of IE throws unspecified error when touching
            // document.activeElement in some cases (during loading, in iframe)
            if (ie && ie_version < 11) activeElt = function() {
              try { return document.activeElement; }
              catch(e) { return document.body; }
            };
          
            function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
            var rmClass = CodeMirror.rmClass = function(node, cls) {
              var current = node.className;
              var match = classTest(cls).exec(current);
              if (match) {
                var after = current.slice(match.index + match[0].length);
                node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
              }
            };
            var addClass = CodeMirror.addClass = function(node, cls) {
              var current = node.className;
              if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
            };
            function joinClasses(a, b) {
              var as = a.split(" ");
              for (var i = 0; i < as.length; i++)
                if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
              return b;
            }
          
            // WINDOW-WIDE EVENTS
          
            // These must be handled carefully, because naively registering a
            // handler for each editor will cause the editors to never be
            // garbage collected.
          
            function forEachCodeMirror(f) {
              if (!document.body.getElementsByClassName) return;
              var byClass = document.body.getElementsByClassName("CodeMirror");
              for (var i = 0; i < byClass.length; i++) {
                var cm = byClass[i].CodeMirror;
                if (cm) f(cm);
              }
            }
          
            var globalsRegistered = false;
            function ensureGlobalHandlers() {
              if (globalsRegistered) return;
              registerGlobalHandlers();
              globalsRegistered = true;
            }
            function registerGlobalHandlers() {
              // When the window resizes, we need to refresh active editors.
              var resizeTimer;
              on(window, "resize", function() {
                if (resizeTimer == null) resizeTimer = setTimeout(function() {
                  resizeTimer = null;
                  forEachCodeMirror(onResize);
                }, 100);
              });
              // When the window loses focus, we want to show the editor as blurred
              on(window, "blur", function() {
                forEachCodeMirror(onBlur);
              });
            }
          
            // FEATURE DETECTION
          
            // Detect drag-and-drop
            var dragAndDrop = function() {
              // There is *some* kind of drag-and-drop support in IE6-8, but I
              // couldn't get it to work yet.
              if (ie && ie_version < 9) return false;
              var div = elt('div');
              return "draggable" in div || "dragDrop" in div;
            }();
          
            var zwspSupported;
            function zeroWidthElement(measure) {
              if (zwspSupported == null) {
                var test = elt("span", "\u200b");
                removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
                if (measure.firstChild.offsetHeight != 0)
                  zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
              }
              var node = zwspSupported ? elt("span", "\u200b") :
                elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
              node.setAttribute("cm-text", "");
              return node;
            }
          
            // Feature-detect IE's crummy client rect reporting for bidi text
            var badBidiRects;
            function hasBadBidiRects(measure) {
              if (badBidiRects != null) return badBidiRects;
              var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
              var r0 = range(txt, 0, 1).getBoundingClientRect();
              if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
              var r1 = range(txt, 1, 2).getBoundingClientRect();
              return badBidiRects = (r1.right - r0.right < 3);
            }
          
            // See if "".split is the broken IE version, if so, provide an
            // alternative way to split lines.
            var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
              var pos = 0, result = [], l = string.length;
              while (pos <= l) {
                var nl = string.indexOf("\n", pos);
                if (nl == -1) nl = string.length;
                var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
                var rt = line.indexOf("\r");
                if (rt != -1) {
                  result.push(line.slice(0, rt));
                  pos += rt + 1;
                } else {
                  result.push(line);
                  pos = nl + 1;
                }
              }
              return result;
            } : function(string){return string.split(/\r\n?|\n/);};
          
            var hasSelection = window.getSelection ? function(te) {
              try { return te.selectionStart != te.selectionEnd; }
              catch(e) { return false; }
            } : function(te) {
              try {var range = te.ownerDocument.selection.createRange();}
              catch(e) {}
              if (!range || range.parentElement() != te) return false;
              return range.compareEndPoints("StartToEnd", range) != 0;
            };
          
            var hasCopyEvent = (function() {
              var e = elt("div");
              if ("oncopy" in e) return true;
              e.setAttribute("oncopy", "return;");
              return typeof e.oncopy == "function";
            })();
          
            var badZoomedRects = null;
            function hasBadZoomedRects(measure) {
              if (badZoomedRects != null) return badZoomedRects;
              var node = removeChildrenAndAdd(measure, elt("span", "x"));
              var normal = node.getBoundingClientRect();
              var fromRange = range(node, 0, 1).getBoundingClientRect();
              return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
            }
          
            // KEY NAMES
          
            var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
                            19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
                            36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
                            46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
                            173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
                            221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
                            63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
            CodeMirror.keyNames = keyNames;
            (function() {
              // Number keys
              for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
              // Alphabetic keys
              for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
              // Function keys
              for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
            })();
          
            // BIDI HELPERS
          
            function iterateBidiSections(order, from, to, f) {
              if (!order) return f(from, to, "ltr");
              var found = false;
              for (var i = 0; i < order.length; ++i) {
                var part = order[i];
                if (part.from < to && part.to > from || from == to && part.to == from) {
                  f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
                  found = true;
                }
              }
              if (!found) f(from, to, "ltr");
            }
          
            function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
            function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
          
            function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
            function lineRight(line) {
              var order = getOrder(line);
              if (!order) return line.text.length;
              return bidiRight(lst(order));
            }
          
            function lineStart(cm, lineN) {
              var line = getLine(cm.doc, lineN);
              var visual = visualLine(line);
              if (visual != line) lineN = lineNo(visual);
              var order = getOrder(visual);
              var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
              return Pos(lineN, ch);
            }
            function lineEnd(cm, lineN) {
              var merged, line = getLine(cm.doc, lineN);
              while (merged = collapsedSpanAtEnd(line)) {
                line = merged.find(1, true).line;
                lineN = null;
              }
              var order = getOrder(line);
              var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
              return Pos(lineN == null ? lineNo(line) : lineN, ch);
            }
            function lineStartSmart(cm, pos) {
              var start = lineStart(cm, pos.line);
              var line = getLine(cm.doc, start.line);
              var order = getOrder(line);
              if (!order || order[0].level == 0) {
                var firstNonWS = Math.max(0, line.text.search(/\S/));
                var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
                return Pos(start.line, inWS ? 0 : firstNonWS);
              }
              return start;
            }
          
            function compareBidiLevel(order, a, b) {
              var linedir = order[0].level;
              if (a == linedir) return true;
              if (b == linedir) return false;
              return a < b;
            }
            var bidiOther;
            function getBidiPartAt(order, pos) {
              bidiOther = null;
              for (var i = 0, found; i < order.length; ++i) {
                var cur = order[i];
                if (cur.from < pos && cur.to > pos) return i;
                if ((cur.from == pos || cur.to == pos)) {
                  if (found == null) {
                    found = i;
                  } else if (compareBidiLevel(order, cur.level, order[found].level)) {
                    if (cur.from != cur.to) bidiOther = found;
                    return i;
                  } else {
                    if (cur.from != cur.to) bidiOther = i;
                    return found;
                  }
                }
              }
              return found;
            }
          
            function moveInLine(line, pos, dir, byUnit) {
              if (!byUnit) return pos + dir;
              do pos += dir;
              while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
              return pos;
            }
          
            // This is needed in order to move 'visually' through bi-directional
            // text -- i.e., pressing left should make the cursor go left, even
            // when in RTL text. The tricky part is the 'jumps', where RTL and
            // LTR text touch each other. This often requires the cursor offset
            // to move more than one unit, in order to visually move one unit.
            function moveVisually(line, start, dir, byUnit) {
              var bidi = getOrder(line);
              if (!bidi) return moveLogically(line, start, dir, byUnit);
              var pos = getBidiPartAt(bidi, start), part = bidi[pos];
              var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
          
              for (;;) {
                if (target > part.from && target < part.to) return target;
                if (target == part.from || target == part.to) {
                  if (getBidiPartAt(bidi, target) == pos) return target;
                  part = bidi[pos += dir];
                  return (dir > 0) == part.level % 2 ? part.to : part.from;
                } else {
                  part = bidi[pos += dir];
                  if (!part) return null;
                  if ((dir > 0) == part.level % 2)
                    target = moveInLine(line, part.to, -1, byUnit);
                  else
                    target = moveInLine(line, part.from, 1, byUnit);
                }
              }
            }
          
            function moveLogically(line, start, dir, byUnit) {
              var target = start + dir;
              if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
              return target < 0 || target > line.text.length ? null : target;
            }
          
            // Bidirectional ordering algorithm
            // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
            // that this (partially) implements.
          
            // One-char codes used for character types:
            // L (L):   Left-to-Right
            // R (R):   Right-to-Left
            // r (AL):  Right-to-Left Arabic
            // 1 (EN):  European Number
            // + (ES):  European Number Separator
            // % (ET):  European Number Terminator
            // n (AN):  Arabic Number
            // , (CS):  Common Number Separator
            // m (NSM): Non-Spacing Mark
            // b (BN):  Boundary Neutral
            // s (B):   Paragraph Separator
            // t (S):   Segment Separator
            // w (WS):  Whitespace
            // N (ON):  Other Neutrals
          
            // Returns null if characters are ordered as they appear
            // (left-to-right), or an array of sections ({from, to, level}
            // objects) in the order in which they occur visually.
            var bidiOrdering = (function() {
              // Character types for codepoints 0 to 0xff
              var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
              // Character types for codepoints 0x600 to 0x6ff
              var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
              function charType(code) {
                if (code <= 0xf7) return lowTypes.charAt(code);
                else if (0x590 <= code && code <= 0x5f4) return "R";
                else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
                else if (0x6ee <= code && code <= 0x8ac) return "r";
                else if (0x2000 <= code && code <= 0x200b) return "w";
                else if (code == 0x200c) return "b";
                else return "L";
              }
          
              var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
              var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
              // Browsers seem to always treat the boundaries of block elements as being L.
              var outerType = "L";
          
              function BidiSpan(level, from, to) {
                this.level = level;
                this.from = from; this.to = to;
              }
          
              return function(str) {
                if (!bidiRE.test(str)) return false;
                var len = str.length, types = [];
                for (var i = 0, type; i < len; ++i)
                  types.push(type = charType(str.charCodeAt(i)));
          
                // W1. Examine each non-spacing mark (NSM) in the level run, and
                // change the type of the NSM to the type of the previous
                // character. If the NSM is at the start of the level run, it will
                // get the type of sor.
                for (var i = 0, prev = outerType; i < len; ++i) {
                  var type = types[i];
                  if (type == "m") types[i] = prev;
                  else prev = type;
                }
          
                // W2. Search backwards from each instance of a European number
                // until the first strong type (R, L, AL, or sor) is found. If an
                // AL is found, change the type of the European number to Arabic
                // number.
                // W3. Change all ALs to R.
                for (var i = 0, cur = outerType; i < len; ++i) {
                  var type = types[i];
                  if (type == "1" && cur == "r") types[i] = "n";
                  else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
                }
          
                // W4. A single European separator between two European numbers
                // changes to a European number. A single common separator between
                // two numbers of the same type changes to that type.
                for (var i = 1, prev = types[0]; i < len - 1; ++i) {
                  var type = types[i];
                  if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
                  else if (type == "," && prev == types[i+1] &&
                           (prev == "1" || prev == "n")) types[i] = prev;
                  prev = type;
                }
          
                // W5. A sequence of European terminators adjacent to European
                // numbers changes to all European numbers.
                // W6. Otherwise, separators and terminators change to Other
                // Neutral.
                for (var i = 0; i < len; ++i) {
                  var type = types[i];
                  if (type == ",") types[i] = "N";
                  else if (type == "%") {
                    for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
                    var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
                    for (var j = i; j < end; ++j) types[j] = replace;
                    i = end - 1;
                  }
                }
          
                // W7. Search backwards from each instance of a European number
                // until the first strong type (R, L, or sor) is found. If an L is
                // found, then change the type of the European number to L.
                for (var i = 0, cur = outerType; i < len; ++i) {
                  var type = types[i];
                  if (cur == "L" && type == "1") types[i] = "L";
                  else if (isStrong.test(type)) cur = type;
                }
          
                // N1. A sequence of neutrals takes the direction of the
                // surrounding strong text if the text on both sides has the same
                // direction. European and Arabic numbers act as if they were R in
                // terms of their influence on neutrals. Start-of-level-run (sor)
                // and end-of-level-run (eor) are used at level run boundaries.
                // N2. Any remaining neutrals take the embedding direction.
                for (var i = 0; i < len; ++i) {
                  if (isNeutral.test(types[i])) {
                    for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
                    var before = (i ? types[i-1] : outerType) == "L";
                    var after = (end < len ? types[end] : outerType) == "L";
                    var replace = before || after ? "L" : "R";
                    for (var j = i; j < end; ++j) types[j] = replace;
                    i = end - 1;
                  }
                }
          
                // Here we depart from the documented algorithm, in order to avoid
                // building up an actual levels array. Since there are only three
                // levels (0, 1, 2) in an implementation that doesn't take
                // explicit embedding into account, we can build up the order on
                // the fly, without following the level-based algorithm.
                var order = [], m;
                for (var i = 0; i < len;) {
                  if (countsAsLeft.test(types[i])) {
                    var start = i;
                    for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
                    order.push(new BidiSpan(0, start, i));
                  } else {
                    var pos = i, at = order.length;
                    for (++i; i < len && types[i] != "L"; ++i) {}
                    for (var j = pos; j < i;) {
                      if (countsAsNum.test(types[j])) {
                        if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
                        var nstart = j;
                        for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
                        order.splice(at, 0, new BidiSpan(2, nstart, j));
                        pos = j;
                      } else ++j;
                    }
                    if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
                  }
                }
                if (order[0].level == 1 && (m = str.match(/^\s+/))) {
                  order[0].from = m[0].length;
                  order.unshift(new BidiSpan(0, 0, m[0].length));
                }
                if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
                  lst(order).to -= m[0].length;
                  order.push(new BidiSpan(0, len - m[0].length, len));
                }
                if (order[0].level != lst(order).level)
                  order.push(new BidiSpan(order[0].level, len, len));
          
                return order;
              };
            })();
          
            // THE END
          
            CodeMirror.version = "5.0.1";
          
            return CodeMirror;
          });
          
      • mode
        • apl
          • apl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("apl", function() {
              var builtInOps = {
                ".": "innerProduct",
                "\\": "scan",
                "/": "reduce",
                "⌿": "reduce1Axis",
                "⍀": "scan1Axis",
                "¨": "each",
                "⍣": "power"
              };
              var builtInFuncs = {
                "+": ["conjugate", "add"],
                "−": ["negate", "subtract"],
                "×": ["signOf", "multiply"],
                "÷": ["reciprocal", "divide"],
                "⌈": ["ceiling", "greaterOf"],
                "⌊": ["floor", "lesserOf"],
                "∣": ["absolute", "residue"],
                "⍳": ["indexGenerate", "indexOf"],
                "?": ["roll", "deal"],
                "⋆": ["exponentiate", "toThePowerOf"],
                "⍟": ["naturalLog", "logToTheBase"],
                "○": ["piTimes", "circularFuncs"],
                "!": ["factorial", "binomial"],
                "⌹": ["matrixInverse", "matrixDivide"],
                "<": [null, "lessThan"],
                "≤": [null, "lessThanOrEqual"],
                "=": [null, "equals"],
                ">": [null, "greaterThan"],
                "≥": [null, "greaterThanOrEqual"],
                "≠": [null, "notEqual"],
                "≡": ["depth", "match"],
                "≢": [null, "notMatch"],
                "∈": ["enlist", "membership"],
                "⍷": [null, "find"],
                "∪": ["unique", "union"],
                "∩": [null, "intersection"],
                "∼": ["not", "without"],
                "∨": [null, "or"],
                "∧": [null, "and"],
                "⍱": [null, "nor"],
                "⍲": [null, "nand"],
                "⍴": ["shapeOf", "reshape"],
                ",": ["ravel", "catenate"],
                "⍪": [null, "firstAxisCatenate"],
                "⌽": ["reverse", "rotate"],
                "⊖": ["axis1Reverse", "axis1Rotate"],
                "⍉": ["transpose", null],
                "↑": ["first", "take"],
                "↓": [null, "drop"],
                "⊂": ["enclose", "partitionWithAxis"],
                "⊃": ["diclose", "pick"],
                "⌷": [null, "index"],
                "⍋": ["gradeUp", null],
                "⍒": ["gradeDown", null],
                "⊤": ["encode", null],
                "⊥": ["decode", null],
                "⍕": ["format", "formatByExample"],
                "⍎": ["execute", null],
                "⊣": ["stop", "left"],
                "⊢": ["pass", "right"]
              };
            
              var isOperator = /[\.\/⌿⍀¨⍣]/;
              var isNiladic = /⍬/;
              var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;
              var isArrow = /←/;
              var isComment = /[⍝#].*$/;
            
              var stringEater = function(type) {
                var prev;
                prev = false;
                return function(c) {
                  prev = c;
                  if (c === type) {
                    return prev === "\\";
                  }
                  return true;
                };
              };
              return {
                startState: function() {
                  return {
                    prev: false,
                    func: false,
                    op: false,
                    string: false,
                    escape: false
                  };
                },
                token: function(stream, state) {
                  var ch, funcName, word;
                  if (stream.eatSpace()) {
                    return null;
                  }
                  ch = stream.next();
                  if (ch === '"' || ch === "'") {
                    stream.eatWhile(stringEater(ch));
                    stream.next();
                    state.prev = true;
                    return "string";
                  }
                  if (/[\[{\(]/.test(ch)) {
                    state.prev = false;
                    return null;
                  }
                  if (/[\]}\)]/.test(ch)) {
                    state.prev = true;
                    return null;
                  }
                  if (isNiladic.test(ch)) {
                    state.prev = false;
                    return "niladic";
                  }
                  if (/[¯\d]/.test(ch)) {
                    if (state.func) {
                      state.func = false;
                      state.prev = false;
                    } else {
                      state.prev = true;
                    }
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  if (isOperator.test(ch)) {
                    return "operator apl-" + builtInOps[ch];
                  }
                  if (isArrow.test(ch)) {
                    return "apl-arrow";
                  }
                  if (isFunction.test(ch)) {
                    funcName = "apl-";
                    if (builtInFuncs[ch] != null) {
                      if (state.prev) {
                        funcName += builtInFuncs[ch][1];
                      } else {
                        funcName += builtInFuncs[ch][0];
                      }
                    }
                    state.func = true;
                    state.prev = false;
                    return "function " + funcName;
                  }
                  if (isComment.test(ch)) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (ch === "∘" && stream.peek() === ".") {
                    stream.next();
                    return "function jot-dot";
                  }
                  stream.eatWhile(/[\w\$_]/);
                  word = stream.current();
                  state.prev = true;
                  return "keyword";
                }
              };
            });
            
            CodeMirror.defineMIME("text/apl", "apl");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: APL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="./apl.js"></script>
            <style>
            	.CodeMirror { border: 2px inset #dee; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">APL</a>
              </ul>
            </div>
            
            <article>
            <h2>APL mode</h2>
            <form><textarea id="code" name="code">
            ⍝ Conway's game of life
            
            ⍝ This example was inspired by the impressive demo at
            ⍝ http://www.youtube.com/watch?v=a9xAKttWgP4
            
            ⍝ Create a matrix:
            ⍝     0 1 1
            ⍝     1 1 0
            ⍝     0 1 0
            creature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7   ⍝ Original creature from demo
            creature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8   ⍝ Glider
            
            ⍝ Place the creature on a larger board, near the centre
            board ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature
            
            ⍝ A function to move from one generation to the next
            life ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}
            
            ⍝ Compute n-th generation and format it as a
            ⍝ character matrix
            gen ← {' #'[(life ⍣ ⍵) board]}
            
            ⍝ Show first three generations
            (gen 1) (gen 2) (gen 3)
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/apl"
                  });
                </script>
            
                <p>Simple mode that tries to handle APL as well as it can.</p>
                <p>It attempts to label functions/operators based upon
                monadic/dyadic usage (but this is far from fully fleshed out).
                This means there are meaningful classnames so hover states can
                have popups etc.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>
              </article>
            
        • asterisk
          • asterisk.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             * =====================================================================================
             *
             *       Filename:  mode/asterisk/asterisk.js
             *
             *    Description:  CodeMirror mode for Asterisk dialplan
             *
             *        Created:  05/17/2012 09:20:25 PM
             *       Revision:  none
             *
             *         Author:  Stas Kobzar (stas@modulis.ca),
             *        Company:  Modulis.ca Inc.
             *
             * =====================================================================================
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("asterisk", function() {
              var atoms    = ["exten", "same", "include","ignorepat","switch"],
                  dpcmd    = ["#include","#exec"],
                  apps     = [
                              "addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi",
                              "alarmreceiver","amd","answer","authenticate","background","backgrounddetect",
                              "bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent",
                              "changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge",
                              "congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge",
                              "dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility",
                              "datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa",
                              "dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy",
                              "externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif",
                              "goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete",
                              "ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus",
                              "jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme",
                              "meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete",
                              "minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode",
                              "mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish",
                              "originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce",
                              "parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones",
                              "privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten",
                              "readfile","receivefax","receivefax","receivefax","record","removequeuemember",
                              "resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun",
                              "saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax",
                              "sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags",
                              "setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel",
                              "slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground",
                              "speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound",
                              "speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor",
                              "stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec",
                              "trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate",
                              "vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring",
                              "waitforsilence","waitmusiconhold","waituntil","while","zapateller"
                             ];
            
              function basicToken(stream,state){
                var cur = '';
                var ch  = '';
                ch = stream.next();
                // comment
                if(ch == ";") {
                  stream.skipToEnd();
                  return "comment";
                }
                // context
                if(ch == '[') {
                  stream.skipTo(']');
                  stream.eat(']');
                  return "header";
                }
                // string
                if(ch == '"') {
                  stream.skipTo('"');
                  return "string";
                }
                if(ch == "'") {
                  stream.skipTo("'");
                  return "string-2";
                }
                // dialplan commands
                if(ch == '#') {
                  stream.eatWhile(/\w/);
                  cur = stream.current();
                  if(dpcmd.indexOf(cur) !== -1) {
                    stream.skipToEnd();
                    return "strong";
                  }
                }
                // application args
                if(ch == '$'){
                  var ch1 = stream.peek();
                  if(ch1 == '{'){
                    stream.skipTo('}');
                    stream.eat('}');
                    return "variable-3";
                  }
                }
                // extension
                stream.eatWhile(/\w/);
                cur = stream.current();
                if(atoms.indexOf(cur) !== -1) {
                  state.extenStart = true;
                  switch(cur) {
                    case 'same': state.extenSame = true; break;
                    case 'include':
                    case 'switch':
                    case 'ignorepat':
                      state.extenInclude = true;break;
                    default:break;
                  }
                  return "atom";
                }
              }
            
              return {
                startState: function() {
                  return {
                    extenStart: false,
                    extenSame:  false,
                    extenInclude: false,
                    extenExten: false,
                    extenPriority: false,
                    extenApplication: false
                  };
                },
                token: function(stream, state) {
            
                  var cur = '';
                  var ch  = '';
                  if(stream.eatSpace()) return null;
                  // extension started
                  if(state.extenStart){
                    stream.eatWhile(/[^\s]/);
                    cur = stream.current();
                    if(/^=>?$/.test(cur)){
                      state.extenExten = true;
                      state.extenStart = false;
                      return "strong";
                    } else {
                      state.extenStart = false;
                      stream.skipToEnd();
                      return "error";
                    }
                  } else if(state.extenExten) {
                    // set exten and priority
                    state.extenExten = false;
                    state.extenPriority = true;
                    stream.eatWhile(/[^,]/);
                    if(state.extenInclude) {
                      stream.skipToEnd();
                      state.extenPriority = false;
                      state.extenInclude = false;
                    }
                    if(state.extenSame) {
                      state.extenPriority = false;
                      state.extenSame = false;
                      state.extenApplication = true;
                    }
                    return "tag";
                  } else if(state.extenPriority) {
                    state.extenPriority = false;
                    state.extenApplication = true;
                    ch = stream.next(); // get comma
                    if(state.extenSame) return null;
                    stream.eatWhile(/[^,]/);
                    return "number";
                  } else if(state.extenApplication) {
                    stream.eatWhile(/,/);
                    cur = stream.current();
                    if(cur === ',') return null;
                    stream.eatWhile(/\w/);
                    cur = stream.current().toLowerCase();
                    state.extenApplication = false;
                    if(apps.indexOf(cur) !== -1){
                      return "def strong";
                    }
                  } else{
                    return basicToken(stream,state);
                  }
            
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-asterisk", "asterisk");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Asterisk dialplan mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="asterisk.js"></script>
            <style>
                  .CodeMirror {border: 1px solid #999;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Asterisk dialplan</a>
              </ul>
            </div>
            
            <article>
            <h2>Asterisk dialplan mode</h2>
            <form><textarea id="code" name="code">
            ; extensions.conf - the Asterisk dial plan
            ;
            
            [general]
            ;
            ; If static is set to no, or omitted, then the pbx_config will rewrite
            ; this file when extensions are modified.  Remember that all comments
            ; made in the file will be lost when that happens.
            static=yes
            
            #include "/etc/asterisk/additional_general.conf
            
            [iaxprovider]
            switch => IAX2/user:[key]@myserver/mycontext
            
            [dynamic]
            #exec /usr/bin/dynamic-peers.pl
            
            [trunkint]
            ;
            ; International long distance through trunk
            ;
            exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
            exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})
            
            [local]
            ;
            ; Master context for local, toll-free, and iaxtel calls only
            ;
            ignorepat => 9
            include => default
            
            [demo]
            include => stdexten
            ;
            ; We start with what to do when a call first comes in.
            ;
            exten => s,1,Wait(1)			; Wait a second, just for fun
            same  => n,Answer			; Answer the line
            same  => n,Set(TIMEOUT(digit)=5)	; Set Digit Timeout to 5 seconds
            same  => n,Set(TIMEOUT(response)=10)	; Set Response Timeout to 10 seconds
            same  => n(restart),BackGround(demo-congrats)	; Play a congratulatory message
            same  => n(instruct),BackGround(demo-instruct)	; Play some instructions
            same  => n,WaitExten			; Wait for an extension to be dialed.
            
            exten => 2,1,BackGround(demo-moreinfo)	; Give some more information.
            exten => 2,n,Goto(s,instruct)
            
            exten => 3,1,Set(LANGUAGE()=fr)		; Set language to french
            exten => 3,n,Goto(s,restart)		; Start with the congratulations
            
            exten => 1000,1,Goto(default,s,1)
            ;
            ; We also create an example user, 1234, who is on the console and has
            ; voicemail, etc.
            ;
            exten => 1234,1,Playback(transfer,skip)		; "Please hold while..."
            					; (but skip if channel is not up)
            exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
            exten => 1234,n,Goto(default,s,1)		; exited Voicemail
            
            exten => 1235,1,Voicemail(1234,u)		; Right to voicemail
            
            exten => 1236,1,Dial(Console/dsp)		; Ring forever
            exten => 1236,n,Voicemail(1234,b)		; Unless busy
            
            ;
            ; # for when they're done with the demo
            ;
            exten => #,1,Playback(demo-thanks)	; "Thanks for trying the demo"
            exten => #,n,Hangup			; Hang them up.
            
            ;
            ; A timeout and "invalid extension rule"
            ;
            exten => t,1,Goto(#,1)			; If they take too long, give up
            exten => i,1,Playback(invalid)		; "That's not valid, try again"
            
            ;
            ; Create an extension, 500, for dialing the
            ; Asterisk demo.
            ;
            exten => 500,1,Playback(demo-abouttotry); Let them know what's going on
            exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default)	; Call the Asterisk demo
            exten => 500,n,Playback(demo-nogo)	; Couldn't connect to the demo site
            exten => 500,n,Goto(s,6)		; Return to the start over message.
            
            ;
            ; Create an extension, 600, for evaluating echo latency.
            ;
            exten => 600,1,Playback(demo-echotest)	; Let them know what's going on
            exten => 600,n,Echo			; Do the echo test
            exten => 600,n,Playback(demo-echodone)	; Let them know it's over
            exten => 600,n,Goto(s,6)		; Start over
            
            ;
            ;	You can use the Macro Page to intercom a individual user
            exten => 76245,1,Macro(page,SIP/Grandstream1)
            ; or if your peernames are the same as extensions
            exten => _7XXX,1,Macro(page,SIP/${EXTEN})
            ;
            ;
            ; System Wide Page at extension 7999
            ;
            exten => 7999,1,Set(TIMEOUT(absolute)=60)
            exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
            
            ; Give voicemail at extension 8500
            ;
            exten => 8500,1,VoicemailMain
            exten => 8500,n,Goto(s,6)
            
                </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-asterisk",
                    matchBrackets: true,
                    lineNumber: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-asterisk</code>.</p>
            
              </article>
            
        • clike
          • clike.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("clike", function(config, parserConfig) {
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  dontAlignCalls = parserConfig.dontAlignCalls,
                  keywords = parserConfig.keywords || {},
                  builtin = parserConfig.builtin || {},
                  blockKeywords = parserConfig.blockKeywords || {},
                  atoms = parserConfig.atoms || {},
                  hooks = parserConfig.hooks || {},
                  multiLineStrings = parserConfig.multiLineStrings,
                  indentStatements = parserConfig.indentStatements !== false;
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                if (state.context && state.context.type == "statement")
                  indent = state.context.indented;
                return state.context = new Context(indent, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (indentStatements &&
                           (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
                            (ctx.type == "statement" && curPunc == "newstatement")))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
                  else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//",
                fold: "brace"
              };
            });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
                "double static else struct entry switch extern typedef float union for unsigned " +
                "goto while enum void const signed volatile";
            
              function cppHook(stream, state) {
                if (!state.startOfLine) return false;
                for (;;) {
                  if (stream.skipTo("\\")) {
                    stream.next();
                    if (stream.eol()) {
                      state.tokenize = cppHook;
                      break;
                    }
                  } else {
                    stream.skipToEnd();
                    state.tokenize = null;
                    break;
                  }
                }
                return "meta";
              }
            
              function cpp11StringHook(stream, state) {
                stream.backUp(1);
                // Raw strings.
                if (stream.match(/(R|u8R|uR|UR|LR)/)) {
                  var match = stream.match(/"([^\s\\()]{0,16})\(/);
                  if (!match) {
                    return false;
                  }
                  state.cpp11RawStringDelim = match[1];
                  state.tokenize = tokenRawString;
                  return tokenRawString(stream, state);
                }
                // Unicode strings/chars.
                if (stream.match(/(u8|u|U|L)/)) {
                  if (stream.match(/["']/, /* eat */ false)) {
                    return "string";
                  }
                  return false;
                }
                // Ignore this hook.
                stream.next();
                return false;
              }
            
              // C#-style strings where "" escapes a quote.
              function tokenAtString(stream, state) {
                var next;
                while ((next = stream.next()) != null) {
                  if (next == '"' && !stream.eat('"')) {
                    state.tokenize = null;
                    break;
                  }
                }
                return "string";
              }
            
              // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
              // <delim> can be a string up to 16 characters long.
              function tokenRawString(stream, state) {
                // Escape characters that have special regex meanings.
                var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
                var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
                if (match)
                  state.tokenize = null;
                else
                  stream.skipToEnd();
                return "string";
              }
            
              function def(mimes, mode) {
                if (typeof mimes == "string") mimes = [mimes];
                var words = [];
                function add(obj) {
                  if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
                    words.push(prop);
                }
                add(mode.keywords);
                add(mode.builtin);
                add(mode.atoms);
                if (words.length) {
                  mode.helperType = mimes[0];
                  CodeMirror.registerHelper("hintWords", mimes[0], words);
                }
            
                for (var i = 0; i < mimes.length; ++i)
                  CodeMirror.defineMIME(mimes[i], mode);
              }
            
              def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
                name: "clike",
                keywords: words(cKeywords),
                blockKeywords: words("case do else for if switch while struct"),
                atoms: words("null"),
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def(["text/x-c++src", "text/x-c++hdr"], {
                name: "clike",
                keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
                                "static_cast typeid catch operator template typename class friend private " +
                                "this using const_cast inline public throw virtual delete mutable protected " +
                                "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
                                "static_assert override"),
                blockKeywords: words("catch class do else finally for if struct switch try while"),
                atoms: words("true false null"),
                hooks: {
                  "#": cppHook,
                  "u": cpp11StringHook,
                  "U": cpp11StringHook,
                  "L": cpp11StringHook,
                  "R": cpp11StringHook
                },
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-java", {
                name: "clike",
                keywords: words("abstract assert boolean break byte case catch char class const continue default " +
                                "do double else enum extends final finally float for goto if implements import " +
                                "instanceof int interface long native new package private protected public " +
                                "return short static strictfp super switch synchronized this throw throws transient " +
                                "try void volatile while"),
                blockKeywords: words("catch class do else finally for if switch try while"),
                atoms: words("true false null"),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                },
                modeProps: {fold: ["brace", "import"]}
              });
            
              def("text/x-csharp", {
                name: "clike",
                keywords: words("abstract as base break case catch checked class const continue" +
                                " default delegate do else enum event explicit extern finally fixed for" +
                                " foreach goto if implicit in interface internal is lock namespace new" +
                                " operator out override params private protected public readonly ref return sealed" +
                                " sizeof stackalloc static struct switch this throw try typeof unchecked" +
                                " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
                                " global group into join let orderby partial remove select set value var yield"),
                blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
                builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
                                " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
                                " UInt64 bool byte char decimal double short int long object"  +
                                " sbyte float string ushort uint ulong"),
                atoms: words("true false null"),
                hooks: {
                  "@": function(stream, state) {
                    if (stream.eat('"')) {
                      state.tokenize = tokenAtString;
                      return tokenAtString(stream, state);
                    }
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
              function tokenTripleString(stream, state) {
                var escaped = false;
                while (!stream.eol()) {
                  if (!escaped && stream.match('"""')) {
                    state.tokenize = null;
                    break;
                  }
                  escaped = stream.next() == "\\" && !escaped;
                }
                return "string";
              }
            
              def("text/x-scala", {
                name: "clike",
                keywords: words(
            
                  /* scala */
                  "abstract case catch class def do else extends false final finally for forSome if " +
                  "implicit import lazy match new null object override package private protected return " +
                  "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
                  "<% >: # @ " +
            
                  /* package scala */
                  "assert assume require print println printf readLine readBoolean readByte readShort " +
                  "readChar readInt readLong readFloat readDouble " +
            
                  "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
                  "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
                  "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
                  "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
                  "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
            
                  /* package java.lang */
                  "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
                  "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
                  "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
                  "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
                ),
                multiLineStrings: true,
                blockKeywords: words("catch class do else finally for forSome if match switch try while"),
                atoms: words("true false null"),
                indentStatements: false,
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  },
                  '"': function(stream, state) {
                    if (!stream.match('""')) return false;
                    state.tokenize = tokenTripleString;
                    return state.tokenize(stream, state);
                  },
                  "'": function(stream) {
                    stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                    return "atom";
                  }
                }
              });
            
              def(["x-shader/x-vertex", "x-shader/x-fragment"], {
                name: "clike",
                keywords: words("float int bool void " +
                                "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
                                "mat2 mat3 mat4 " +
                                "sampler1D sampler2D sampler3D samplerCube " +
                                "sampler1DShadow sampler2DShadow " +
                                "const attribute uniform varying " +
                                "break continue discard return " +
                                "for while do if else struct " +
                                "in out inout"),
                blockKeywords: words("for while do if else struct"),
                builtin: words("radians degrees sin cos tan asin acos atan " +
                                "pow exp log exp2 sqrt inversesqrt " +
                                "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
                                "length distance dot cross normalize ftransform faceforward " +
                                "reflect refract matrixCompMult " +
                                "lessThan lessThanEqual greaterThan greaterThanEqual " +
                                "equal notEqual any all not " +
                                "texture1D texture1DProj texture1DLod texture1DProjLod " +
                                "texture2D texture2DProj texture2DLod texture2DProjLod " +
                                "texture3D texture3DProj texture3DLod texture3DProjLod " +
                                "textureCube textureCubeLod " +
                                "shadow1D shadow2D shadow1DProj shadow2DProj " +
                                "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
                                "dFdx dFdy fwidth " +
                                "noise1 noise2 noise3 noise4"),
                atoms: words("true false " +
                            "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
                            "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
                            "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
                            "gl_FogCoord gl_PointCoord " +
                            "gl_Position gl_PointSize gl_ClipVertex " +
                            "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
                            "gl_TexCoord gl_FogFragCoord " +
                            "gl_FragCoord gl_FrontFacing " +
                            "gl_FragData gl_FragDepth " +
                            "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
                            "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
                            "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
                            "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
                            "gl_ProjectionMatrixInverseTranspose " +
                            "gl_ModelViewProjectionMatrixInverseTranspose " +
                            "gl_TextureMatrixInverseTranspose " +
                            "gl_NormalScale gl_DepthRange gl_ClipPlane " +
                            "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
                            "gl_FrontLightModelProduct gl_BackLightModelProduct " +
                            "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
                            "gl_FogParameters " +
                            "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
                            "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
                            "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
                            "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
                            "gl_MaxDrawBuffers"),
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-nesc", {
                name: "clike",
                keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
                                "implementation includes interface module new norace nx_struct nx_union post provides " +
                                "signal task uses abstract extends"),
                blockKeywords: words("case do else for if switch while struct"),
                atoms: words("null"),
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-objectivec", {
                name: "clike",
                keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
                                "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
                atoms: words("YES NO NULL NILL ON OFF"),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$]/);
                    return "keyword";
                  },
                  "#": cppHook
                },
                modeProps: {fold: "brace"}
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: C-like mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="clike.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">C-like</a>
              </ul>
            </div>
            
            <article>
            <h2>C-like mode</h2>
            
            <div><textarea id="c-code">
            /* C demo code */
            
            #include <zmq.h>
            #include <pthread.h>
            #include <semaphore.h>
            #include <time.h>
            #include <stdio.h>
            #include <fcntl.h>
            #include <malloc.h>
            
            typedef struct {
              void* arg_socket;
              zmq_msg_t* arg_msg;
              char* arg_string;
              unsigned long arg_len;
              int arg_int, arg_command;
            
              int signal_fd;
              int pad;
              void* context;
              sem_t sem;
            } acl_zmq_context;
            
            #define p(X) (context->arg_##X)
            
            void* zmq_thread(void* context_pointer) {
              acl_zmq_context* context = (acl_zmq_context*)context_pointer;
              char ok = 'K', err = 'X';
              int res;
            
              while (1) {
                while ((res = sem_wait(&amp;context->sem)) == EINTR);
                if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}
                switch(p(command)) {
                case 0: goto cleanup;
                case 1: p(socket) = zmq_socket(context->context, p(int)); break;
                case 2: p(int) = zmq_close(p(socket)); break;
                case 3: p(int) = zmq_bind(p(socket), p(string)); break;
                case 4: p(int) = zmq_connect(p(socket), p(string)); break;
                case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;
                case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
                case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
                case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
                case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
                }
                p(command) = errno;
                write(context->signal_fd, &amp;ok, 1);
              }
             cleanup:
              close(context->signal_fd);
              free(context_pointer);
              return 0;
            }
            
            void* zmq_thread_init(void* zmq_context, int signal_fd) {
              acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
              pthread_t thread;
            
              context->context = zmq_context;
              context->signal_fd = signal_fd;
              sem_init(&amp;context->sem, 1, 0);
              pthread_create(&amp;thread, 0, &amp;zmq_thread, context);
              pthread_detach(thread);
              return context;
            }
            </textarea></div>
            
            <h2>C++ example</h2>
            
            <div><textarea id="cpp-code">
            #include <iostream>
            #include "mystuff/util.h"
            
            namespace {
            enum Enum {
              VAL1, VAL2, VAL3
            };
            
            char32_t unicode_string = U"\U0010FFFF";
            string raw_string = R"delim(anything
            you
            want)delim";
            
            int Helper(const MyType& param) {
              return 0;
            }
            } // namespace
            
            class ForwardDec;
            
            template <class T, class V>
            class Class : public BaseClass {
              const MyType<T, V> member_;
            
             public:
              const MyType<T, V>& Method() const {
                return member_;
              }
            
              void Method2(MyType<T, V>* value);
            }
            
            template <class T, class V>
            void Class::Method2(MyType<T, V>* value) {
              std::out << 1 >> method();
              value->Method3(member_);
              member_ = value;
            }
            </textarea></div>
            
            <h2>Objective-C example</h2>
            
            <div><textarea id="objectivec-code">
            /*
            This is a longer comment
            That spans two lines
            */
            
            #import <Test/Test.h>
            @implementation YourAppDelegate
            
            // This is a one-line comment
            
            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
              char myString[] = "This is a C character array";
              int test = 5;
              return YES;
            }
            </textarea></div>
            
            <h2>Java example</h2>
            
            <div><textarea id="java-code">
            import com.demo.util.MyType;
            import com.demo.util.MyInterface;
            
            public enum Enum {
              VAL1, VAL2, VAL3
            }
            
            public class Class<T, V> implements MyInterface {
              public static final MyType<T, V> member;
              
              private class InnerClass {
                public int zero() {
                  return 0;
                }
              }
            
              @Override
              public MyType method() {
                return member;
              }
            
              public void method2(MyType<T, V> value) {
                method();
                value.method3();
                member = value;
              }
            }
            </textarea></div>
            
            <h2>Scala example</h2>
            
            <div><textarea id="scala-code">
            object FilterTest extends App {
              def filter(xs: List[Int], threshold: Int) = {
                def process(ys: List[Int]): List[Int] =
                  if (ys.isEmpty) ys
                  else if (ys.head < threshold) ys.head :: process(ys.tail)
                  else process(ys.tail)
                process(xs)
              }
              println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
            }
            </textarea></div>
            
                <script>
                  var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-csrc"
                  });
                  var cppEditor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-c++src"
                  });
                  var javaEditor = CodeMirror.fromTextArea(document.getElementById("java-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-java"
                  });
                  var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-objectivec"
                  });
                  var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-scala"
                  });
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
            
                <p>Simple mode that tries to handle C-like languages as well as it
                can. Takes two configuration parameters: <code>keywords</code>, an
                object whose property names are the keywords in the language,
                and <code>useCPP</code>, which determines whether C preprocessor
                directives are recognized.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
                (C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
                (Java), <code>text/x-csharp</code> (C#),
                <code>text/x-objectivec</code> (Objective-C),
                <code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
                and <code>x-shader/x-fragment</code> (shader programs).</p>
            </article>
            
          • scala.html
            <!doctype html>
            
            <title>CodeMirror: Scala mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="clike.js"></script>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Scala</a>
              </ul>
            </div>
            
            <article>
            <h2>Scala mode</h2>
            <form>
            <textarea id="code" name="code">
            
              /*                     __                                               *\
              **     ________ ___   / /  ___     Scala API                            **
              **    / __/ __// _ | / /  / _ |    (c) 2003-2011, LAMP/EPFL             **
              **  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
              ** /____/\___/_/ |_/____/_/ | |                                         **
              **                          |/                                          **
              \*                                                                      */
            
              package scala.collection
            
              import generic._
              import mutable.{ Builder, ListBuffer }
              import annotation.{tailrec, migration, bridge}
              import annotation.unchecked.{ uncheckedVariance => uV }
              import parallel.ParIterable
            
              /** A template trait for traversable collections of type `Traversable[A]`.
               *  
               *  $traversableInfo
               *  @define mutability
               *  @define traversableInfo
               *  This is a base trait of all kinds of $mutability Scala collections. It
               *  implements the behavior common to all collections, in terms of a method
               *  `foreach` with signature:
               * {{{
               *     def foreach[U](f: Elem => U): Unit
               * }}}
               *  Collection classes mixing in this trait provide a concrete 
               *  `foreach` method which traverses all the
               *  elements contained in the collection, applying a given function to each.
               *  They also need to provide a method `newBuilder`
               *  which creates a builder for collections of the same kind.
               *  
               *  A traversable class might or might not have two properties: strictness
               *  and orderedness. Neither is represented as a type.
               *  
               *  The instances of a strict collection class have all their elements
               *  computed before they can be used as values. By contrast, instances of
               *  a non-strict collection class may defer computation of some of their
               *  elements until after the instance is available as a value.
               *  A typical example of a non-strict collection class is a
               *  <a href="../immutable/Stream.html" target="ContentFrame">
               *  `scala.collection.immutable.Stream`</a>.
               *  A more general class of examples are `TraversableViews`.
               *  
               *  If a collection is an instance of an ordered collection class, traversing
               *  its elements with `foreach` will always visit elements in the
               *  same order, even for different runs of the program. If the class is not
               *  ordered, `foreach` can visit elements in different orders for
               *  different runs (but it will keep the same order in the same run).'
               * 
               *  A typical example of a collection class which is not ordered is a
               *  `HashMap` of objects. The traversal order for hash maps will
               *  depend on the hash codes of its elements, and these hash codes might
               *  differ from one run to the next. By contrast, a `LinkedHashMap`
               *  is ordered because it's `foreach` method visits elements in the
               *  order they were inserted into the `HashMap`.
               *
               *  @author Martin Odersky
               *  @version 2.8
               *  @since   2.8
               *  @tparam A    the element type of the collection
               *  @tparam Repr the type of the actual collection containing the elements.
               *
               *  @define Coll Traversable
               *  @define coll traversable collection
               */
              trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr] 
                                                  with FilterMonadic[A, Repr]
                                                  with TraversableOnce[A]
                                                  with GenTraversableLike[A, Repr]
                                                  with Parallelizable[A, ParIterable[A]]
              {
                self =>
            
                import Traversable.breaks._
            
                /** The type implementing this traversable */
                protected type Self = Repr
            
                /** The collection of type $coll underlying this `TraversableLike` object.
                 *  By default this is implemented as the `TraversableLike` object itself,
                 *  but this can be overridden.
                 */
                def repr: Repr = this.asInstanceOf[Repr]
            
                /** The underlying collection seen as an instance of `$Coll`.
                 *  By default this is implemented as the current collection object itself,
                 *  but this can be overridden.
                 */
                protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
            
                /** A conversion from collections of type `Repr` to `$Coll` objects.
                 *  By default this is implemented as just a cast, but this can be overridden.
                 */
                protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
            
                /** Creates a new builder for this collection type.
                 */
                protected[this] def newBuilder: Builder[A, Repr]
            
                protected[this] def parCombiner = ParIterable.newCombiner[A]
            
                /** Applies a function `f` to all elements of this $coll.
                 *  
                 *    Note: this method underlies the implementation of most other bulk operations.
                 *    It's important to implement this method in an efficient way.
                 *  
                 *
                 *  @param  f   the function that is applied for its side-effect to every element.
                 *              The result of function `f` is discarded.
                 *              
                 *  @tparam  U  the type parameter describing the result of function `f`. 
                 *              This result will always be ignored. Typically `U` is `Unit`,
                 *              but this is not necessary.
                 *
                 *  @usecase def foreach(f: A => Unit): Unit
                 */
                def foreach[U](f: A => U): Unit
            
                /** Tests whether this $coll is empty.
                 *
                 *  @return    `true` if the $coll contain no elements, `false` otherwise.
                 */
                def isEmpty: Boolean = {
                  var result = true
                  breakable {
                    for (x <- this) {
                      result = false
                      break
                    }
                  }
                  result
                }
            
                /** Tests whether this $coll is known to have a finite size.
                 *  All strict collections are known to have finite size. For a non-strict collection
                 *  such as `Stream`, the predicate returns `true` if all elements have been computed.
                 *  It returns `false` if the stream is not yet evaluated to the end.
                 *
                 *  Note: many collection methods will not work on collections of infinite sizes. 
                 *
                 *  @return  `true` if this collection is known to have finite size, `false` otherwise.
                 */
                def hasDefiniteSize = true
            
                def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)
                  b ++= thisCollection
                  b ++= that.seq
                  b.result
                }
            
                @bridge
                def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
                  ++(that: GenTraversableOnce[B])(bf)
            
                /** Concatenates this $coll with the elements of a traversable collection.
                 *  It differs from ++ in that the right operand determines the type of the
                 *  resulting collection rather than the left one.
                 * 
                 *  @param that   the traversable to append.
                 *  @tparam B     the element type of the returned collection. 
                 *  @tparam That  $thatinfo
                 *  @param bf     $bfinfo
                 *  @return       a new collection of type `That` which contains all elements
                 *                of this $coll followed by all elements of `that`.
                 * 
                 *  @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
                 *  
                 *  @return       a new $coll which contains all elements of this $coll
                 *                followed by all elements of `that`.
                 */
                def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)
                  b ++= that
                  b ++= thisCollection
                  b.result
                }
            
                /** This overload exists because: for the implementation of ++: we should reuse
                 *  that of ++ because many collections override it with more efficient versions.
                 *  Since TraversableOnce has no '++' method, we have to implement that directly,
                 *  but Traversable and down can use the overload.
                 */
                def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
                  (that ++ seq)(breakOut)
            
                def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  b.sizeHint(this) 
                  for (x <- this) b += f(x)
                  b.result
                }
            
                def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) b ++= f(x).seq
                  b.result
                }
            
                /** Selects all elements of this $coll which satisfy a predicate.
                 *
                 *  @param p     the predicate used to test elements.
                 *  @return      a new $coll consisting of all elements of this $coll that satisfy the given
                 *               predicate `p`. The order of the elements is preserved.
                 */
                def filter(p: A => Boolean): Repr = {
                  val b = newBuilder
                  for (x <- this) 
                    if (p(x)) b += x
                  b.result
                }
            
                /** Selects all elements of this $coll which do not satisfy a predicate.
                 *
                 *  @param p     the predicate used to test elements.
                 *  @return      a new $coll consisting of all elements of this $coll that do not satisfy the given
                 *               predicate `p`. The order of the elements is preserved.
                 */
                def filterNot(p: A => Boolean): Repr = filter(!p(_))
            
                def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)
                  b.result
                }
            
                /** Builds a new collection by applying an option-valued function to all
                 *  elements of this $coll on which the function is defined.
                 *
                 *  @param f      the option-valued function which filters and maps the $coll.
                 *  @tparam B     the element type of the returned collection.
                 *  @tparam That  $thatinfo
                 *  @param bf     $bfinfo
                 *  @return       a new collection of type `That` resulting from applying the option-valued function
                 *                `f` to each element and collecting all defined results.
                 *                The order of the elements is preserved.
                 *
                 *  @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
                 *  
                 *  @param pf     the partial function which filters and maps the $coll.
                 *  @return       a new $coll resulting from applying the given option-valued function
                 *                `f` to each element and collecting all defined results.
                 *                The order of the elements is preserved.
                def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) 
                    f(x) match {
                      case Some(y) => b += y
                      case _ =>
                    }
                  b.result
                }
                 */
            
                /** Partitions this $coll in two ${coll}s according to a predicate.
                 *
                 *  @param p the predicate on which to partition.
                 *  @return  a pair of ${coll}s: the first $coll consists of all elements that 
                 *           satisfy the predicate `p` and the second $coll consists of all elements
                 *           that don't. The relative order of the elements in the resulting ${coll}s
                 *           is the same as in the original $coll.
                 */
                def partition(p: A => Boolean): (Repr, Repr) = {
                  val l, r = newBuilder
                  for (x <- this) (if (p(x)) l else r) += x
                  (l.result, r.result)
                }
            
                def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
                  val m = mutable.Map.empty[K, Builder[A, Repr]]
                  for (elem <- this) {
                    val key = f(elem)
                    val bldr = m.getOrElseUpdate(key, newBuilder)
                    bldr += elem
                  }
                  val b = immutable.Map.newBuilder[K, Repr]
                  for ((k, v) <- m)
                    b += ((k, v.result))
            
                  b.result
                }
            
                /** Tests whether a predicate holds for all elements of this $coll.
                 *
                 *  $mayNotTerminateInf
                 *
                 *  @param   p     the predicate used to test elements.
                 *  @return        `true` if the given predicate `p` holds for all elements
                 *                 of this $coll, otherwise `false`.
                 */
                def forall(p: A => Boolean): Boolean = {
                  var result = true
                  breakable {
                    for (x <- this)
                      if (!p(x)) { result = false; break }
                  }
                  result
                }
            
                /** Tests whether a predicate holds for some of the elements of this $coll.
                 *
                 *  $mayNotTerminateInf
                 *
                 *  @param   p     the predicate used to test elements.
                 *  @return        `true` if the given predicate `p` holds for some of the
                 *                 elements of this $coll, otherwise `false`.
                 */
                def exists(p: A => Boolean): Boolean = {
                  var result = false
                  breakable {
                    for (x <- this)
                      if (p(x)) { result = true; break }
                  }
                  result
                }
            
                /** Finds the first element of the $coll satisfying a predicate, if any.
                 * 
                 *  $mayNotTerminateInf
                 *  $orderDependent
                 *
                 *  @param p    the predicate used to test elements.
                 *  @return     an option value containing the first element in the $coll
                 *              that satisfies `p`, or `None` if none exists.
                 */
                def find(p: A => Boolean): Option[A] = {
                  var result: Option[A] = None
                  breakable {
                    for (x <- this)
                      if (p(x)) { result = Some(x); break }
                  }
                  result
                }
            
                def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)
            
                def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  b.sizeHint(this, 1)
                  var acc = z
                  b += acc
                  for (x <- this) { acc = op(acc, x); b += acc }
                  b.result
                }
            
                @migration(2, 9,
                  "This scanRight definition has changed in 2.9.\n" +
                  "The previous behavior can be reproduced with scanRight.reverse."
                )
                def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  var scanned = List(z)
                  var acc = z
                  for (x <- reversed) {
                    acc = op(x, acc)
                    scanned ::= acc
                  }
                  val b = bf(repr)
                  for (elem <- scanned) b += elem
                  b.result
                }
            
                /** Selects the first element of this $coll.
                 *  $orderDependent
                 *  @return  the first element of this $coll.
                 *  @throws `NoSuchElementException` if the $coll is empty.
                 */
                def head: A = {
                  var result: () => A = () => throw new NoSuchElementException
                  breakable {
                    for (x <- this) {
                      result = () => x
                      break
                    }
                  }
                  result()
                }
            
                /** Optionally selects the first element.
                 *  $orderDependent
                 *  @return  the first element of this $coll if it is nonempty, `None` if it is empty.
                 */
                def headOption: Option[A] = if (isEmpty) None else Some(head)
            
                /** Selects all elements except the first.
                 *  $orderDependent
                 *  @return  a $coll consisting of all elements of this $coll
                 *           except the first one.
                 *  @throws `UnsupportedOperationException` if the $coll is empty.
                 */ 
                override def tail: Repr = {
                  if (isEmpty) throw new UnsupportedOperationException("empty.tail")
                  drop(1)
                }
            
                /** Selects the last element.
                  * $orderDependent
                  * @return The last element of this $coll.
                  * @throws NoSuchElementException If the $coll is empty.
                  */
                def last: A = {
                  var lst = head
                  for (x <- this)
                    lst = x
                  lst
                }
            
                /** Optionally selects the last element.
                 *  $orderDependent
                 *  @return  the last element of this $coll$ if it is nonempty, `None` if it is empty.
                 */
                def lastOption: Option[A] = if (isEmpty) None else Some(last)
            
                /** Selects all elements except the last.
                 *  $orderDependent
                 *  @return  a $coll consisting of all elements of this $coll
                 *           except the last one.
                 *  @throws `UnsupportedOperationException` if the $coll is empty.
                 */
                def init: Repr = {
                  if (isEmpty) throw new UnsupportedOperationException("empty.init")
                  var lst = head
                  var follow = false
                  val b = newBuilder
                  b.sizeHint(this, -1)
                  for (x <- this.seq) {
                    if (follow) b += lst
                    else follow = true
                    lst = x
                  }
                  b.result
                }
            
                def take(n: Int): Repr = slice(0, n)
            
                def drop(n: Int): Repr = 
                  if (n <= 0) {
                    val b = newBuilder
                    b.sizeHint(this)
                    b ++= thisCollection result
                  }
                  else sliceWithKnownDelta(n, Int.MaxValue, -n)
            
                def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
            
                // Precondition: from >= 0, until > 0, builder already configured for building.
                private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
                  var i = 0
                  breakable {
                    for (x <- this.seq) {
                      if (i >= from) b += x
                      i += 1
                      if (i >= until) break
                    }
                  }
                  b.result
                }
                // Precondition: from >= 0
                private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {
                  val b = newBuilder
                  if (until <= from) b.result
                  else {
                    b.sizeHint(this, delta)
                    sliceInternal(from, until, b)
                  }
                }
                // Precondition: from >= 0
                private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {
                  val b = newBuilder
                  if (until <= from) b.result
                  else {
                    b.sizeHintBounded(until - from, this)      
                    sliceInternal(from, until, b)
                  }
                }
            
                def takeWhile(p: A => Boolean): Repr = {
                  val b = newBuilder
                  breakable {
                    for (x <- this) {
                      if (!p(x)) break
                      b += x
                    }
                  }
                  b.result
                }
            
                def dropWhile(p: A => Boolean): Repr = {
                  val b = newBuilder
                  var go = false
                  for (x <- this) {
                    if (!p(x)) go = true
                    if (go) b += x
                  }
                  b.result
                }
            
                def span(p: A => Boolean): (Repr, Repr) = {
                  val l, r = newBuilder
                  var toLeft = true
                  for (x <- this) {
                    toLeft = toLeft && p(x)
                    (if (toLeft) l else r) += x
                  }
                  (l.result, r.result)
                }
            
                def splitAt(n: Int): (Repr, Repr) = {
                  val l, r = newBuilder
                  l.sizeHintBounded(n, this)
                  if (n >= 0) r.sizeHint(this, -n)
                  var i = 0
                  for (x <- this) {
                    (if (i < n) l else r) += x
                    i += 1
                  }
                  (l.result, r.result)
                }
            
                /** Iterates over the tails of this $coll. The first value will be this
                 *  $coll and the final one will be an empty $coll, with the intervening
                 *  values the results of successive applications of `tail`.
                 *
                 *  @return   an iterator over all the tails of this $coll
                 *  @example  `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`
                 */  
                def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)
            
                /** Iterates over the inits of this $coll. The first value will be this
                 *  $coll and the final one will be an empty $coll, with the intervening
                 *  values the results of successive applications of `init`.
                 *
                 *  @return  an iterator over all the inits of this $coll
                 *  @example  `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`
                 */
                def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
            
                /** Copies elements of this $coll to an array.
                 *  Fills the given array `xs` with at most `len` elements of
                 *  this $coll, starting at position `start`.
                 *  Copying will stop once either the end of the current $coll is reached,
                 *  or the end of the array is reached, or `len` elements have been copied.
                 *
                 *  $willNotTerminateInf
                 * 
                 *  @param  xs     the array to fill.
                 *  @param  start  the starting index.
                 *  @param  len    the maximal number of elements to copy.
                 *  @tparam B      the type of the elements of the array. 
                 * 
                 *
                 *  @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
                 */
                def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
                  var i = start
                  val end = (start + len) min xs.length
                  breakable {
                    for (x <- this) {
                      if (i >= end) break
                      xs(i) = x
                      i += 1
                    }
                  }
                }
            
                def toTraversable: Traversable[A] = thisCollection
                def toIterator: Iterator[A] = toStream.iterator
                def toStream: Stream[A] = toBuffer.toStream
            
                /** Converts this $coll to a string.
                 *
                 *  @return   a string representation of this collection. By default this
                 *            string consists of the `stringPrefix` of this $coll,
                 *            followed by all elements separated by commas and enclosed in parentheses.
                 */
                override def toString = mkString(stringPrefix + "(", ", ", ")")
            
                /** Defines the prefix of this object's `toString` representation.
                 *
                 *  @return  a string representation which starts the result of `toString`
                 *           applied to this $coll. By default the string prefix is the
                 *           simple name of the collection class $coll.
                 */
                def stringPrefix : String = {
                  var string = repr.asInstanceOf[AnyRef].getClass.getName
                  val idx1 = string.lastIndexOf('.' : Int)
                  if (idx1 != -1) string = string.substring(idx1 + 1)
                  val idx2 = string.indexOf('$')
                  if (idx2 != -1) string = string.substring(0, idx2)
                  string
                }
            
                /** Creates a non-strict view of this $coll.
                 * 
                 *  @return a non-strict view of this $coll.
                 */
                def view = new TraversableView[A, Repr] {
                  protected lazy val underlying = self.repr
                  override def foreach[U](f: A => U) = self foreach f
                }
            
                /** Creates a non-strict view of a slice of this $coll.
                 *
                 *  Note: the difference between `view` and `slice` is that `view` produces
                 *        a view of the current $coll, whereas `slice` produces a new $coll.
                 * 
                 *  Note: `view(from, to)` is equivalent to `view.slice(from, to)`
                 *  $orderDependent
                 * 
                 *  @param from   the index of the first element of the view
                 *  @param until  the index of the element following the view
                 *  @return a non-strict view of a slice of this $coll, starting at index `from`
                 *  and extending up to (but not including) index `until`.
                 */
                def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)
            
                /** Creates a non-strict filter of this $coll.
                 *
                 *  Note: the difference between `c filter p` and `c withFilter p` is that
                 *        the former creates a new collection, whereas the latter only
                 *        restricts the domain of subsequent `map`, `flatMap`, `foreach`,
                 *        and `withFilter` operations.
                 *  $orderDependent
                 * 
                 *  @param p   the predicate used to test elements.
                 *  @return    an object of class `WithFilter`, which supports
                 *             `map`, `flatMap`, `foreach`, and `withFilter` operations.
                 *             All these operations apply to those elements of this $coll which
                 *             satisfy the predicate `p`.
                 */
                def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
            
                /** A class supporting filtered operations. Instances of this class are
                 *  returned by method `withFilter`.
                 */
                class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
            
                  /** Builds a new collection by applying a function to all elements of the
                   *  outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
                   *
                   *  @param f      the function to apply to each element.
                   *  @tparam B     the element type of the returned collection.
                   *  @tparam That  $thatinfo
                   *  @param bf     $bfinfo
                   *  @return       a new collection of type `That` resulting from applying
                   *                the given function `f` to each element of the outer $coll
                   *                that satisfies predicate `p` and collecting the results.
                   *
                   *  @usecase def map[B](f: A => B): $Coll[B] 
                   *  
                   *  @return       a new $coll resulting from applying the given function
                   *                `f` to each element of the outer $coll that satisfies
                   *                predicate `p` and collecting the results.
                   */
                  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                    val b = bf(repr)
                    for (x <- self) 
                      if (p(x)) b += f(x)
                    b.result
                  }
            
                  /** Builds a new collection by applying a function to all elements of the
                   *  outer $coll containing this `WithFilter` instance that satisfy
                   *  predicate `p` and concatenating the results. 
                   *
                   *  @param f      the function to apply to each element.
                   *  @tparam B     the element type of the returned collection.
                   *  @tparam That  $thatinfo
                   *  @param bf     $bfinfo
                   *  @return       a new collection of type `That` resulting from applying
                   *                the given collection-valued function `f` to each element
                   *                of the outer $coll that satisfies predicate `p` and
                   *                concatenating the results.
                   *
                   *  @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
                   * 
                   *  @return       a new $coll resulting from applying the given collection-valued function
                   *                `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
                   */
                  def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                    val b = bf(repr)
                    for (x <- self) 
                      if (p(x)) b ++= f(x).seq
                    b.result
                  }
            
                  /** Applies a function `f` to all elements of the outer $coll containing
                   *  this `WithFilter` instance that satisfy predicate `p`.
                   *
                   *  @param  f   the function that is applied for its side-effect to every element.
                   *              The result of function `f` is discarded.
                   *              
                   *  @tparam  U  the type parameter describing the result of function `f`. 
                   *              This result will always be ignored. Typically `U` is `Unit`,
                   *              but this is not necessary.
                   *
                   *  @usecase def foreach(f: A => Unit): Unit
                   */   
                  def foreach[U](f: A => U): Unit = 
                    for (x <- self) 
                      if (p(x)) f(x)
            
                  /** Further refines the filter for this $coll.
                   *
                   *  @param q   the predicate used to test elements.
                   *  @return    an object of class `WithFilter`, which supports
                   *             `map`, `flatMap`, `foreach`, and `withFilter` operations.
                   *             All these operations apply to those elements of this $coll which
                   *             satisfy the predicate `q` in addition to the predicate `p`.
                   */
                  def withFilter(q: A => Boolean): WithFilter = 
                    new WithFilter(x => p(x) && q(x))
                }
            
                // A helper for tails and inits.
                private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
                  val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
                  it ++ Iterator(Nil) map (newBuilder ++= _ result)
                }
              }
            
            
            </textarea>
            </form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "ambiance",
                    mode: "text/x-scala"
                  });
                </script>
              </article>
            
        • clojure
          • clojure.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Hans Engel
             * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("clojure", function (options) {
                var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
                    ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
                var INDENT_WORD_SKIP = options.indentUnit || 2;
                var NORMAL_INDENT_UNIT = options.indentUnit || 2;
            
                function makeKeywords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var atoms = makeKeywords("true false nil");
            
                var keywords = makeKeywords(
                  "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
            
                var builtins = makeKeywords(
                    "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>");
            
                var indentKeys = makeKeywords(
                    // Built-ins
                    "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " +
            
                    // Binding forms
                    "let letfn binding loop for doseq dotimes when-let if-let " +
            
                    // Data structures
                    "defstruct struct-map assoc " +
            
                    // clojure.test
                    "testing deftest " +
            
                    // contrib
                    "handler-case handle dotrace deftrace");
            
                var tests = {
                    digit: /\d/,
                    digit_or_colon: /[\d:]/,
                    hex: /[0-9a-f]/i,
                    sign: /[+-]/,
                    exponent: /e/i,
                    keyword_char: /[^\s\(\[\;\)\]]/,
                    symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
                };
            
                function stateStack(indent, type, prev) { // represents a state stack object
                    this.indent = indent;
                    this.type = type;
                    this.prev = prev;
                }
            
                function pushStack(state, indent, type) {
                    state.indentStack = new stateStack(indent, type, state.indentStack);
                }
            
                function popStack(state) {
                    state.indentStack = state.indentStack.prev;
                }
            
                function isNumber(ch, stream){
                    // hex
                    if ( ch === '0' && stream.eat(/x/i) ) {
                        stream.eatWhile(tests.hex);
                        return true;
                    }
            
                    // leading sign
                    if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
                      stream.eat(tests.sign);
                      ch = stream.next();
                    }
            
                    if ( tests.digit.test(ch) ) {
                        stream.eat(ch);
                        stream.eatWhile(tests.digit);
            
                        if ( '.' == stream.peek() ) {
                            stream.eat('.');
                            stream.eatWhile(tests.digit);
                        }
            
                        if ( stream.eat(tests.exponent) ) {
                            stream.eat(tests.sign);
                            stream.eatWhile(tests.digit);
                        }
            
                        return true;
                    }
            
                    return false;
                }
            
                // Eat character that starts after backslash \
                function eatCharacter(stream) {
                    var first = stream.next();
                    // Read special literals: backspace, newline, space, return.
                    // Just read all lowercase letters.
                    if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
                        return;
                    }
                    // Read unicode character: \u1000 \uA0a1
                    if (first === "u") {
                        stream.match(/[0-9a-z]{4}/i, true);
                    }
                }
            
                return {
                    startState: function () {
                        return {
                            indentStack: null,
                            indentation: 0,
                            mode: false
                        };
                    },
            
                    token: function (stream, state) {
                        if (state.indentStack == null && stream.sol()) {
                            // update indentation, but only if indentStack is empty
                            state.indentation = stream.indentation();
                        }
            
                        // skip spaces
                        if (stream.eatSpace()) {
                            return null;
                        }
                        var returnType = null;
            
                        switch(state.mode){
                            case "string": // multi-line string parsing mode
                                var next, escaped = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "\"" && !escaped) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    escaped = !escaped && next == "\\";
                                }
                                returnType = STRING; // continue on in string mode
                                break;
                            default: // default parsing mode
                                var ch = stream.next();
            
                                if (ch == "\"") {
                                    state.mode = "string";
                                    returnType = STRING;
                                } else if (ch == "\\") {
                                    eatCharacter(stream);
                                    returnType = CHARACTER;
                                } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
                                    returnType = ATOM;
                                } else if (ch == ";") { // comment
                                    stream.skipToEnd(); // rest of the line is a comment
                                    returnType = COMMENT;
                                } else if (isNumber(ch,stream)){
                                    returnType = NUMBER;
                                } else if (ch == "(" || ch == "[" || ch == "{" ) {
                                    var keyWord = '', indentTemp = stream.column(), letter;
                                    /**
                                    Either
                                    (indent-word ..
                                    (non-indent-word ..
                                    (;something else, bracket, etc.
                                    */
            
                                    if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
                                        keyWord += letter;
                                    }
            
                                    if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
                                                               /^(?:def|with)/.test(keyWord))) { // indent-word
                                        pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
                                    } else { // non-indent word
                                        // we continue eating the spaces
                                        stream.eatSpace();
                                        if (stream.eol() || stream.peek() == ";") {
                                            // nothing significant after
                                            // we restart indentation the user defined spaces after
                                            pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);
                                        } else {
                                            pushStack(state, indentTemp + stream.current().length, ch); // else we match
                                        }
                                    }
                                    stream.backUp(stream.current().length - 1); // undo all the eating
            
                                    returnType = BRACKET;
                                } else if (ch == ")" || ch == "]" || ch == "}") {
                                    returnType = BRACKET;
                                    if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) {
                                        popStack(state);
                                    }
                                } else if ( ch == ":" ) {
                                    stream.eatWhile(tests.symbol);
                                    return ATOM;
                                } else {
                                    stream.eatWhile(tests.symbol);
            
                                    if (keywords && keywords.propertyIsEnumerable(stream.current())) {
                                        returnType = KEYWORD;
                                    } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
                                        returnType = BUILTIN;
                                    } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
                                        returnType = ATOM;
                                    } else {
                                      returnType = VAR;
                                    }
                                }
                        }
            
                        return returnType;
                    },
            
                    indent: function (state) {
                        if (state.indentStack == null) return state.indentation;
                        return state.indentStack.indent;
                    },
            
                    lineComment: ";;"
                };
            });
            
            CodeMirror.defineMIME("text/x-clojure", "clojure");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Clojure mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="clojure.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Clojure</a>
              </ul>
            </div>
            
            <article>
            <h2>Clojure mode</h2>
            <form><textarea id="code" name="code">
            ; Conway's Game of Life, based on the work of:
            ;; Laurent Petit https://gist.github.com/1200343
            ;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
            
            (ns ^{:doc "Conway's Game of Life."}
             game-of-life)
            
            ;; Core game of life's algorithm functions
            
            (defn neighbours
              "Given a cell's coordinates, returns the coordinates of its neighbours."
              [[x y]]
              (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
                [(+ dx x) (+ dy y)]))
            
            (defn step
              "Given a set of living cells, computes the new set of living cells."
              [cells]
              (set (for [[cell n] (frequencies (mapcat neighbours cells))
                         :when (or (= n 3) (and (= n 2) (cells cell)))]
                     cell)))
            
            ;; Utility methods for displaying game on a text terminal
            
            (defn print-board
              "Prints a board on *out*, representing a step in the game."
              [board w h]
              (doseq [x (range (inc w)) y (range (inc h))]
                (if (= y 0) (print "\n"))
                (print (if (board [x y]) "[X]" " . "))))
            
            (defn display-grids
              "Prints a squence of boards on *out*, representing several steps."
              [grids w h]
              (doseq [board grids]
                (print-board board w h)
                (print "\n")))
            
            ;; Launches an example board
            
            (def
              ^{:doc "board represents the initial set of living cells"}
               board #{[2 1] [2 2] [2 3]})
            
            (display-grids (take 3 (iterate step board)) 5 5)
            
            ;; Let's play with characters
            (println \1 \a \# \\
                     \" \( \newline
                     \} \" \space
                     \tab \return \backspace
                     \u1000 \uAaAa \u9F9F)
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>
            
              </article>
            
        • cobol
          • cobol.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Gautam Mehta
             * Branched from CodeMirror's Scheme mode
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("cobol", function () {
              var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
                  ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",
                  COBOLLINENUM = "def", PERIOD = "link";
              function makeKeywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES ");
              var keywords = makeKeywords(
                  "ACCEPT ACCESS ACQUIRE ADD ADDRESS " +
                  "ADVANCING AFTER ALIAS ALL ALPHABET " +
                  "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " +
                  "ALSO ALTER ALTERNATE AND ANY " +
                  "ARE AREA AREAS ARITHMETIC ASCENDING " +
                  "ASSIGN AT ATTRIBUTE AUTHOR AUTO " +
                  "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " +
                  "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " +
                  "BEFORE BELL BINARY BIT BITS " +
                  "BLANK BLINK BLOCK BOOLEAN BOTTOM " +
                  "BY CALL CANCEL CD CF " +
                  "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " +
                  "CLOSE COBOL CODE CODE-SET COL " +
                  "COLLATING COLUMN COMMA COMMIT COMMITMENT " +
                  "COMMON COMMUNICATION COMP COMP-0 COMP-1 " +
                  "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " +
                  "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " +
                  "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " +
                  "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " +
                  "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " +
                  "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " +
                  "CONVERTING COPY CORR CORRESPONDING COUNT " +
                  "CRT CRT-UNDER CURRENCY CURRENT CURSOR " +
                  "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " +
                  "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " +
                  "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " +
                  "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " +
                  "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " +
                  "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " +
                  "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " +
                  "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " +
                  "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " +
                  "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " +
                  "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " +
                  "EBCDIC EGI EJECT ELSE EMI " +
                  "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " +
                  "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " +
                  "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " +
                  "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " +
                  "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " +
                  "END-UNSTRING END-WRITE END-XML ENTER ENTRY " +
                  "ENVIRONMENT EOP EQUAL EQUALS ERASE " +
                  "ERROR ESI EVALUATE EVERY EXCEEDS " +
                  "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " +
                  "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " +
                  "FILE-STREAM FILES FILLER FINAL FIND " +
                  "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " +
                  "FOREGROUND-COLOUR FORMAT FREE FROM FULL " +
                  "FUNCTION GENERATE GET GIVING GLOBAL " +
                  "GO GOBACK GREATER GROUP HEADING " +
                  "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " +
                  "ID IDENTIFICATION IF IN INDEX " +
                  "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " +
                  "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " +
                  "INDIC INDICATE INDICATOR INDICATORS INITIAL " +
                  "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " +
                  "INSTALLATION INTO INVALID INVOKE IS " +
                  "JUST JUSTIFIED KANJI KEEP KEY " +
                  "LABEL LAST LD LEADING LEFT " +
                  "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " +
                  "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " +
                  "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " +
                  "LOCALE LOCALLY LOCK " +
                  "MEMBER MEMORY MERGE MESSAGE METACLASS " +
                  "MODE MODIFIED MODIFY MODULES MOVE " +
                  "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " +
                  "NEXT NO NO-ECHO NONE NOT " +
                  "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " +
                  "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " +
                  "OF OFF OMITTED ON ONLY " +
                  "OPEN OPTIONAL OR ORDER ORGANIZATION " +
                  "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " +
                  "PADDING PAGE PAGE-COUNTER PARSE PERFORM " +
                  "PF PH PIC PICTURE PLUS " +
                  "POINTER POSITION POSITIVE PREFIX PRESENT " +
                  "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " +
                  "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " +
                  "PROMPT PROTECTED PURGE QUEUE QUOTE " +
                  "QUOTES RANDOM RD READ READY " +
                  "REALM RECEIVE RECONNECT RECORD RECORD-NAME " +
                  "RECORDS RECURSIVE REDEFINES REEL REFERENCE " +
                  "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " +
                  "REMAINDER REMOVAL RENAMES REPEATED REPLACE " +
                  "REPLACING REPORT REPORTING REPORTS REPOSITORY " +
                  "REQUIRED RERUN RESERVE RESET RETAINING " +
                  "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " +
                  "REVERSED REWIND REWRITE RF RH " +
                  "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " +
                  "RUN SAME SCREEN SD SEARCH " +
                  "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " +
                  "SELECT SEND SENTENCE SEPARATE SEQUENCE " +
                  "SEQUENTIAL SET SHARED SIGN SIZE " +
                  "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " +
                  "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " +
                  "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " +
                  "START STARTING STATUS STOP STORE " +
                  "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " +
                  "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " +
                  "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " +
                  "TABLE TALLYING TAPE TENANT TERMINAL " +
                  "TERMINATE TEST TEXT THAN THEN " +
                  "THROUGH THRU TIME TIMES TITLE " +
                  "TO TOP TRAILING TRAILING-SIGN TRANSACTION " +
                  "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " +
                  "UNSTRING UNTIL UP UPDATE UPON " +
                  "USAGE USAGE-MODE USE USING VALID " +
                  "VALIDATE VALUE VALUES VARYING VLR " +
                  "WAIT WHEN WHEN-COMPILED WITH WITHIN " +
                  "WORDS WORKING-STORAGE WRITE XML XML-CODE " +
                  "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " );
            
              var builtins = makeKeywords("- * ** / + < <= = > >= ");
              var tests = {
                digit: /\d/,
                digit_or_colon: /[\d:]/,
                hex: /[0-9a-f]/i,
                sign: /[+-]/,
                exponent: /e/i,
                keyword_char: /[^\s\(\[\;\)\]]/,
                symbol: /[\w*+\-]/
              };
              function isNumber(ch, stream){
                // hex
                if ( ch === '0' && stream.eat(/x/i) ) {
                  stream.eatWhile(tests.hex);
                  return true;
                }
                // leading sign
                if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
                  stream.eat(tests.sign);
                  ch = stream.next();
                }
                if ( tests.digit.test(ch) ) {
                  stream.eat(ch);
                  stream.eatWhile(tests.digit);
                  if ( '.' == stream.peek()) {
                    stream.eat('.');
                    stream.eatWhile(tests.digit);
                  }
                  if ( stream.eat(tests.exponent) ) {
                    stream.eat(tests.sign);
                    stream.eatWhile(tests.digit);
                  }
                  return true;
                }
                return false;
              }
              return {
                startState: function () {
                  return {
                    indentStack: null,
                    indentation: 0,
                    mode: false
                  };
                },
                token: function (stream, state) {
                  if (state.indentStack == null && stream.sol()) {
                    // update indentation, but only if indentStack is empty
                    state.indentation = 6 ; //stream.indentation();
                  }
                  // skip spaces
                  if (stream.eatSpace()) {
                    return null;
                  }
                  var returnType = null;
                  switch(state.mode){
                  case "string": // multi-line string parsing mode
                    var next = false;
                    while ((next = stream.next()) != null) {
                      if (next == "\"" || next == "\'") {
                        state.mode = false;
                        break;
                      }
                    }
                    returnType = STRING; // continue on in string mode
                    break;
                  default: // default parsing mode
                    var ch = stream.next();
                    var col = stream.column();
                    if (col >= 0 && col <= 5) {
                      returnType = COBOLLINENUM;
                    } else if (col >= 72 && col <= 79) {
                      stream.skipToEnd();
                      returnType = MODTAG;
                    } else if (ch == "*" && col == 6) { // comment
                      stream.skipToEnd(); // rest of the line is a comment
                      returnType = COMMENT;
                    } else if (ch == "\"" || ch == "\'") {
                      state.mode = "string";
                      returnType = STRING;
                    } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
                      returnType = ATOM;
                    } else if (ch == ".") {
                      returnType = PERIOD;
                    } else if (isNumber(ch,stream)){
                      returnType = NUMBER;
                    } else {
                      if (stream.current().match(tests.symbol)) {
                        while (col < 71) {
                          if (stream.eat(tests.symbol) === undefined) {
                            break;
                          } else {
                            col++;
                          }
                        }
                      }
                      if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = KEYWORD;
                      } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = BUILTIN;
                      } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = ATOM;
                      } else returnType = null;
                    }
                  }
                  return returnType;
                },
                indent: function (state) {
                  if (state.indentStack == null) return state.indentation;
                  return state.indentStack.indent;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-cobol", "cobol");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: COBOL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <link rel="stylesheet" href="../../theme/erlang-dark.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <link rel="stylesheet" href="../../theme/monokai.css">
            <link rel="stylesheet" href="../../theme/cobalt.css">
            <link rel="stylesheet" href="../../theme/eclipse.css">
            <link rel="stylesheet" href="../../theme/rubyblue.css">
            <link rel="stylesheet" href="../../theme/lesser-dark.css">
            <link rel="stylesheet" href="../../theme/xq-dark.css">
            <link rel="stylesheet" href="../../theme/xq-light.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <link rel="stylesheet" href="../../theme/blackboard.css">
            <link rel="stylesheet" href="../../theme/vibrant-ink.css">
            <link rel="stylesheet" href="../../theme/solarized.css">
            <link rel="stylesheet" href="../../theme/twilight.css">
            <link rel="stylesheet" href="../../theme/midnight.css">
            <link rel="stylesheet" href="../../addon/dialog/dialog.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="cobol.js"></script>
            <script src="../../addon/selection/active-line.js"></script>
            <script src="../../addon/search/search.js"></script>
            <script src="../../addon/dialog/dialog.js"></script>
            <script src="../../addon/search/searchcursor.js"></script>
            <style>
                    .CodeMirror {
                      border: 1px solid #eee;
                      font-size : 20px;
                      height : auto !important;
                    }
                    .CodeMirror-activeline-background {background: #555555 !important;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">COBOL</a>
              </ul>
            </div>
            
            <article>
            <h2>COBOL mode</h2>
            
                <p> Select Theme <select onchange="selectTheme()" id="selectTheme">
                    <option>default</option>
                    <option>ambiance</option>
                    <option>blackboard</option>
                    <option>cobalt</option>
                    <option>eclipse</option>
                    <option>elegant</option>
                    <option>erlang-dark</option>
                    <option>lesser-dark</option>
                    <option>midnight</option>
                    <option>monokai</option>
                    <option>neat</option>
                    <option>night</option>
                    <option>rubyblue</option>
                    <option>solarized dark</option>
                    <option>solarized light</option>
                    <option selected>twilight</option>
                    <option>vibrant-ink</option>
                    <option>xq-dark</option>
                    <option>xq-light</option>
                </select>    Select Font Size <select onchange="selectFontsize()" id="selectFontSize">
                      <option value="13px">13px</option>
                      <option value="14px">14px</option>
                      <option value="16px">16px</option>
                      <option value="18px">18px</option>
                      <option value="20px" selected="selected">20px</option>
                      <option value="24px">24px</option>
                      <option value="26px">26px</option>
                      <option value="28px">28px</option>
                      <option value="30px">30px</option>
                      <option value="32px">32px</option>
                      <option value="34px">34px</option>
                      <option value="36px">36px</option>
                    </select>
            <label for="checkBoxReadOnly">Read-only</label>
            <input type="checkbox" id="checkBoxReadOnly" onchange="selectReadOnly()">
            <label for="id_tabToIndentSpace">Insert Spaces on Tab</label>
            <input type="checkbox" id="id_tabToIndentSpace" onchange="tabToIndentSpace()">
            </p>
            <textarea id="code" name="code">
            ---------1---------2---------3---------4---------5---------6---------7---------8
            12345678911234567892123456789312345678941234567895123456789612345678971234567898
            000010 IDENTIFICATION DIVISION.                                        MODTGHERE
            000020 PROGRAM-ID.       SAMPLE.
            000030 AUTHOR.           TEST SAM. 
            000040 DATE-WRITTEN.     5 February 2013
            000041
            000042* A sample program just to show the form.
            000043* The program copies its input to the output,
            000044* and counts the number of records.
            000045* At the end this number is printed.
            000046
            000050 ENVIRONMENT DIVISION.
            000060 INPUT-OUTPUT SECTION.
            000070 FILE-CONTROL.
            000080     SELECT STUDENT-FILE     ASSIGN TO SYSIN
            000090         ORGANIZATION IS LINE SEQUENTIAL.
            000100     SELECT PRINT-FILE       ASSIGN TO SYSOUT
            000110         ORGANIZATION IS LINE SEQUENTIAL.
            000120
            000130 DATA DIVISION.
            000140 FILE SECTION.
            000150 FD  STUDENT-FILE
            000160     RECORD CONTAINS 43 CHARACTERS
            000170     DATA RECORD IS STUDENT-IN.
            000180 01  STUDENT-IN              PIC X(43).
            000190
            000200 FD  PRINT-FILE
            000210     RECORD CONTAINS 80 CHARACTERS
            000220     DATA RECORD IS PRINT-LINE.
            000230 01  PRINT-LINE              PIC X(80).
            000240
            000250 WORKING-STORAGE SECTION.
            000260 01  DATA-REMAINS-SWITCH     PIC X(2)      VALUE SPACES.
            000261 01  RECORDS-WRITTEN         PIC 99.
            000270
            000280 01  DETAIL-LINE.
            000290     05  FILLER              PIC X(7)      VALUE SPACES.
            000300     05  RECORD-IMAGE        PIC X(43).
            000310     05  FILLER              PIC X(30)     VALUE SPACES.
            000311 
            000312 01  SUMMARY-LINE.
            000313     05  FILLER              PIC X(7)      VALUE SPACES.
            000314     05  TOTAL-READ          PIC 99.
            000315     05  FILLER              PIC X         VALUE SPACE.
            000316     05  FILLER              PIC X(17)     
            000317                 VALUE  'Records were read'.
            000318     05  FILLER              PIC X(53)     VALUE SPACES.
            000319
            000320 PROCEDURE DIVISION.
            000321
            000330 PREPARE-SENIOR-REPORT.
            000340     OPEN INPUT  STUDENT-FILE
            000350          OUTPUT PRINT-FILE.
            000351     MOVE ZERO TO RECORDS-WRITTEN.
            000360     READ STUDENT-FILE
            000370         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
            000380     END-READ.
            000390     PERFORM PROCESS-RECORDS
            000410         UNTIL DATA-REMAINS-SWITCH = 'NO'.
            000411     PERFORM PRINT-SUMMARY.
            000420     CLOSE STUDENT-FILE
            000430           PRINT-FILE.
            000440     STOP RUN.
            000450
            000460 PROCESS-RECORDS.
            000470     MOVE STUDENT-IN TO RECORD-IMAGE.
            000480     MOVE DETAIL-LINE TO PRINT-LINE.
            000490     WRITE PRINT-LINE.
            000500     ADD 1 TO RECORDS-WRITTEN.
            000510     READ STUDENT-FILE
            000520         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
            000530     END-READ. 
            000540
            000550 PRINT-SUMMARY.
            000560     MOVE RECORDS-WRITTEN TO TOTAL-READ.
            000570     MOVE SUMMARY-LINE TO PRINT-LINE.
            000571     WRITE PRINT-LINE. 
            000572
            000580
            </textarea>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-cobol",
                    theme : "twilight",
                    styleActiveLine: true,
                    showCursorWhenSelecting : true,  
                  });
                  function selectTheme() {
                    var themeInput = document.getElementById("selectTheme");
                    var theme = themeInput.options[themeInput.selectedIndex].innerHTML;
                    editor.setOption("theme", theme);
                  }
                  function selectFontsize() {
                    var fontSizeInput = document.getElementById("selectFontSize");
                    var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;
                    editor.getWrapperElement().style.fontSize = fontSize;
                    editor.refresh();
                  }
                  function selectReadOnly() {
                    editor.setOption("readOnly", document.getElementById("checkBoxReadOnly").checked);
                  }
                  function tabToIndentSpace() {
                    if (document.getElementById("id_tabToIndentSpace").checked) {
                        editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection("    ", "end"); }});
                    } else {
                        editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection("    ", "end"); }});
                    }
                  }
                </script>
              </article>
            
        • coffeescript
          • coffeescript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Link to the project's GitHub page:
             * https://github.com/pickhardt/coffeescript-codemirror-mode
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
              var ERRORCLASS = "error";
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
              var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
              var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
              var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
            
              var wordOperators = wordRegexp(["and", "or", "not",
                                              "is", "isnt", "in",
                                              "instanceof", "typeof"]);
              var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
                                    "switch", "try", "catch", "finally", "class"];
              var commonKeywords = ["break", "by", "continue", "debugger", "delete",
                                    "do", "in", "of", "new", "return", "then",
                                    "this", "@", "throw", "when", "until", "extends"];
            
              var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
            
              indentKeywords = wordRegexp(indentKeywords);
            
            
              var stringPrefixes = /^('{3}|\"{3}|['\"])/;
              var regexPrefixes = /^(\/{3}|\/)/;
              var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
              var constants = wordRegexp(commonConstants);
            
              // Tokenizers
              function tokenBase(stream, state) {
                // Handle scope changes
                if (stream.sol()) {
                  if (state.scope.align === null) state.scope.align = false;
                  var scopeOffset = state.scope.offset;
                  if (stream.eatSpace()) {
                    var lineOffset = stream.indentation();
                    if (lineOffset > scopeOffset && state.scope.type == "coffee") {
                      return "indent";
                    } else if (lineOffset < scopeOffset) {
                      return "dedent";
                    }
                    return null;
                  } else {
                    if (scopeOffset > 0) {
                      dedent(stream, state);
                    }
                  }
                }
                if (stream.eatSpace()) {
                  return null;
                }
            
                var ch = stream.peek();
            
                // Handle docco title comment (single line)
                if (stream.match("####")) {
                  stream.skipToEnd();
                  return "comment";
                }
            
                // Handle multi line comments
                if (stream.match("###")) {
                  state.tokenize = longComment;
                  return state.tokenize(stream, state);
                }
            
                // Single line comment
                if (ch === "#") {
                  stream.skipToEnd();
                  return "comment";
                }
            
                // Handle number literals
                if (stream.match(/^-?[0-9\.]/, false)) {
                  var floatLiteral = false;
                  // Floats
                  if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
                    floatLiteral = true;
                  }
                  if (stream.match(/^-?\d+\.\d*/)) {
                    floatLiteral = true;
                  }
                  if (stream.match(/^-?\.\d+/)) {
                    floatLiteral = true;
                  }
            
                  if (floatLiteral) {
                    // prevent from getting extra . on 1..
                    if (stream.peek() == "."){
                      stream.backUp(1);
                    }
                    return "number";
                  }
                  // Integers
                  var intLiteral = false;
                  // Hex
                  if (stream.match(/^-?0x[0-9a-f]+/i)) {
                    intLiteral = true;
                  }
                  // Decimal
                  if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
                    intLiteral = true;
                  }
                  // Zero by itself with no other piece of number.
                  if (stream.match(/^-?0(?![\dx])/i)) {
                    intLiteral = true;
                  }
                  if (intLiteral) {
                    return "number";
                  }
                }
            
                // Handle strings
                if (stream.match(stringPrefixes)) {
                  state.tokenize = tokenFactory(stream.current(), false, "string");
                  return state.tokenize(stream, state);
                }
                // Handle regex literals
                if (stream.match(regexPrefixes)) {
                  if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
                    state.tokenize = tokenFactory(stream.current(), true, "string-2");
                    return state.tokenize(stream, state);
                  } else {
                    stream.backUp(1);
                  }
                }
            
                // Handle operators and delimiters
                if (stream.match(operators) || stream.match(wordOperators)) {
                  return "operator";
                }
                if (stream.match(delimiters)) {
                  return "punctuation";
                }
            
                if (stream.match(constants)) {
                  return "atom";
                }
            
                if (stream.match(keywords)) {
                  return "keyword";
                }
            
                if (stream.match(identifiers)) {
                  return "variable";
                }
            
                if (stream.match(properties)) {
                  return "property";
                }
            
                // Handle non-detected items
                stream.next();
                return ERRORCLASS;
              }
            
              function tokenFactory(delimiter, singleline, outclass) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    stream.eatWhile(/[^'"\/\\]/);
                    if (stream.eat("\\")) {
                      stream.next();
                      if (singleline && stream.eol()) {
                        return outclass;
                      }
                    } else if (stream.match(delimiter)) {
                      state.tokenize = tokenBase;
                      return outclass;
                    } else {
                      stream.eat(/['"\/]/);
                    }
                  }
                  if (singleline) {
                    if (parserConf.singleLineStringErrors) {
                      outclass = ERRORCLASS;
                    } else {
                      state.tokenize = tokenBase;
                    }
                  }
                  return outclass;
                };
              }
            
              function longComment(stream, state) {
                while (!stream.eol()) {
                  stream.eatWhile(/[^#]/);
                  if (stream.match("###")) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  stream.eatWhile("#");
                }
                return "comment";
              }
            
              function indent(stream, state, type) {
                type = type || "coffee";
                var offset = 0, align = false, alignOffset = null;
                for (var scope = state.scope; scope; scope = scope.prev) {
                  if (scope.type === "coffee" || scope.type == "}") {
                    offset = scope.offset + conf.indentUnit;
                    break;
                  }
                }
                if (type !== "coffee") {
                  align = null;
                  alignOffset = stream.column() + stream.current().length;
                } else if (state.scope.align) {
                  state.scope.align = false;
                }
                state.scope = {
                  offset: offset,
                  type: type,
                  prev: state.scope,
                  align: align,
                  alignOffset: alignOffset
                };
              }
            
              function dedent(stream, state) {
                if (!state.scope.prev) return;
                if (state.scope.type === "coffee") {
                  var _indent = stream.indentation();
                  var matched = false;
                  for (var scope = state.scope; scope; scope = scope.prev) {
                    if (_indent === scope.offset) {
                      matched = true;
                      break;
                    }
                  }
                  if (!matched) {
                    return true;
                  }
                  while (state.scope.prev && state.scope.offset !== _indent) {
                    state.scope = state.scope.prev;
                  }
                  return false;
                } else {
                  state.scope = state.scope.prev;
                  return false;
                }
              }
            
              function tokenLexer(stream, state) {
                var style = state.tokenize(stream, state);
                var current = stream.current();
            
                // Handle "." connected identifiers
                if (current === ".") {
                  style = state.tokenize(stream, state);
                  current = stream.current();
                  if (/^\.[\w$]+$/.test(current)) {
                    return "variable";
                  } else {
                    return ERRORCLASS;
                  }
                }
            
                // Handle scope changes.
                if (current === "return") {
                  state.dedent = true;
                }
                if (((current === "->" || current === "=>") &&
                     !state.lambda &&
                     !stream.peek())
                    || style === "indent") {
                  indent(stream, state);
                }
                var delimiter_index = "[({".indexOf(current);
                if (delimiter_index !== -1) {
                  indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
                }
                if (indentKeywords.exec(current)){
                  indent(stream, state);
                }
                if (current == "then"){
                  dedent(stream, state);
                }
            
            
                if (style === "dedent") {
                  if (dedent(stream, state)) {
                    return ERRORCLASS;
                  }
                }
                delimiter_index = "])}".indexOf(current);
                if (delimiter_index !== -1) {
                  while (state.scope.type == "coffee" && state.scope.prev)
                    state.scope = state.scope.prev;
                  if (state.scope.type == current)
                    state.scope = state.scope.prev;
                }
                if (state.dedent && stream.eol()) {
                  if (state.scope.type == "coffee" && state.scope.prev)
                    state.scope = state.scope.prev;
                  state.dedent = false;
                }
            
                return style;
              }
            
              var external = {
                startState: function(basecolumn) {
                  return {
                    tokenize: tokenBase,
                    scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
                    lastToken: null,
                    lambda: false,
                    dedent: 0
                  };
                },
            
                token: function(stream, state) {
                  var fillAlign = state.scope.align === null && state.scope;
                  if (fillAlign && stream.sol()) fillAlign.align = false;
            
                  var style = tokenLexer(stream, state);
                  if (fillAlign && style && style != "comment") fillAlign.align = true;
            
                  state.lastToken = {style:style, content: stream.current()};
            
                  if (stream.eol() && stream.lambda) {
                    state.lambda = false;
                  }
            
                  return style;
                },
            
                indent: function(state, text) {
                  if (state.tokenize != tokenBase) return 0;
                  var scope = state.scope;
                  var closer = text && "])}".indexOf(text.charAt(0)) > -1;
                  if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
                  var closes = closer && scope.type === text.charAt(0);
                  if (scope.align)
                    return scope.alignOffset - (closes ? 1 : 0);
                  else
                    return (closes ? scope.prev : scope).offset;
                },
            
                lineComment: "#",
                fold: "indent"
              };
              return external;
            });
            
            CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: CoffeeScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="coffeescript.js"></script>
            <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">CoffeeScript</a>
              </ul>
            </div>
            
            <article>
            <h2>CoffeeScript mode</h2>
            <form><textarea id="code" name="code">
            # CoffeeScript mode for CodeMirror
            # Copyright (c) 2011 Jeff Pickhardt, released under
            # the MIT License.
            #
            # Modified from the Python CodeMirror mode, which also is 
            # under the MIT License Copyright (c) 2010 Timothy Farrell.
            #
            # The following script, Underscore.coffee, is used to 
            # demonstrate CoffeeScript mode for CodeMirror.
            #
            # To download CoffeeScript mode for CodeMirror, go to:
            # https://github.com/pickhardt/coffeescript-codemirror-mode
            
            # **Underscore.coffee
            # (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
            # Underscore is freely distributable under the terms of the
            # [MIT license](http://en.wikipedia.org/wiki/MIT_License).
            # Portions of Underscore are inspired by or borrowed from
            # [Prototype.js](http://prototypejs.org/api), Oliver Steele's
            # [Functional](http://osteele.com), and John Resig's
            # [Micro-Templating](http://ejohn.org).
            # For all details and documentation:
            # http://documentcloud.github.com/underscore/
            
            
            # Baseline setup
            # --------------
            
            # Establish the root object, `window` in the browser, or `global` on the server.
            root = this
            
            
            # Save the previous value of the `_` variable.
            previousUnderscore = root._
            
            ### Multiline
                comment
            ###
            
            # Establish the object that gets thrown to break out of a loop iteration.
            # `StopIteration` is SOP on Mozilla.
            breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
            
            
            #### Docco style single line comment (title)
            
            
            # Helper function to escape **RegExp** contents, because JS doesn't have one.
            escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
            
            
            # Save bytes in the minified (but not gzipped) version:
            ArrayProto = Array.prototype
            ObjProto = Object.prototype
            
            
            # Create quick reference variables for speed access to core prototypes.
            slice = ArrayProto.slice
            unshift = ArrayProto.unshift
            toString = ObjProto.toString
            hasOwnProperty = ObjProto.hasOwnProperty
            propertyIsEnumerable = ObjProto.propertyIsEnumerable
            
            
            # All **ECMA5** native implementations we hope to use are declared here.
            nativeForEach = ArrayProto.forEach
            nativeMap = ArrayProto.map
            nativeReduce = ArrayProto.reduce
            nativeReduceRight = ArrayProto.reduceRight
            nativeFilter = ArrayProto.filter
            nativeEvery = ArrayProto.every
            nativeSome = ArrayProto.some
            nativeIndexOf = ArrayProto.indexOf
            nativeLastIndexOf = ArrayProto.lastIndexOf
            nativeIsArray = Array.isArray
            nativeKeys = Object.keys
            
            
            # Create a safe reference to the Underscore object for use below.
            _ = (obj) -> new wrapper(obj)
            
            
            # Export the Underscore object for **CommonJS**.
            if typeof(exports) != 'undefined' then exports._ = _
            
            
            # Export Underscore to global scope.
            root._ = _
            
            
            # Current version.
            _.VERSION = '1.1.0'
            
            
            # Collection Functions
            # --------------------
            
            # The cornerstone, an **each** implementation.
            # Handles objects implementing **forEach**, arrays, and raw objects.
            _.each = (obj, iterator, context) ->
              try
                if nativeForEach and obj.forEach is nativeForEach
                  obj.forEach iterator, context
                else if _.isNumber obj.length
                  iterator.call context, obj[i], i, obj for i in [0...obj.length]
                else
                  iterator.call context, val, key, obj for own key, val of obj
              catch e
                throw e if e isnt breaker
              obj
            
            
            # Return the results of applying the iterator to each element. Use JavaScript
            # 1.6's version of **map**, if possible.
            _.map = (obj, iterator, context) ->
              return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
              results = []
              _.each obj, (value, index, list) ->
                results.push iterator.call context, value, index, list
              results
            
            
            # **Reduce** builds up a single result from a list of values. Also known as
            # **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
            _.reduce = (obj, iterator, memo, context) ->
              if nativeReduce and obj.reduce is nativeReduce
                iterator = _.bind iterator, context if context
                return obj.reduce iterator, memo
              _.each obj, (value, index, list) ->
                memo = iterator.call context, memo, value, index, list
              memo
            
            
            # The right-associative version of **reduce**, also known as **foldr**. Uses
            # JavaScript 1.8's version of **reduceRight**, if available.
            _.reduceRight = (obj, iterator, memo, context) ->
              if nativeReduceRight and obj.reduceRight is nativeReduceRight
                iterator = _.bind iterator, context if context
                return obj.reduceRight iterator, memo
              reversed = _.clone(_.toArray(obj)).reverse()
              _.reduce reversed, iterator, memo, context
            
            
            # Return the first value which passes a truth test.
            _.detect = (obj, iterator, context) ->
              result = null
              _.each obj, (value, index, list) ->
                if iterator.call context, value, index, list
                  result = value
                  _.breakLoop()
              result
            
            
            # Return all the elements that pass a truth test. Use JavaScript 1.6's
            # **filter**, if it exists.
            _.filter = (obj, iterator, context) ->
              return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
              results = []
              _.each obj, (value, index, list) ->
                results.push value if iterator.call context, value, index, list
              results
            
            
            # Return all the elements for which a truth test fails.
            _.reject = (obj, iterator, context) ->
              results = []
              _.each obj, (value, index, list) ->
                results.push value if not iterator.call context, value, index, list
              results
            
            
            # Determine whether all of the elements match a truth test. Delegate to
            # JavaScript 1.6's **every**, if it is present.
            _.every = (obj, iterator, context) ->
              iterator ||= _.identity
              return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
              result = true
              _.each obj, (value, index, list) ->
                _.breakLoop() unless (result = result and iterator.call(context, value, index, list))
              result
            
            
            # Determine if at least one element in the object matches a truth test. Use
            # JavaScript 1.6's **some**, if it exists.
            _.some = (obj, iterator, context) ->
              iterator ||= _.identity
              return obj.some iterator, context if nativeSome and obj.some is nativeSome
              result = false
              _.each obj, (value, index, list) ->
                _.breakLoop() if (result = iterator.call(context, value, index, list))
              result
            
            
            # Determine if a given value is included in the array or object,
            # based on `===`.
            _.include = (obj, target) ->
              return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
              return true for own key, val of obj when val is target
              false
            
            
            # Invoke a method with arguments on every item in a collection.
            _.invoke = (obj, method) ->
              args = _.rest arguments, 2
              (if method then val[method] else val).apply(val, args) for val in obj
            
            
            # Convenience version of a common use case of **map**: fetching a property.
            _.pluck = (obj, key) ->
              _.map(obj, (val) -> val[key])
            
            
            # Return the maximum item or (item-based computation).
            _.max = (obj, iterator, context) ->
              return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
              result = computed: -Infinity
              _.each obj, (value, index, list) ->
                computed = if iterator then iterator.call(context, value, index, list) else value
                computed >= result.computed and (result = {value: value, computed: computed})
              result.value
            
            
            # Return the minimum element (or element-based computation).
            _.min = (obj, iterator, context) ->
              return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
              result = computed: Infinity
              _.each obj, (value, index, list) ->
                computed = if iterator then iterator.call(context, value, index, list) else value
                computed < result.computed and (result = {value: value, computed: computed})
              result.value
            
            
            # Sort the object's values by a criterion produced by an iterator.
            _.sortBy = (obj, iterator, context) ->
              _.pluck(((_.map obj, (value, index, list) ->
                {value: value, criteria: iterator.call(context, value, index, list)}
              ).sort((left, right) ->
                a = left.criteria; b = right.criteria
                if a < b then -1 else if a > b then 1 else 0
              )), 'value')
            
            
            # Use a comparator function to figure out at what index an object should
            # be inserted so as to maintain order. Uses binary search.
            _.sortedIndex = (array, obj, iterator) ->
              iterator ||= _.identity
              low = 0
              high = array.length
              while low < high
                mid = (low + high) >> 1
                if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
              low
            
            
            # Convert anything iterable into a real, live array.
            _.toArray = (iterable) ->
              return [] if (!iterable)
              return iterable.toArray() if (iterable.toArray)
              return iterable if (_.isArray(iterable))
              return slice.call(iterable) if (_.isArguments(iterable))
              _.values(iterable)
            
            
            # Return the number of elements in an object.
            _.size = (obj) -> _.toArray(obj).length
            
            
            # Array Functions
            # ---------------
            
            # Get the first element of an array. Passing `n` will return the first N
            # values in the array. Aliased as **head**. The `guard` check allows it to work
            # with **map**.
            _.first = (array, n, guard) ->
              if n and not guard then slice.call(array, 0, n) else array[0]
            
            
            # Returns everything but the first entry of the array. Aliased as **tail**.
            # Especially useful on the arguments object. Passing an `index` will return
            # the rest of the values in the array from that index onward. The `guard`
            # check allows it to work with **map**.
            _.rest = (array, index, guard) ->
              slice.call(array, if _.isUndefined(index) or guard then 1 else index)
            
            
            # Get the last element of an array.
            _.last = (array) -> array[array.length - 1]
            
            
            # Trim out all falsy values from an array.
            _.compact = (array) -> item for item in array when item
            
            
            # Return a completely flattened version of an array.
            _.flatten = (array) ->
              _.reduce array, (memo, value) ->
                return memo.concat(_.flatten(value)) if _.isArray value
                memo.push value
                memo
              , []
            
            
            # Return a version of the array that does not contain the specified value(s).
            _.without = (array) ->
              values = _.rest arguments
              val for val in _.toArray(array) when not _.include values, val
            
            
            # Produce a duplicate-free version of the array. If the array has already
            # been sorted, you have the option of using a faster algorithm.
            _.uniq = (array, isSorted) ->
              memo = []
              for el, i in _.toArray array
                memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
              memo
            
            
            # Produce an array that contains every item shared between all the
            # passed-in arrays.
            _.intersect = (array) ->
              rest = _.rest arguments
              _.select _.uniq(array), (item) ->
                _.all rest, (other) ->
                  _.indexOf(other, item) >= 0
            
            
            # Zip together multiple lists into a single array -- elements that share
            # an index go together.
            _.zip = ->
              length = _.max _.pluck arguments, 'length'
              results = new Array length
              for i in [0...length]
                results[i] = _.pluck arguments, String i
              results
            
            
            # If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
            # we need this function. Return the position of the first occurrence of an
            # item in an array, or -1 if the item is not included in the array.
            _.indexOf = (array, item) ->
              return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
              i = 0; l = array.length
              while l - i
                if array[i] is item then return i else i++
              -1
            
            
            # Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
            # if possible.
            _.lastIndexOf = (array, item) ->
              return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
              i = array.length
              while i
                if array[i] is item then return i else i--
              -1
            
            
            # Generate an integer Array containing an arithmetic progression. A port of
            # [the native Python **range** function](http://docs.python.org/library/functions.html#range).
            _.range = (start, stop, step) ->
              a = arguments
              solo = a.length <= 1
              i = start = if solo then 0 else a[0]
              stop = if solo then a[0] else a[1]
              step = a[2] or 1
              len = Math.ceil((stop - start) / step)
              return [] if len <= 0
              range = new Array len
              idx = 0
              loop
                return range if (if step > 0 then i - stop else stop - i) >= 0
                range[idx] = i
                idx++
                i+= step
            
            
            # Function Functions
            # ------------------
            
            # Create a function bound to a given object (assigning `this`, and arguments,
            # optionally). Binding with arguments is also known as **curry**.
            _.bind = (func, obj) ->
              args = _.rest arguments, 2
              -> func.apply obj or root, args.concat arguments
            
            
            # Bind all of an object's methods to that object. Useful for ensuring that
            # all callbacks defined on an object belong to it.
            _.bindAll = (obj) ->
              funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
              _.each funcs, (f) -> obj[f] = _.bind obj[f], obj
              obj
            
            
            # Delays a function for the given number of milliseconds, and then calls
            # it with the arguments supplied.
            _.delay = (func, wait) ->
              args = _.rest arguments, 2
              setTimeout((-> func.apply(func, args)), wait)
            
            
            # Memoize an expensive function by storing its results.
            _.memoize = (func, hasher) ->
              memo = {}
              hasher or= _.identity
              ->
                key = hasher.apply this, arguments
                return memo[key] if key of memo
                memo[key] = func.apply this, arguments
            
            
            # Defers a function, scheduling it to run after the current call stack has
            # cleared.
            _.defer = (func) ->
              _.delay.apply _, [func, 1].concat _.rest arguments
            
            
            # Returns the first function passed as an argument to the second,
            # allowing you to adjust arguments, run code before and after, and
            # conditionally execute the original function.
            _.wrap = (func, wrapper) ->
              -> wrapper.apply wrapper, [func].concat arguments
            
            
            # Returns a function that is the composition of a list of functions, each
            # consuming the return value of the function that follows.
            _.compose = ->
              funcs = arguments
              ->
                args = arguments
                for i in [funcs.length - 1..0] by -1
                  args = [funcs[i].apply(this, args)]
                args[0]
            
            
            # Object Functions
            # ----------------
            
            # Retrieve the names of an object's properties.
            _.keys = nativeKeys or (obj) ->
              return _.range 0, obj.length if _.isArray(obj)
              key for key, val of obj
            
            
            # Retrieve the values of an object's properties.
            _.values = (obj) ->
              _.map obj, _.identity
            
            
            # Return a sorted list of the function names available in Underscore.
            _.functions = (obj) ->
              _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
            
            
            # Extend a given object with all of the properties in a source object.
            _.extend = (obj) ->
              for source in _.rest(arguments)
                obj[key] = val for key, val of source
              obj
            
            
            # Create a (shallow-cloned) duplicate of an object.
            _.clone = (obj) ->
              return obj.slice 0 if _.isArray obj
              _.extend {}, obj
            
            
            # Invokes interceptor with the obj, and then returns obj.
            # The primary purpose of this method is to "tap into" a method chain,
            # in order to perform operations on intermediate results within
             the chain.
            _.tap = (obj, interceptor) ->
              interceptor obj
              obj
            
            
            # Perform a deep comparison to check if two objects are equal.
            _.isEqual = (a, b) ->
              # Check object identity.
              return true if a is b
              # Different types?
              atype = typeof(a); btype = typeof(b)
              return false if atype isnt btype
              # Basic equality test (watch out for coercions).
              return true if `a == b`
              # One is falsy and the other truthy.
              return false if (!a and b) or (a and !b)
              # One of them implements an `isEqual()`?
              return a.isEqual(b) if a.isEqual
              # Check dates' integer values.
              return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
              # Both are NaN?
              return false if _.isNaN(a) and _.isNaN(b)
              # Compare regular expressions.
              if _.isRegExp(a) and _.isRegExp(b)
                return a.source is b.source and
                       a.global is b.global and
                       a.ignoreCase is b.ignoreCase and
                       a.multiline is b.multiline
              # If a is not an object by this point, we can't handle it.
              return false if atype isnt 'object'
              # Check for different array lengths before comparing contents.
              return false if a.length and (a.length isnt b.length)
              # Nothing else worked, deep compare the contents.
              aKeys = _.keys(a); bKeys = _.keys(b)
              # Different object sizes?
              return false if aKeys.length isnt bKeys.length
              # Recursive comparison of contents.
              return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
              true
            
            
            # Is a given array or object empty?
            _.isEmpty = (obj) ->
              return obj.length is 0 if _.isArray(obj) or _.isString(obj)
              return false for own key of obj
              true
            
            
            # Is a given value a DOM element?
            _.isElement = (obj) -> obj and obj.nodeType is 1
            
            
            # Is a given value an array?
            _.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
            
            
            # Is a given variable an arguments object?
            _.isArguments = (obj) -> obj and obj.callee
            
            
            # Is the given value a function?
            _.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
            
            
            # Is the given value a string?
            _.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
            
            
            # Is a given value a number?
            _.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
            
            
            # Is a given value a boolean?
            _.isBoolean = (obj) -> obj is true or obj is false
            
            
            # Is a given value a Date?
            _.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
            
            
            # Is the given value a regular expression?
            _.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
            
            
            # Is the given value NaN -- this one is interesting. `NaN != NaN`, and
            # `isNaN(undefined) == true`, so we make sure it's a number first.
            _.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
            
            
            # Is a given value equal to null?
            _.isNull = (obj) -> obj is null
            
            
            # Is a given variable undefined?
            _.isUndefined = (obj) -> typeof obj is 'undefined'
            
            
            # Utility Functions
            # -----------------
            
            # Run Underscore.js in noConflict mode, returning the `_` variable to its
            # previous owner. Returns a reference to the Underscore object.
            _.noConflict = ->
              root._ = previousUnderscore
              this
            
            
            # Keep the identity function around for default iterators.
            _.identity = (value) -> value
            
            
            # Run a function `n` times.
            _.times = (n, iterator, context) ->
              iterator.call context, i for i in [0...n]
            
            
            # Break out of the middle of an iteration.
            _.breakLoop = -> throw breaker
            
            
            # Add your own custom functions to the Underscore object, ensuring that
            # they're correctly added to the OOP wrapper as well.
            _.mixin = (obj) ->
              for name in _.functions(obj)
                addToWrapper name, _[name] = obj[name]
            
            
            # Generate a unique integer id (unique within the entire client session).
            # Useful for temporary DOM ids.
            idCounter = 0
            _.uniqueId = (prefix) ->
              (prefix or '') + idCounter++
            
            
            # By default, Underscore uses **ERB**-style template delimiters, change the
            # following template settings to use alternative delimiters.
            _.templateSettings = {
              start: '<%'
              end: '%>'
              interpolate: /<%=(.+?)%>/g
            }
            
            
            # JavaScript templating a-la **ERB**, pilfered from John Resig's
            # *Secrets of the JavaScript Ninja*, page 83.
            # Single-quote fix from Rick Strahl.
            # With alterations for arbitrary delimiters, and to preserve whitespace.
            _.template = (str, data) ->
              c = _.templateSettings
              endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
              fn = new Function 'obj',
                'var p=[],print=function(){p.push.apply(p,arguments);};' +
                'with(obj||{}){p.push(\'' +
                str.replace(/\r/g, '\\r')
                   .replace(/\n/g, '\\n')
                   .replace(/\t/g, '\\t')
                   .replace(endMatch,"���")
                   .split("'").join("\\'")
                   .split("���").join("'")
                   .replace(c.interpolate, "',$1,'")
                   .split(c.start).join("');")
                   .split(c.end).join("p.push('") +
                   "');}return p.join('');"
              if data then fn(data) else fn
            
            
            # Aliases
            # -------
            
            _.forEach = _.each
            _.foldl = _.inject = _.reduce
            _.foldr = _.reduceRight
            _.select = _.filter
            _.all = _.every
            _.any = _.some
            _.contains = _.include
            _.head = _.first
            _.tail = _.rest
            _.methods = _.functions
            
            
            # Setup the OOP Wrapper
            # ---------------------
            
            # If Underscore is called as a function, it returns a wrapped object that
            # can be used OO-style. This wrapper holds altered versions of all the
            # underscore functions. Wrapped objects may be chained.
            wrapper = (obj) ->
              this._wrapped = obj
              this
            
            
            # Helper function to continue chaining intermediate results.
            result = (obj, chain) ->
              if chain then _(obj).chain() else obj
            
            
            # A method to easily add functions to the OOP wrapper.
            addToWrapper = (name, func) ->
              wrapper.prototype[name] = ->
                args = _.toArray arguments
                unshift.call args, this._wrapped
                result func.apply(_, args), this._chain
            
            
            # Add all ofthe Underscore functions to the wrapper object.
            _.mixin _
            
            
            # Add all mutator Array functions to the wrapper.
            _.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
              method = Array.prototype[name]
              wrapper.prototype[name] = ->
                method.apply(this._wrapped, arguments)
                result(this._wrapped, this._chain)
            
            
            # Add all accessor Array functions to the wrapper.
            _.each ['concat', 'join', 'slice'], (name) ->
              method = Array.prototype[name]
              wrapper.prototype[name] = ->
                result(method.apply(this._wrapped, arguments), this._chain)
            
            
            # Start chaining a wrapped Underscore object.
            wrapper::chain = ->
              this._chain = true
              this
            
            
            # Extracts the result from a wrapped and chained object.
            wrapper::value = -> this._wrapped
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
            
                <p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
            
              </article>
            
        • commonlisp
          • commonlisp.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("commonlisp", function (config) {
              var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;
              var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
              var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
              var symbol = /[^\s'`,@()\[\]";]/;
              var type;
            
              function readSym(stream) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "\\") stream.next();
                  else if (!symbol.test(ch)) { stream.backUp(1); break; }
                }
                return stream.current();
              }
            
              function base(stream, state) {
                if (stream.eatSpace()) {type = "ws"; return null;}
                if (stream.match(numLiteral)) return "number";
                var ch = stream.next();
                if (ch == "\\") ch = stream.next();
            
                if (ch == '"') return (state.tokenize = inString)(stream, state);
                else if (ch == "(") { type = "open"; return "bracket"; }
                else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
                else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
                else if (/['`,@]/.test(ch)) return null;
                else if (ch == "|") {
                  if (stream.skipTo("|")) { stream.next(); return "symbol"; }
                  else { stream.skipToEnd(); return "error"; }
                } else if (ch == "#") {
                  var ch = stream.next();
                  if (ch == "[") { type = "open"; return "bracket"; }
                  else if (/[+\-=\.']/.test(ch)) return null;
                  else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null;
                  else if (ch == "|") return (state.tokenize = inComment)(stream, state);
                  else if (ch == ":") { readSym(stream); return "meta"; }
                  else return "error";
                } else {
                  var name = readSym(stream);
                  if (name == ".") return null;
                  type = "symbol";
                  if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";
                  if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";
                  if (name.charAt(0) == "&") return "variable-2";
                  return "variable";
                }
              }
            
              function inString(stream, state) {
                var escaped = false, next;
                while (next = stream.next()) {
                  if (next == '"' && !escaped) { state.tokenize = base; break; }
                  escaped = !escaped && next == "\\";
                }
                return "string";
              }
            
              function inComment(stream, state) {
                var next, last;
                while (next = stream.next()) {
                  if (next == "#" && last == "|") { state.tokenize = base; break; }
                  last = next;
                }
                type = "ws";
                return "comment";
              }
            
              return {
                startState: function () {
                  return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};
                },
            
                token: function (stream, state) {
                  if (stream.sol() && typeof state.ctx.indentTo != "number")
                    state.ctx.indentTo = state.ctx.start + 1;
            
                  type = null;
                  var style = state.tokenize(stream, state);
                  if (type != "ws") {
                    if (state.ctx.indentTo == null) {
                      if (type == "symbol" && assumeBody.test(stream.current()))
                        state.ctx.indentTo = state.ctx.start + config.indentUnit;
                      else
                        state.ctx.indentTo = "next";
                    } else if (state.ctx.indentTo == "next") {
                      state.ctx.indentTo = stream.column();
                    }
                    state.lastType = type;
                  }
                  if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
                  else if (type == "close") state.ctx = state.ctx.prev || state.ctx;
                  return style;
                },
            
                indent: function (state, _textAfter) {
                  var i = state.ctx.indentTo;
                  return typeof i == "number" ? i : state.ctx.start + 1;
                },
            
                lineComment: ";;",
                blockCommentStart: "#|",
                blockCommentEnd: "|#"
              };
            });
            
            CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Common Lisp mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="commonlisp.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Common Lisp</a>
              </ul>
            </div>
            
            <article>
            <h2>Common Lisp mode</h2>
            <form><textarea id="code" name="code">(in-package :cl-postgres)
            
            ;; These are used to synthesize reader and writer names for integer
            ;; reading/writing functions when the amount of bytes and the
            ;; signedness is known. Both the macro that creates the functions and
            ;; some macros that use them create names this way.
            (eval-when (:compile-toplevel :load-toplevel :execute)
              (defun integer-reader-name (bytes signed)
                (intern (with-standard-io-syntax
                          (format nil "~a~a~a~a" '#:read- (if signed "" '#:u) '#:int bytes))))
              (defun integer-writer-name (bytes signed)
                (intern (with-standard-io-syntax
                          (format nil "~a~a~a~a" '#:write- (if signed "" '#:u) '#:int bytes)))))
            
            (defmacro integer-reader (bytes)
              "Create a function to read integers from a binary stream."
              (let ((bits (* bytes 8)))
                (labels ((return-form (signed)
                           (if signed
                               `(if (logbitp ,(1- bits) result)
                                    (dpb result (byte ,(1- bits) 0) -1)
                                    result)
                               `result))
                         (generate-reader (signed)
                           `(defun ,(integer-reader-name bytes signed) (socket)
                              (declare (type stream socket)
                                       #.*optimize*)
                              ,(if (= bytes 1)
                                   `(let ((result (the (unsigned-byte 8) (read-byte socket))))
                                      (declare (type (unsigned-byte 8) result))
                                      ,(return-form signed))
                                   `(let ((result 0))
                                      (declare (type (unsigned-byte ,bits) result))
                                      ,@(loop :for byte :from (1- bytes) :downto 0
                                               :collect `(setf (ldb (byte 8 ,(* 8 byte)) result)
                                                               (the (unsigned-byte 8) (read-byte socket))))
                                      ,(return-form signed))))))
                  `(progn
            ;; This causes weird errors on SBCL in some circumstances. Disabled for now.
            ;;         (declaim (inline ,(integer-reader-name bytes t)
            ;;                          ,(integer-reader-name bytes nil)))
                     (declaim (ftype (function (t) (signed-byte ,bits))
                                     ,(integer-reader-name bytes t)))
                     ,(generate-reader t)
                     (declaim (ftype (function (t) (unsigned-byte ,bits))
                                     ,(integer-reader-name bytes nil)))
                     ,(generate-reader nil)))))
            
            (defmacro integer-writer (bytes)
              "Create a function to write integers to a binary stream."
              (let ((bits (* 8 bytes)))
                `(progn
                  (declaim (inline ,(integer-writer-name bytes t)
                                   ,(integer-writer-name bytes nil)))
                  (defun ,(integer-writer-name bytes nil) (socket value)
                    (declare (type stream socket)
                             (type (unsigned-byte ,bits) value)
                             #.*optimize*)
                    ,@(if (= bytes 1)
                          `((write-byte value socket))
                          (loop :for byte :from (1- bytes) :downto 0
                                :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
                                           socket)))
                    (values))
                  (defun ,(integer-writer-name bytes t) (socket value)
                    (declare (type stream socket)
                             (type (signed-byte ,bits) value)
                             #.*optimize*)
                    ,@(if (= bytes 1)
                          `((write-byte (ldb (byte 8 0) value) socket))
                          (loop :for byte :from (1- bytes) :downto 0
                                :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
                                           socket)))
                    (values)))))
            
            ;; All the instances of the above that we need.
            
            (integer-reader 1)
            (integer-reader 2)
            (integer-reader 4)
            (integer-reader 8)
            
            (integer-writer 1)
            (integer-writer 2)
            (integer-writer 4)
            
            (defun write-bytes (socket bytes)
              "Write a byte-array to a stream."
              (declare (type stream socket)
                       (type (simple-array (unsigned-byte 8)) bytes)
                       #.*optimize*)
              (write-sequence bytes socket))
            
            (defun write-str (socket string)
              "Write a null-terminated string to a stream \(encoding it when UTF-8
            support is enabled.)."
              (declare (type stream socket)
                       (type string string)
                       #.*optimize*)
              (enc-write-string string socket)
              (write-uint1 socket 0))
            
            (declaim (ftype (function (t unsigned-byte)
                                      (simple-array (unsigned-byte 8) (*)))
                            read-bytes))
            (defun read-bytes (socket length)
              "Read a byte array of the given length from a stream."
              (declare (type stream socket)
                       (type fixnum length)
                       #.*optimize*)
              (let ((result (make-array length :element-type '(unsigned-byte 8))))
                (read-sequence result socket)
                result))
            
            (declaim (ftype (function (t) string) read-str))
            (defun read-str (socket)
              "Read a null-terminated string from a stream. Takes care of encoding
            when UTF-8 support is enabled."
              (declare (type stream socket)
                       #.*optimize*)
              (enc-read-string socket :null-terminated t))
            
            (defun skip-bytes (socket length)
              "Skip a given number of bytes in a binary stream."
              (declare (type stream socket)
                       (type (unsigned-byte 32) length)
                       #.*optimize*)
              (dotimes (i length)
                (read-byte socket)))
            
            (defun skip-str (socket)
              "Skip a null-terminated string."
              (declare (type stream socket)
                       #.*optimize*)
              (loop :for char :of-type fixnum = (read-byte socket)
                    :until (zerop char)))
            
            (defun ensure-socket-is-closed (socket &amp;key abort)
              (when (open-stream-p socket)
                (handler-case
                    (close socket :abort abort)
                  (error (error)
                    (warn "Ignoring the error which happened while trying to close PostgreSQL socket: ~A" error)))))
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {lineNumbers: true});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-common-lisp</code>.</p>
            
              </article>
            
        • css
          • css.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("css", function(config, parserConfig) {
              if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
            
              var indentUnit = config.indentUnit,
                  tokenHooks = parserConfig.tokenHooks,
                  documentTypes = parserConfig.documentTypes || {},
                  mediaTypes = parserConfig.mediaTypes || {},
                  mediaFeatures = parserConfig.mediaFeatures || {},
                  propertyKeywords = parserConfig.propertyKeywords || {},
                  nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
                  fontProperties = parserConfig.fontProperties || {},
                  counterDescriptors = parserConfig.counterDescriptors || {},
                  colorKeywords = parserConfig.colorKeywords || {},
                  valueKeywords = parserConfig.valueKeywords || {},
                  allowNested = parserConfig.allowNested;
            
              var type, override;
              function ret(style, tp) { type = tp; return style; }
            
              // Tokenizers
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (tokenHooks[ch]) {
                  var result = tokenHooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == "@") {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("def", stream.current());
                } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
                  return ret(null, "compare");
                } else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (ch == "#") {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("atom", "hash");
                } else if (ch == "!") {
                  stream.match(/^\s*\w*/);
                  return ret("keyword", "important");
                } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
                  stream.eatWhile(/[\w.%]/);
                  return ret("number", "unit");
                } else if (ch === "-") {
                  if (/[\d.]/.test(stream.peek())) {
                    stream.eatWhile(/[\w.%]/);
                    return ret("number", "unit");
                  } else if (stream.match(/^-[\w\\\-]+/)) {
                    stream.eatWhile(/[\w\\\-]/);
                    if (stream.match(/^\s*:/, false))
                      return ret("variable-2", "variable-definition");
                    return ret("variable-2", "variable");
                  } else if (stream.match(/^\w+-/)) {
                    return ret("meta", "meta");
                  }
                } else if (/[,+>*\/]/.test(ch)) {
                  return ret(null, "select-op");
                } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
                  return ret("qualifier", "qualifier");
                } else if (/[:;{}\[\]\(\)]/.test(ch)) {
                  return ret(null, ch);
                } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
                           (ch == "d" && stream.match("omain(")) ||
                           (ch == "r" && stream.match("egexp("))) {
                  stream.backUp(1);
                  state.tokenize = tokenParenthesized;
                  return ret("property", "word");
                } else if (/[\w\\\-]/.test(ch)) {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("property", "word");
                } else {
                  return ret(null, null);
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      if (quote == ")") stream.backUp(1);
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  if (ch == quote || !escaped && quote != ")") state.tokenize = null;
                  return ret("string", "string");
                };
              }
            
              function tokenParenthesized(stream, state) {
                stream.next(); // Must be '('
                if (!stream.match(/\s*[\"\')]/, false))
                  state.tokenize = tokenString(")");
                else
                  state.tokenize = null;
                return ret(null, "(");
              }
            
              // Context management
            
              function Context(type, indent, prev) {
                this.type = type;
                this.indent = indent;
                this.prev = prev;
              }
            
              function pushContext(state, stream, type) {
                state.context = new Context(type, stream.indentation() + indentUnit, state.context);
                return type;
              }
            
              function popContext(state) {
                state.context = state.context.prev;
                return state.context.type;
              }
            
              function pass(type, stream, state) {
                return states[state.context.type](type, stream, state);
              }
              function popAndPass(type, stream, state, n) {
                for (var i = n || 1; i > 0; i--)
                  state.context = state.context.prev;
                return pass(type, stream, state);
              }
            
              // Parser
            
              function wordAsValue(stream) {
                var word = stream.current().toLowerCase();
                if (valueKeywords.hasOwnProperty(word))
                  override = "atom";
                else if (colorKeywords.hasOwnProperty(word))
                  override = "keyword";
                else
                  override = "variable";
              }
            
              var states = {};
            
              states.top = function(type, stream, state) {
                if (type == "{") {
                  return pushContext(state, stream, "block");
                } else if (type == "}" && state.context.prev) {
                  return popContext(state);
                } else if (/@(media|supports|(-moz-)?document)/.test(type)) {
                  return pushContext(state, stream, "atBlock");
                } else if (/@(font-face|counter-style)/.test(type)) {
                  state.stateArg = type;
                  return "restricted_atBlock_before";
                } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
                  return "keyframes";
                } else if (type && type.charAt(0) == "@") {
                  return pushContext(state, stream, "at");
                } else if (type == "hash") {
                  override = "builtin";
                } else if (type == "word") {
                  override = "tag";
                } else if (type == "variable-definition") {
                  return "maybeprop";
                } else if (type == "interpolation") {
                  return pushContext(state, stream, "interpolation");
                } else if (type == ":") {
                  return "pseudo";
                } else if (allowNested && type == "(") {
                  return pushContext(state, stream, "parens");
                }
                return state.context.type;
              };
            
              states.block = function(type, stream, state) {
                if (type == "word") {
                  var word = stream.current().toLowerCase();
                  if (propertyKeywords.hasOwnProperty(word)) {
                    override = "property";
                    return "maybeprop";
                  } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
                    override = "string-2";
                    return "maybeprop";
                  } else if (allowNested) {
                    override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
                    return "block";
                  } else {
                    override += " error";
                    return "maybeprop";
                  }
                } else if (type == "meta") {
                  return "block";
                } else if (!allowNested && (type == "hash" || type == "qualifier")) {
                  override = "error";
                  return "block";
                } else {
                  return states.top(type, stream, state);
                }
              };
            
              states.maybeprop = function(type, stream, state) {
                if (type == ":") return pushContext(state, stream, "prop");
                return pass(type, stream, state);
              };
            
              states.prop = function(type, stream, state) {
                if (type == ";") return popContext(state);
                if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
                if (type == "}" || type == "{") return popAndPass(type, stream, state);
                if (type == "(") return pushContext(state, stream, "parens");
            
                if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
                  override += " error";
                } else if (type == "word") {
                  wordAsValue(stream);
                } else if (type == "interpolation") {
                  return pushContext(state, stream, "interpolation");
                }
                return "prop";
              };
            
              states.propBlock = function(type, _stream, state) {
                if (type == "}") return popContext(state);
                if (type == "word") { override = "property"; return "maybeprop"; }
                return state.context.type;
              };
            
              states.parens = function(type, stream, state) {
                if (type == "{" || type == "}") return popAndPass(type, stream, state);
                if (type == ")") return popContext(state);
                if (type == "(") return pushContext(state, stream, "parens");
                if (type == "word") wordAsValue(stream);
                return "parens";
              };
            
              states.pseudo = function(type, stream, state) {
                if (type == "word") {
                  override = "variable-3";
                  return state.context.type;
                }
                return pass(type, stream, state);
              };
            
              states.atBlock = function(type, stream, state) {
                if (type == "(") return pushContext(state, stream, "atBlock_parens");
                if (type == "}") return popAndPass(type, stream, state);
                if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
            
                if (type == "word") {
                  var word = stream.current().toLowerCase();
                  if (word == "only" || word == "not" || word == "and" || word == "or")
                    override = "keyword";
                  else if (documentTypes.hasOwnProperty(word))
                    override = "tag";
                  else if (mediaTypes.hasOwnProperty(word))
                    override = "attribute";
                  else if (mediaFeatures.hasOwnProperty(word))
                    override = "property";
                  else if (propertyKeywords.hasOwnProperty(word))
                    override = "property";
                  else if (nonStandardPropertyKeywords.hasOwnProperty(word))
                    override = "string-2";
                  else if (valueKeywords.hasOwnProperty(word))
                    override = "atom";
                  else
                    override = "error";
                }
                return state.context.type;
              };
            
              states.atBlock_parens = function(type, stream, state) {
                if (type == ")") return popContext(state);
                if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
                return states.atBlock(type, stream, state);
              };
            
              states.restricted_atBlock_before = function(type, stream, state) {
                if (type == "{")
                  return pushContext(state, stream, "restricted_atBlock");
                if (type == "word" && state.stateArg == "@counter-style") {
                  override = "variable";
                  return "restricted_atBlock_before";
                }
                return pass(type, stream, state);
              };
            
              states.restricted_atBlock = function(type, stream, state) {
                if (type == "}") {
                  state.stateArg = null;
                  return popContext(state);
                }
                if (type == "word") {
                  if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
                      (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
                    override = "error";
                  else
                    override = "property";
                  return "maybeprop";
                }
                return "restricted_atBlock";
              };
            
              states.keyframes = function(type, stream, state) {
                if (type == "word") { override = "variable"; return "keyframes"; }
                if (type == "{") return pushContext(state, stream, "top");
                return pass(type, stream, state);
              };
            
              states.at = function(type, stream, state) {
                if (type == ";") return popContext(state);
                if (type == "{" || type == "}") return popAndPass(type, stream, state);
                if (type == "word") override = "tag";
                else if (type == "hash") override = "builtin";
                return "at";
              };
            
              states.interpolation = function(type, stream, state) {
                if (type == "}") return popContext(state);
                if (type == "{" || type == ";") return popAndPass(type, stream, state);
                if (type != "variable") override = "error";
                return "interpolation";
              };
            
              return {
                startState: function(base) {
                  return {tokenize: null,
                          state: "top",
                          stateArg: null,
                          context: new Context("top", base || 0, null)};
                },
            
                token: function(stream, state) {
                  if (!state.tokenize && stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style && typeof style == "object") {
                    type = style[1];
                    style = style[0];
                  }
                  override = style;
                  state.state = states[state.state](type, stream, state);
                  return override;
                },
            
                indent: function(state, textAfter) {
                  var cx = state.context, ch = textAfter && textAfter.charAt(0);
                  var indent = cx.indent;
                  if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
                  if (cx.prev &&
                      (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "restricted_atBlock") ||
                       ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
                       ch == "{" && (cx.type == "at" || cx.type == "atBlock"))) {
                    indent = cx.indent - indentUnit;
                    cx = cx.prev;
                  }
                  return indent;
                },
            
                electricChars: "}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                fold: "brace"
              };
            });
            
              function keySet(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) {
                  keys[array[i]] = true;
                }
                return keys;
              }
            
              var documentTypes_ = [
                "domain", "regexp", "url", "url-prefix"
              ], documentTypes = keySet(documentTypes_);
            
              var mediaTypes_ = [
                "all", "aural", "braille", "handheld", "print", "projection", "screen",
                "tty", "tv", "embossed"
              ], mediaTypes = keySet(mediaTypes_);
            
              var mediaFeatures_ = [
                "width", "min-width", "max-width", "height", "min-height", "max-height",
                "device-width", "min-device-width", "max-device-width", "device-height",
                "min-device-height", "max-device-height", "aspect-ratio",
                "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
                "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
                "max-color", "color-index", "min-color-index", "max-color-index",
                "monochrome", "min-monochrome", "max-monochrome", "resolution",
                "min-resolution", "max-resolution", "scan", "grid"
              ], mediaFeatures = keySet(mediaFeatures_);
            
              var propertyKeywords_ = [
                "align-content", "align-items", "align-self", "alignment-adjust",
                "alignment-baseline", "anchor-point", "animation", "animation-delay",
                "animation-direction", "animation-duration", "animation-fill-mode",
                "animation-iteration-count", "animation-name", "animation-play-state",
                "animation-timing-function", "appearance", "azimuth", "backface-visibility",
                "background", "background-attachment", "background-clip", "background-color",
                "background-image", "background-origin", "background-position",
                "background-repeat", "background-size", "baseline-shift", "binding",
                "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
                "bookmark-target", "border", "border-bottom", "border-bottom-color",
                "border-bottom-left-radius", "border-bottom-right-radius",
                "border-bottom-style", "border-bottom-width", "border-collapse",
                "border-color", "border-image", "border-image-outset",
                "border-image-repeat", "border-image-slice", "border-image-source",
                "border-image-width", "border-left", "border-left-color",
                "border-left-style", "border-left-width", "border-radius", "border-right",
                "border-right-color", "border-right-style", "border-right-width",
                "border-spacing", "border-style", "border-top", "border-top-color",
                "border-top-left-radius", "border-top-right-radius", "border-top-style",
                "border-top-width", "border-width", "bottom", "box-decoration-break",
                "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
                "caption-side", "clear", "clip", "color", "color-profile", "column-count",
                "column-fill", "column-gap", "column-rule", "column-rule-color",
                "column-rule-style", "column-rule-width", "column-span", "column-width",
                "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
                "cue-after", "cue-before", "cursor", "direction", "display",
                "dominant-baseline", "drop-initial-after-adjust",
                "drop-initial-after-align", "drop-initial-before-adjust",
                "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
                "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
                "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
                "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
                "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
                "font-stretch", "font-style", "font-synthesis", "font-variant",
                "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
                "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
                "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
                "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
                "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
                "grid-template", "grid-template-areas", "grid-template-columns",
                "grid-template-rows", "hanging-punctuation", "height", "hyphens",
                "icon", "image-orientation", "image-rendering", "image-resolution",
                "inline-box-align", "justify-content", "left", "letter-spacing",
                "line-break", "line-height", "line-stacking", "line-stacking-ruby",
                "line-stacking-shift", "line-stacking-strategy", "list-style",
                "list-style-image", "list-style-position", "list-style-type", "margin",
                "margin-bottom", "margin-left", "margin-right", "margin-top",
                "marker-offset", "marks", "marquee-direction", "marquee-loop",
                "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
                "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
                "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
                "opacity", "order", "orphans", "outline",
                "outline-color", "outline-offset", "outline-style", "outline-width",
                "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
                "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
                "page", "page-break-after", "page-break-before", "page-break-inside",
                "page-policy", "pause", "pause-after", "pause-before", "perspective",
                "perspective-origin", "pitch", "pitch-range", "play-during", "position",
                "presentation-level", "punctuation-trim", "quotes", "region-break-after",
                "region-break-before", "region-break-inside", "region-fragment",
                "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
                "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
                "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
                "shape-outside", "size", "speak", "speak-as", "speak-header",
                "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
                "tab-size", "table-layout", "target", "target-name", "target-new",
                "target-position", "text-align", "text-align-last", "text-decoration",
                "text-decoration-color", "text-decoration-line", "text-decoration-skip",
                "text-decoration-style", "text-emphasis", "text-emphasis-color",
                "text-emphasis-position", "text-emphasis-style", "text-height",
                "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
                "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
                "text-wrap", "top", "transform", "transform-origin", "transform-style",
                "transition", "transition-delay", "transition-duration",
                "transition-property", "transition-timing-function", "unicode-bidi",
                "vertical-align", "visibility", "voice-balance", "voice-duration",
                "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
                "voice-volume", "volume", "white-space", "widows", "width", "word-break",
                "word-spacing", "word-wrap", "z-index",
                // SVG-specific
                "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
                "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
                "color-interpolation", "color-interpolation-filters",
                "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
                "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
                "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
                "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
                "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
                "glyph-orientation-vertical", "text-anchor", "writing-mode"
              ], propertyKeywords = keySet(propertyKeywords_);
            
              var nonStandardPropertyKeywords_ = [
                "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
                "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
                "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
                "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
                "searchfield-results-decoration", "zoom"
              ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
            
              var fontProperties_ = [
                "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
                "font-stretch", "font-weight", "font-style"
              ], fontProperties = keySet(fontProperties_);
            
              var counterDescriptors_ = [
                "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
                "speak-as", "suffix", "symbols", "system"
              ], counterDescriptors = keySet(counterDescriptors_);
            
              var colorKeywords_ = [
                "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
                "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
                "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
                "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
                "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
                "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
                "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
                "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
                "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
                "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
                "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
                "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
                "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
                "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
                "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
                "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
                "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
                "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
                "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
                "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
                "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
                "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
                "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
                "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
                "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
                "whitesmoke", "yellow", "yellowgreen"
              ], colorKeywords = keySet(colorKeywords_);
            
              var valueKeywords_ = [
                "above", "absolute", "activeborder", "additive", "activecaption", "afar",
                "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
                "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
                "arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
                "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
                "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
                "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
                "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
                "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
                "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
                "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
                "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
                "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
                "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
                "decimal-leading-zero", "default", "default-button", "destination-atop",
                "destination-in", "destination-out", "destination-over", "devanagari",
                "disc", "discard", "disclosure-closed", "disclosure-open", "document",
                "dot-dash", "dot-dot-dash",
                "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
                "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
                "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
                "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
                "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
                "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
                "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
                "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
                "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
                "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes",
                "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
                "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
                "help", "hidden", "hide", "higher", "highlight", "highlighttext",
                "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
                "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
                "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
                "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
                "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
                "katakana", "katakana-iroha", "keep-all", "khmer",
                "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
                "landscape", "lao", "large", "larger", "left", "level", "lighter",
                "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
                "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
                "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
                "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
                "media-controls-background", "media-current-time-display",
                "media-fullscreen-button", "media-mute-button", "media-play-button",
                "media-return-to-realtime-button", "media-rewind-button",
                "media-seek-back-button", "media-seek-forward-button", "media-slider",
                "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
                "media-volume-slider-container", "media-volume-sliderthumb", "medium",
                "menu", "menulist", "menulist-button", "menulist-text",
                "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
                "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
                "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
                "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
                "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
                "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
                "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
                "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
                "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
                "progress", "push-button", "radial-gradient", "radio", "read-only",
                "read-write", "read-write-plaintext-only", "rectangle", "region",
                "relative", "repeat", "repeating-linear-gradient",
                "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
                "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
                "rotateZ", "round", "row-resize", "rtl", "run-in", "running",
                "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
                "scroll", "scrollbar", "se-resize", "searchfield",
                "searchfield-cancel-button", "searchfield-decoration",
                "searchfield-results-button", "searchfield-results-decoration",
                "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
                "simp-chinese-formal", "simp-chinese-informal", "single",
                "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
                "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
                "small", "small-caps", "small-caption", "smaller", "solid", "somali",
                "source-atop", "source-in", "source-out", "source-over", "space", "spell-out", "square",
                "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
                "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
                "table-caption", "table-cell", "table-column", "table-column-group",
                "table-footer-group", "table-header-group", "table-row", "table-row-group",
                "tamil",
                "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
                "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
                "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
                "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
                "trad-chinese-formal", "trad-chinese-informal",
                "translate", "translate3d", "translateX", "translateY", "translateZ",
                "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
                "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
                "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
                "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
                "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
                "window", "windowframe", "windowtext", "words", "x-large", "x-small", "xor",
                "xx-large", "xx-small"
              ], valueKeywords = keySet(valueKeywords_);
            
              var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(propertyKeywords_)
                .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
              CodeMirror.registerHelper("hintWords", "css", allWords);
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ["comment", "comment"];
              }
            
              function tokenSGMLComment(stream, state) {
                if (stream.skipTo("-->")) {
                  stream.match("-->");
                  state.tokenize = null;
                } else {
                  stream.skipToEnd();
                }
                return ["comment", "comment"];
              }
            
              CodeMirror.defineMIME("text/css", {
                documentTypes: documentTypes,
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                fontProperties: fontProperties,
                counterDescriptors: counterDescriptors,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                tokenHooks: {
                  "<": function(stream, state) {
                    if (!stream.match("!--")) return false;
                    state.tokenize = tokenSGMLComment;
                    return tokenSGMLComment(stream, state);
                  },
                  "/": function(stream, state) {
                    if (!stream.eat("*")) return false;
                    state.tokenize = tokenCComment;
                    return tokenCComment(stream, state);
                  }
                },
                name: "css"
              });
            
              CodeMirror.defineMIME("text/x-scss", {
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                fontProperties: fontProperties,
                allowNested: true,
                tokenHooks: {
                  "/": function(stream, state) {
                    if (stream.eat("/")) {
                      stream.skipToEnd();
                      return ["comment", "comment"];
                    } else if (stream.eat("*")) {
                      state.tokenize = tokenCComment;
                      return tokenCComment(stream, state);
                    } else {
                      return ["operator", "operator"];
                    }
                  },
                  ":": function(stream) {
                    if (stream.match(/\s*\{/))
                      return [null, "{"];
                    return false;
                  },
                  "$": function(stream) {
                    stream.match(/^[\w-]+/);
                    if (stream.match(/^\s*:/, false))
                      return ["variable-2", "variable-definition"];
                    return ["variable-2", "variable"];
                  },
                  "#": function(stream) {
                    if (!stream.eat("{")) return false;
                    return [null, "interpolation"];
                  }
                },
                name: "css",
                helperType: "scss"
              });
            
              CodeMirror.defineMIME("text/x-less", {
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                fontProperties: fontProperties,
                allowNested: true,
                tokenHooks: {
                  "/": function(stream, state) {
                    if (stream.eat("/")) {
                      stream.skipToEnd();
                      return ["comment", "comment"];
                    } else if (stream.eat("*")) {
                      state.tokenize = tokenCComment;
                      return tokenCComment(stream, state);
                    } else {
                      return ["operator", "operator"];
                    }
                  },
                  "@": function(stream) {
                    if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
                    stream.eatWhile(/[\w\\\-]/);
                    if (stream.match(/^\s*:/, false))
                      return ["variable-2", "variable-definition"];
                    return ["variable-2", "variable"];
                  },
                  "&": function() {
                    return ["atom", "atom"];
                  }
                },
                name: "css",
                helperType: "less"
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: CSS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="css.js"></script>
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/css-hint.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">CSS</a>
              </ul>
            </div>
            
            <article>
            <h2>CSS mode</h2>
            <form><textarea id="code" name="code">
            /* Some example CSS */
            
            @import url("something.css");
            
            body {
              margin: 0;
              padding: 3em 6em;
              font-family: tahoma, arial, sans-serif;
              color: #000;
            }
            
            #navigation a {
              font-weight: bold;
              text-decoration: none !important;
            }
            
            h1 {
              font-size: 2.5em;
            }
            
            h2 {
              font-size: 1.7em;
            }
            
            h1:before, h2:before {
              content: "::";
            }
            
            code {
              font-family: courier, monospace;
              font-size: 80%;
              color: #418A8A;
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href="scss.html">demo</a>), <code>text/x-less</code> (<a href="less.html">demo</a>).</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#css_*">normal</a>,  <a href="../../test/index.html#verbose,css_*">verbose</a>.</p>
            
              </article>
            
          • less.html
            <!doctype html>
            
            <title>CodeMirror: LESS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="css.js"></script>
            <style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">LESS</a>
              </ul>
            </div>
            
            <article>
            <h2>LESS mode</h2>
            <form><textarea id="code" name="code">@media screen and (device-aspect-ratio: 16/9) { … }
            @media screen and (device-aspect-ratio: 1280/720) { … }
            @media screen and (device-aspect-ratio: 2560/1440) { … }
            
            html:lang(fr-be)
            
            tr:nth-child(2n+1) /* represents every odd row of an HTML table */
            
            img:nth-of-type(2n+1) { float: right; }
            img:nth-of-type(2n) { float: left; }
            
            body > h2:not(:first-of-type):not(:last-of-type)
            
            html|*:not(:link):not(:visited)
            *|*:not(:hover)
            p::first-line { text-transform: uppercase }
            
            @namespace foo url(http://www.example.com);
            foo|h1 { color: blue }  /* first rule */
            
            span[hello="Ocean"][goodbye="Land"]
            
            E[foo]{
              padding:65px;
            }
            
            input[type="search"]::-webkit-search-decoration,
            input[type="search"]::-webkit-search-cancel-button {
              -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
            }
            button::-moz-focus-inner,
            input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
              padding: 0;
              border: 0;
            }
            .btn {
              // reset here as of 2.0.3 due to Recess property order
              border-color: #ccc;
              border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
            }
            fieldset span button, fieldset span input[type="file"] {
              font-size:12px;
            	font-family:Arial, Helvetica, sans-serif;
            }
            
            .rounded-corners (@radius: 5px) {
              border-radius: @radius;
              -webkit-border-radius: @radius;
              -moz-border-radius: @radius;
            }
            
            @import url("something.css");
            
            @light-blue:   hsl(190, 50%, 65%);
            
            #menu {
              position: absolute;
              width: 100%;
              z-index: 3;
              clear: both;
              display: block;
              background-color: @blue;
              height: 42px;
              border-top: 2px solid lighten(@alpha-blue, 20%);
              border-bottom: 2px solid darken(@alpha-blue, 25%);
              .box-shadow(0, 1px, 8px, 0.6);
              -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
            
              &.docked {
                background-color: hsla(210, 60%, 40%, 0.4);
              }
              &:hover {
                background-color: @blue;
              }
            
              #dropdown {
                margin: 0 0 0 117px;
                padding: 0;
                padding-top: 5px;
                display: none;
                width: 190px;
                border-top: 2px solid @medium;
                color: @highlight;
                border: 2px solid darken(@medium, 25%);
                border-left-color: darken(@medium, 15%);
                border-right-color: darken(@medium, 15%);
                border-top-width: 0;
                background-color: darken(@medium, 10%);
                ul {
                  padding: 0px;  
                }
                li {
                  font-size: 14px;
                  display: block;
                  text-align: left;
                  padding: 0;
                  border: 0;
                  a {
                    display: block;
                    padding: 0px 15px;  
                    text-decoration: none;
                    color: white;  
                    &:hover {
                      background-color: darken(@medium, 15%);
                      text-decoration: none;
                    }
                  }
                }
                .border-radius(5px, bottom);
                .box-shadow(0, 6px, 8px, 0.5);
              }
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers : true,
                    matchBrackets : true,
                    mode: "text/x-less"
                  });
                </script>
            
                <p>The LESS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#less_*">normal</a>,  <a href="../../test/index.html#verbose,less_*">verbose</a>.</p>
              </article>
            
          • less_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              "use strict";
            
              var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
            
              MT("variable",
                 "[variable-2 @base]: [atom #f04615];",
                 "[qualifier .class] {",
                 "  [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]",
                 "  [property color]: [variable saturate]([variable-2 @base], [number 5%]);",
                 "}");
            
              MT("amp",
                 "[qualifier .child], [qualifier .sibling] {",
                 "  [qualifier .parent] [atom &] {",
                 "    [property color]: [keyword black];",
                 "  }",
                 "  [atom &] + [atom &] {",
                 "    [property color]: [keyword red];",
                 "  }",
                 "}");
            
              MT("mixin",
                 "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
                 "  [property color]: [variable darken]([variable-2 @color], [number 10%]);",
                 "}",
                 "[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
                 "  [property color]: [variable lighten]([variable-2 @color], [number 10%]);",
                 "}",
                 "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
                 "  [property display]: [atom block];",
                 "}",
                 "[variable-2 @switch]: [variable light];",
                 "[qualifier .class] {",
                 "  [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
                 "}");
            
              MT("nest",
                 "[qualifier .one] {",
                 "  [def @media] ([property width]: [number 400px]) {",
                 "    [property font-size]: [number 1.2em];",
                 "    [def @media] [attribute print] [keyword and] [property color] {",
                 "      [property color]: [keyword blue];",
                 "    }",
                 "  }",
                 "}");
            })();
            
          • scss.html
            <!doctype html>
            
            <title>CodeMirror: SCSS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="css.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SCSS</a>
              </ul>
            </div>
            
            <article>
            <h2>SCSS mode</h2>
            <form><textarea id="code" name="code">
            /* Some example SCSS */
            
            @import "compass/css3";
            $variable: #333;
            
            $blue: #3bbfce;
            $margin: 16px;
            
            .content-navigation {
              #nested {
                background-color: black;
              }
              border-color: $blue;
              color:
                darken($blue, 9%);
            }
            
            .border {
              padding: $margin / 2;
              margin: $margin / 2;
              border-color: $blue;
            }
            
            @mixin table-base {
              th {
                text-align: center;
                font-weight: bold;
              }
              td, th {padding: 2px}
            }
            
            table.hl {
              margin: 2em 0;
              td.ln {
                text-align: right;
              }
            }
            
            li {
              font: {
                family: serif;
                weight: bold;
                size: 1.2em;
              }
            }
            
            @mixin left($dist) {
              float: left;
              margin-left: $dist;
            }
            
            #data {
              @include left(10px);
              @include table-base;
            }
            
            .source {
              @include flow-into(target);
              border: 10px solid green;
              margin: 20px;
              width: 200px; }
            
            .new-container {
              @include flow-from(target);
              border: 10px solid red;
              margin: 20px;
              width: 200px; }
            
            body {
              margin: 0;
              padding: 3em 6em;
              font-family: tahoma, arial, sans-serif;
              color: #000;
            }
            
            @mixin yellow() {
              background: yellow;
            }
            
            .big {
              font-size: 14px;
            }
            
            .nested {
              @include border-radius(3px);
              @extend .big;
              p {
                background: whitesmoke;
                a {
                  color: red;
                }
              }
            }
            
            #navigation a {
              font-weight: bold;
              text-decoration: none !important;
            }
            
            h1 {
              font-size: 2.5em;
            }
            
            h2 {
              font-size: 1.7em;
            }
            
            h1:before, h2:before {
              content: "::";
            }
            
            code {
              font-family: courier, monospace;
              font-size: 80%;
              color: #418A8A;
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-scss"
                  });
                </script>
            
                <p>The SCSS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#scss_*">normal</a>,  <a href="../../test/index.html#verbose,scss_*">verbose</a>.</p>
            
              </article>
            
          • scss_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
            
              MT('url_with_quotation',
                "[tag foo] { [property background]:[atom url]([string test.jpg]) }");
            
              MT('url_with_double_quotes',
                "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }");
            
              MT('url_with_single_quotes',
                "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }");
            
              MT('string',
                "[def @import] [string \"compass/css3\"]");
            
              MT('important_keyword',
                "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }");
            
              MT('variable',
                "[variable-2 $blue]:[atom #333]");
            
              MT('variable_as_attribute',
                "[tag foo] { [property color]:[variable-2 $blue] }");
            
              MT('numbers',
                "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }");
            
              MT('number_percentage',
                "[tag foo] { [property width]:[number 80%] }");
            
              MT('selector',
                "[builtin #hello][qualifier .world]{}");
            
              MT('singleline_comment',
                "[comment // this is a comment]");
            
              MT('multiline_comment',
                "[comment /*foobar*/]");
            
              MT('attribute_with_hyphen',
                "[tag foo] { [property font-size]:[number 10px] }");
            
              MT('string_after_attribute',
                "[tag foo] { [property content]:[string \"::\"] }");
            
              MT('directives',
                "[def @include] [qualifier .mixin]");
            
              MT('basic_structure',
                "[tag p] { [property background]:[keyword red]; }");
            
              MT('nested_structure',
                "[tag p] { [tag a] { [property color]:[keyword red]; } }");
            
              MT('mixin',
                "[def @mixin] [tag table-base] {}");
            
              MT('number_without_semicolon',
                "[tag p] {[property width]:[number 12]}",
                "[tag a] {[property color]:[keyword red];}");
            
              MT('atom_in_nested_block',
                "[tag p] { [tag a] { [property color]:[atom #000]; } }");
            
              MT('interpolation_in_property',
                "[tag foo] { #{[variable-2 $hello]}:[number 2]; }");
            
              MT('interpolation_in_selector',
                "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }");
            
              MT('interpolation_error',
                "[tag foo]#{[error foo]} { [property color]:[atom #000]; }");
            
              MT("divide_operator",
                "[tag foo] { [property width]:[number 4] [operator /] [number 2] }");
            
              MT('nested_structure_with_id_selector',
                "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
            
              MT('indent_mixin',
                 "[def @mixin] [tag container] (",
                 "  [variable-2 $a]: [number 10],",
                 "  [variable-2 $b]: [number 10])",
                 "{}");
            
              MT('indent_nested',
                 "[tag foo] {",
                 "  [tag bar] {",
                 "  }",
                 "}");
            
              MT('indent_parentheses',
                 "[tag foo] {",
                 "  [property color]: [variable darken]([variable-2 $blue],",
                 "    [number 9%]);",
                 "}");
            
              MT('indent_vardef',
                 "[variable-2 $name]:",
                 "  [string 'val'];",
                 "[tag tag] {",
                 "  [tag inner] {",
                 "    [property margin]: [number 3px];",
                 "  }",
                 "}");
            })();
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "css");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Error, because "foobarhello" is neither a known type or property, but
              // property was expected (after "and"), and it should be in parenthese.
              MT("atMediaUnknownType",
                 "[def @media] [attribute screen] [keyword and] [error foobarhello] { }");
            
              // Soft error, because "foobarhello" is not a known property or type.
              MT("atMediaUnknownProperty",
                 "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }");
            
              // Make sure nesting works with media queries
              MT("atMediaMaxWidthNested",
                 "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }");
            
              MT("tagSelector",
                 "[tag foo] { }");
            
              MT("classSelector",
                 "[qualifier .foo-bar_hello] { }");
            
              MT("idSelector",
                 "[builtin #foo] { [error #foo] }");
            
              MT("tagSelectorUnclosed",
                 "[tag foo] { [property margin]: [number 0] } [tag bar] { }");
            
              MT("tagStringNoQuotes",
                 "[tag foo] { [property font-family]: [variable hello] [variable world]; }");
            
              MT("tagStringDouble",
                 "[tag foo] { [property font-family]: [string \"hello world\"]; }");
            
              MT("tagStringSingle",
                 "[tag foo] { [property font-family]: [string 'hello world']; }");
            
              MT("tagColorKeyword",
                 "[tag foo] {",
                 "  [property color]: [keyword black];",
                 "  [property color]: [keyword navy];",
                 "  [property color]: [keyword yellow];",
                 "}");
            
              MT("tagColorHex3",
                 "[tag foo] { [property background]: [atom #fff]; }");
            
              MT("tagColorHex6",
                 "[tag foo] { [property background]: [atom #ffffff]; }");
            
              MT("tagColorHex4",
                 "[tag foo] { [property background]: [atom&error #ffff]; }");
            
              MT("tagColorHexInvalid",
                 "[tag foo] { [property background]: [atom&error #ffg]; }");
            
              MT("tagNegativeNumber",
                 "[tag foo] { [property margin]: [number -5px]; }");
            
              MT("tagPositiveNumber",
                 "[tag foo] { [property padding]: [number 5px]; }");
            
              MT("tagVendor",
                 "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }");
            
              MT("tagBogusProperty",
                 "[tag foo] { [property&error barhelloworld]: [number 0]; }");
            
              MT("tagTwoProperties",
                 "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }");
            
              MT("tagTwoPropertiesURL",
                 "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }");
            
              MT("commentSGML",
                 "[comment <!--comment-->]");
            
              MT("commentSGML2",
                 "[comment <!--comment]",
                 "[comment -->] [tag div] {}");
            
              MT("indent_tagSelector",
                 "[tag strong], [tag em] {",
                 "  [property background]: [atom rgba](",
                 "    [number 255], [number 255], [number 0], [number .2]",
                 "  );",
                 "}");
            
              MT("indent_atMedia",
                 "[def @media] {",
                 "  [tag foo] {",
                 "    [property color]:",
                 "      [keyword yellow];",
                 "  }",
                 "}");
            
              MT("indent_comma",
                 "[tag foo] {",
                 "  [property font-family]: [variable verdana],",
                 "    [atom sans-serif];",
                 "}");
            
              MT("indent_parentheses",
                 "[tag foo]:[variable-3 before] {",
                 "  [property background]: [atom url](",
                 "[string     blahblah]",
                 "[string     etc]",
                 "[string   ]) [keyword !important];",
                 "}");
            
              MT("font_face",
                 "[def @font-face] {",
                 "  [property font-family]: [string 'myfont'];",
                 "  [error nonsense]: [string 'abc'];",
                 "  [property src]: [atom url]([string http://blah]),",
                 "    [atom url]([string http://foo]);",
                 "}");
            
              MT("empty_url",
                 "[def @import] [tag url]() [tag screen];");
            
              MT("parens",
                 "[qualifier .foo] {",
                 "  [property background-image]: [variable fade]([atom #000], [number 20%]);",
                 "  [property border-image]: [atom linear-gradient](",
                 "    [atom to] [atom bottom],",
                 "    [variable fade]([atom #000], [number 20%]) [number 0%],",
                 "    [variable fade]([atom #000], [number 20%]) [number 100%]",
                 "  );",
                 "}");
            
              MT("css_variable",
                 ":[variable-3 root] {",
                 "  [variable-2 --main-color]: [atom #06c];",
                 "}",
                 "[tag h1][builtin #foo] {",
                 "  [property color]: [atom var]([variable-2 --main-color]);",
                 "}");
            
              MT("supports",
                 "[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {",
                 "  [property text-align-last]: [atom justify];",
                 "}");
            
               MT("document",
                  "[def @document] [tag url]([string http://blah]),",
                  "  [tag url-prefix]([string https://]),",
                  "  [tag domain]([string blah.com]),",
                  "  [tag regexp]([string \".*blah.+\"]) {",
                  "    [builtin #id] {",
                  "      [property background-color]: [keyword white];",
                  "    }",
                  "    [tag foo] {",
                  "      [property font-family]: [variable Verdana], [atom sans-serif];",
                  "    }",
                  "  }");
            
               MT("document_url",
                  "[def @document] [tag url]([string http://blah]) { [qualifier .class] { } }");
            
               MT("document_urlPrefix",
                  "[def @document] [tag url-prefix]([string https://]) { [builtin #id] { } }");
            
               MT("document_domain",
                  "[def @document] [tag domain]([string blah.com]) { [tag foo] { } }");
            
               MT("document_regexp",
                  "[def @document] [tag regexp]([string \".*blah.+\"]) { [builtin #id] { } }");
            
               MT("counter-style",
                  "[def @counter-style] [variable binary] {",
                  "  [property system]: [atom numeric];",
                  "  [property symbols]: [number 0] [number 1];",
                  "  [property suffix]: [string \".\"];",
                  "  [property range]: [atom infinite];",
                  "  [property speak-as]: [atom numeric];",
                  "}");
            
               MT("counter-style-additive-symbols",
                  "[def @counter-style] [variable simple-roman] {",
                  "  [property system]: [atom additive];",
                  "  [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];",
                  "  [property range]: [number 1] [number 49];",
                  "}");
            
               MT("counter-style-use",
                  "[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }");
            
               MT("counter-style-symbols",
                  "[tag ol] { [property list-style]: [atom symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }");
            })();
            
        • cypher
          • cypher.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // By the Neo4j Team and contributors.
            // https://github.com/neo4j-contrib/CodeMirror
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var wordRegexp = function(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              };
            
              CodeMirror.defineMode("cypher", function(config) {
                var tokenBase = function(stream/*, state*/) {
                  var ch = stream.next(), curPunc = null;
                  if (ch === "\"" || ch === "'") {
                    stream.match(/.+?["']/);
                    return "string";
                  }
                  if (/[{}\(\),\.;\[\]]/.test(ch)) {
                    curPunc = ch;
                    return "node";
                  } else if (ch === "/" && stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  } else if (operatorChars.test(ch)) {
                    stream.eatWhile(operatorChars);
                    return null;
                  } else {
                    stream.eatWhile(/[_\w\d]/);
                    if (stream.eat(":")) {
                      stream.eatWhile(/[\w\d_\-]/);
                      return "atom";
                    }
                    var word = stream.current();
                    if (funcs.test(word)) return "builtin";
                    if (preds.test(word)) return "def";
                    if (keywords.test(word)) return "keyword";
                    return "variable";
                  }
                };
                var pushContext = function(state, type, col) {
                  return state.context = {
                    prev: state.context,
                    indent: state.indent,
                    col: col,
                    type: type
                  };
                };
                var popContext = function(state) {
                  state.indent = state.context.indent;
                  return state.context = state.context.prev;
                };
                var indentUnit = config.indentUnit;
                var curPunc;
                var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
                var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]);
                var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
                var operatorChars = /[*+\-<>=&|~%^]/;
            
                return {
                  startState: function(/*base*/) {
                    return {
                      tokenize: tokenBase,
                      context: null,
                      indent: 0,
                      col: 0
                    };
                  },
                  token: function(stream, state) {
                    if (stream.sol()) {
                      if (state.context && (state.context.align == null)) {
                        state.context.align = false;
                      }
                      state.indent = stream.indentation();
                    }
                    if (stream.eatSpace()) {
                      return null;
                    }
                    var style = state.tokenize(stream, state);
                    if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") {
                      state.context.align = true;
                    }
                    if (curPunc === "(") {
                      pushContext(state, ")", stream.column());
                    } else if (curPunc === "[") {
                      pushContext(state, "]", stream.column());
                    } else if (curPunc === "{") {
                      pushContext(state, "}", stream.column());
                    } else if (/[\]\}\)]/.test(curPunc)) {
                      while (state.context && state.context.type === "pattern") {
                        popContext(state);
                      }
                      if (state.context && curPunc === state.context.type) {
                        popContext(state);
                      }
                    } else if (curPunc === "." && state.context && state.context.type === "pattern") {
                      popContext(state);
                    } else if (/atom|string|variable/.test(style) && state.context) {
                      if (/[\}\]]/.test(state.context.type)) {
                        pushContext(state, "pattern", stream.column());
                      } else if (state.context.type === "pattern" && !state.context.align) {
                        state.context.align = true;
                        state.context.col = stream.column();
                      }
                    }
                    return style;
                  },
                  indent: function(state, textAfter) {
                    var firstChar = textAfter && textAfter.charAt(0);
                    var context = state.context;
                    if (/[\]\}]/.test(firstChar)) {
                      while (context && context.type === "pattern") {
                        context = context.prev;
                      }
                    }
                    var closing = context && firstChar === context.type;
                    if (!context) return 0;
                    if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent;
                    if (context.align) return context.col + (closing ? 0 : 1);
                    return context.indent + (closing ? 0 : indentUnit);
                  }
                };
              });
            
              CodeMirror.modeExtensions["cypher"] = {
                autoFormatLineBreaks: function(text) {
                  var i, lines, reProcessedPortion;
                  var lines = text.split("\n");
                  var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g;
                  for (var i = 0; i < lines.length; i++)
                    lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim();
                  return lines.join("\n");
                }
              };
            
              CodeMirror.defineMIME("application/x-cypher-query", "cypher");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Cypher Mode for CodeMirror</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css" />
            <link rel="stylesheet" href="../../theme/neo.css" />
            <script src="../../lib/codemirror.js"></script>
            <script src="cypher.js"></script>
            <style>
            .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
            }
                    </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Cypher Mode for CodeMirror</a>
              </ul>
            </div>
            
            <article>
            <h2>Cypher Mode for CodeMirror</h2>
            <form>
                        <textarea id="code" name="code">// Cypher Mode for CodeMirror, using the neo theme
            MATCH (joe { name: 'Joe' })-[:knows*2..2]-(friend_of_friend)
            WHERE NOT (joe)-[:knows]-(friend_of_friend)
            RETURN friend_of_friend.name, COUNT(*)
            ORDER BY COUNT(*) DESC , friend_of_friend.name
            </textarea>
                        </form>
                        <p><strong>MIME types defined:</strong> 
                        <code><a href="?mime=application/x-cypher-query">application/x-cypher-query</a></code>
                    </p>
            <script>
            window.onload = function() {
              var mime = 'application/x-cypher-query';
              // get mime type
              if (window.location.href.indexOf('mime=') > -1) {
                mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);
              }
              window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: mime,
                indentWithTabs: true,
                smartIndent: true,
                lineNumbers: true,
                matchBrackets : true,
                autofocus: true,
                theme: 'neo'
              });
            };
            </script>
            
            </article>
            
        • d
          • d.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("d", function(config, parserConfig) {
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  keywords = parserConfig.keywords || {},
                  builtin = parserConfig.builtin || {},
                  blockKeywords = parserConfig.blockKeywords || {},
                  atoms = parserConfig.atoms || {},
                  hooks = parserConfig.hooks || {},
                  multiLineStrings = parserConfig.multiLineStrings;
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'" || ch == "`") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("+")) {
                    state.tokenize = tokenComment;
                    return tokenNestedComment(stream, state);
                  }
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenNestedComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "+");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                if (state.context && state.context.type == "statement")
                  indent = state.context.indented;
                return state.context = new Context(indent, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}"
              };
            });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var blockKeywords = "body catch class do else enum for foreach foreach_reverse if in interface mixin " +
                                  "out scope struct switch try union unittest version while with";
            
              CodeMirror.defineMIME("text/x-d", {
                name: "d",
                keywords: words("abstract alias align asm assert auto break case cast cdouble cent cfloat const continue " +
                                "debug default delegate delete deprecated export extern final finally function goto immutable " +
                                "import inout invariant is lazy macro module new nothrow override package pragma private " +
                                "protected public pure ref return shared short static super synchronized template this " +
                                "throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters " +
                                blockKeywords),
                blockKeywords: words(blockKeywords),
                builtin: words("bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte " +
                               "ucent uint ulong ushort wchar wstring void size_t sizediff_t"),
                atoms: words("exit failure success true false null"),
                hooks: {
                  "@": function(stream, _state) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: D mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="d.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">D</a>
              </ul>
            </div>
            
            <article>
            <h2>D mode</h2>
            <form><textarea id="code" name="code">
            /* D demo code // copied from phobos/sd/metastrings.d */
            // Written in the D programming language.
            
            /**
            Templates with which to do compile-time manipulation of strings.
            
            Macros:
             WIKI = Phobos/StdMetastrings
            
            Copyright: Copyright Digital Mars 2007 - 2009.
            License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
            Authors:   $(WEB digitalmars.com, Walter Bright),
                       Don Clugston
            Source:    $(PHOBOSSRC std/_metastrings.d)
            */
            /*
                     Copyright Digital Mars 2007 - 2009.
            Distributed under the Boost Software License, Version 1.0.
               (See accompanying file LICENSE_1_0.txt or copy at
                     http://www.boost.org/LICENSE_1_0.txt)
             */
            module std.metastrings;
            
            /**
            Formats constants into a string at compile time.  Analogous to $(XREF
            string,format).
            
            Parameters:
            
            A = tuple of constants, which can be strings, characters, or integral
                values.
            
            Formats:
             *    The formats supported are %s for strings, and %%
             *    for the % character.
            Example:
            ---
            import std.metastrings;
            import std.stdio;
            
            void main()
            {
              string s = Format!("Arg %s = %s", "foo", 27);
              writefln(s); // "Arg foo = 27"
            }
             * ---
             */
            
            template Format(A...)
            {
                static if (A.length == 0)
                    enum Format = "";
                else static if (is(typeof(A[0]) : const(char)[]))
                    enum Format = FormatString!(A[0], A[1..$]);
                else
                    enum Format = toStringNow!(A[0]) ~ Format!(A[1..$]);
            }
            
            template FormatString(const(char)[] F, A...)
            {
                static if (F.length == 0)
                    enum FormatString = Format!(A);
                else static if (F.length == 1)
                    enum FormatString = F[0] ~ Format!(A);
                else static if (F[0..2] == "%s")
                    enum FormatString
                        = toStringNow!(A[0]) ~ FormatString!(F[2..$],A[1..$]);
                else static if (F[0..2] == "%%")
                    enum FormatString = "%" ~ FormatString!(F[2..$],A);
                else
                {
                    static assert(F[0] != '%', "unrecognized format %" ~ F[1]);
                    enum FormatString = F[0] ~ FormatString!(F[1..$],A);
                }
            }
            
            unittest
            {
                auto s = Format!("hel%slo", "world", -138, 'c', true);
                assert(s == "helworldlo-138ctrue", "[" ~ s ~ "]");
            }
            
            /**
             * Convert constant argument to a string.
             */
            
            template toStringNow(ulong v)
            {
                static if (v < 10)
                    enum toStringNow = "" ~ cast(char)(v + '0');
                else
                    enum toStringNow = toStringNow!(v / 10) ~ toStringNow!(v % 10);
            }
            
            unittest
            {
                static assert(toStringNow!(1uL << 62) == "4611686018427387904");
            }
            
            /// ditto
            template toStringNow(long v)
            {
                static if (v < 0)
                    enum toStringNow = "-" ~ toStringNow!(cast(ulong) -v);
                else
                    enum toStringNow = toStringNow!(cast(ulong) v);
            }
            
            unittest
            {
                static assert(toStringNow!(0x100000000) == "4294967296");
                static assert(toStringNow!(-138L) == "-138");
            }
            
            /// ditto
            template toStringNow(uint U)
            {
                enum toStringNow = toStringNow!(cast(ulong)U);
            }
            
            /// ditto
            template toStringNow(int I)
            {
                enum toStringNow = toStringNow!(cast(long)I);
            }
            
            /// ditto
            template toStringNow(bool B)
            {
                enum toStringNow = B ? "true" : "false";
            }
            
            /// ditto
            template toStringNow(string S)
            {
                enum toStringNow = S;
            }
            
            /// ditto
            template toStringNow(char C)
            {
                enum toStringNow = "" ~ C;
            }
            
            
            /********
             * Parse unsigned integer literal from the start of string s.
             * returns:
             *    .value = the integer literal as a string,
             *    .rest = the string following the integer literal
             * Otherwise:
             *    .value = null,
             *    .rest = s
             */
            
            template parseUinteger(const(char)[] s)
            {
                static if (s.length == 0)
                {
                    enum value = "";
                    enum rest = "";
                }
                else static if (s[0] >= '0' && s[0] <= '9')
                {
                    enum value = s[0] ~ parseUinteger!(s[1..$]).value;
                    enum rest = parseUinteger!(s[1..$]).rest;
                }
                else
                {
                    enum value = "";
                    enum rest = s;
                }
            }
            
            /********
            Parse integer literal optionally preceded by $(D '-') from the start
            of string $(D s).
            
            Returns:
               .value = the integer literal as a string,
               .rest = the string following the integer literal
            
            Otherwise:
               .value = null,
               .rest = s
            */
            
            template parseInteger(const(char)[] s)
            {
                static if (s.length == 0)
                {
                    enum value = "";
                    enum rest = "";
                }
                else static if (s[0] >= '0' && s[0] <= '9')
                {
                    enum value = s[0] ~ parseUinteger!(s[1..$]).value;
                    enum rest = parseUinteger!(s[1..$]).rest;
                }
                else static if (s.length >= 2 &&
                        s[0] == '-' && s[1] >= '0' && s[1] <= '9')
                {
                    enum value = s[0..2] ~ parseUinteger!(s[2..$]).value;
                    enum rest = parseUinteger!(s[2..$]).rest;
                }
                else
                {
                    enum value = "";
                    enum rest = s;
                }
            }
            
            unittest
            {
                assert(parseUinteger!("1234abc").value == "1234");
                assert(parseUinteger!("1234abc").rest == "abc");
                assert(parseInteger!("-1234abc").value == "-1234");
                assert(parseInteger!("-1234abc").rest == "abc");
            }
            
            /**
            Deprecated aliases held for backward compatibility.
            */
            deprecated alias toStringNow ToString;
            /// Ditto
            deprecated alias parseUinteger ParseUinteger;
            /// Ditto
            deprecated alias parseUinteger ParseInteger;
            
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    indentUnit: 4,
                    mode: "text/x-d"
                  });
                </script>
            
                <p>Simple mode that handle D-Syntax (<a href="http://www.dlang.org">DLang Homepage</a>).</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-d</code>
                .</p>
              </article>
            
        • dart
          • dart.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../clike/clike"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../clike/clike"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var keywords = ("this super static final const abstract class extends external factory " +
                "implements get native operator set typedef with enum throw rethrow " +
                "assert break case continue default in return new deferred async await " +
                "try catch finally do else for if switch while import library export " +
                "part of show hide is").split(" ");
              var blockKeywords = "try catch finally do else for if switch while".split(" ");
              var atoms = "true false null".split(" ");
              var builtins = "void bool num int double dynamic var String".split(" ");
            
              function set(words) {
                var obj = {};
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              CodeMirror.defineMIME("application/dart", {
                name: "clike",
                keywords: set(keywords),
                multiLineStrings: true,
                blockKeywords: set(blockKeywords),
                builtin: set(builtins),
                atoms: set(atoms),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
              CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
            
              // This is needed to make loading through meta.js work.
              CodeMirror.defineMode("dart", function(conf) {
                return CodeMirror.getMode(conf, "application/dart");
              }, "clike");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dart mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="dart.js"></script>
            <style>.CodeMirror {border: 1px solid #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dart</a>
              </ul>
            </div>
            
            <article>
            <h2>Dart mode</h2>
            <form>
            <textarea id="code" name="code">
            import 'dart:math' show Random;
            
            void main() {
              print(new Die(n: 12).roll());
            }
            
            // Define a class.
            class Die {
              // Define a class variable.
              static Random shaker = new Random();
            
              // Define instance variables.
              int sides, value;
            
              // Define a method using shorthand syntax.
              String toString() => '$value';
            
              // Define a constructor.
              Die({int n: 6}) {
                if (4 <= n && n <= 20) {
                  sides = n;
                } else {
                  // Support for errors and exceptions.
                  throw new ArgumentError(/* */);
                }
              }
            
              // Define an instance method.
              int roll() {
                return value = shaker.nextInt(sides) + 1;
              }
            }
            </textarea>
            </form>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                mode: "application/dart"
              });
            </script>
            
            </article>
            
        • diff
          • diff.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("diff", function() {
            
              var TOKEN_NAMES = {
                '+': 'positive',
                '-': 'negative',
                '@': 'meta'
              };
            
              return {
                token: function(stream) {
                  var tw_pos = stream.string.search(/[\t ]+?$/);
            
                  if (!stream.sol() || tw_pos === 0) {
                    stream.skipToEnd();
                    return ("error " + (
                      TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');
                  }
            
                  var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();
            
                  if (tw_pos === -1) {
                    stream.skipToEnd();
                  } else {
                    stream.pos = tw_pos;
                  }
            
                  return token_name;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-diff", "diff");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Diff mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="diff.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}
                  span.cm-meta {color: #a0b !important;}
                  span.cm-error { background-color: black; opacity: 0.4;}
                  span.cm-error.cm-string { background-color: red; }
                  span.cm-error.cm-tag { background-color: #2b2; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Diff</a>
              </ul>
            </div>
            
            <article>
            <h2>Diff mode</h2>
            <form><textarea id="code" name="code">
            diff --git a/index.html b/index.html
            index c1d9156..7764744 100644
            --- a/index.html
            +++ b/index.html
            @@ -95,7 +95,8 @@ StringStream.prototype = {
                 <script>
                   var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                     lineNumbers: true,
            -        autoMatchBrackets: true
            +        autoMatchBrackets: true,
            +      onGutterClick: function(x){console.log(x);}
                   });
                 </script>
               </body>
            diff --git a/lib/codemirror.js b/lib/codemirror.js
            index 04646a9..9a39cc7 100644
            --- a/lib/codemirror.js
            +++ b/lib/codemirror.js
            @@ -399,10 +399,16 @@ var CodeMirror = (function() {
                 }
             
                 function onMouseDown(e) {
            -      var start = posFromMouse(e), last = start;    
            +      var start = posFromMouse(e), last = start, target = e.target();
                   if (!start) return;
                   setCursor(start.line, start.ch, false);
                   if (e.button() != 1) return;
            +      if (target.parentNode == gutter) {    
            +        if (options.onGutterClick)
            +          options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);
            +        return;
            +      }
            +
                   if (!focused) onFocus();
             
                   e.stop();
            @@ -808,7 +814,7 @@ var CodeMirror = (function() {
                   for (var i = showingFrom; i < showingTo; ++i) {
                     var marker = lines[i].gutterMarker;
                     if (marker) html.push('<div class="' + marker.style + '">' + htmlEscape(marker.text) + '</div>');
            -        else html.push("<div>" + (options.lineNumbers ? i + 1 : "\u00a0") + "</div>");
            +        else html.push("<div>" + (options.lineNumbers ? i + options.firstLineNumber : "\u00a0") + "</div>");
                   }
                   gutter.style.display = "none"; // TODO test whether this actually helps
                   gutter.innerHTML = html.join("");
            @@ -1371,10 +1377,8 @@ var CodeMirror = (function() {
                     if (option == "parser") setParser(value);
                     else if (option === "lineNumbers") setLineNumbers(value);
                     else if (option === "gutter") setGutter(value);
            -        else if (option === "readOnly") options.readOnly = value;
            -        else if (option === "indentUnit") {options.indentUnit = indentUnit = value; setParser(options.parser);}
            -        else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;
            -        else throw new Error("Can't set option " + option);
            +        else if (option === "indentUnit") {options.indentUnit = value; setParser(options.parser);}
            +        else options[option] = value;
                   },
                   cursorCoords: cursorCoords,
                   undo: operation(undo),
            @@ -1402,7 +1406,8 @@ var CodeMirror = (function() {
                   replaceRange: operation(replaceRange),
             
                   operation: function(f){return operation(f)();},
            -      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}
            +      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},
            +      getInputField: function(){return input;}
                 };
                 return instance;
               }
            @@ -1420,6 +1425,7 @@ var CodeMirror = (function() {
                 readOnly: false,
                 onChange: null,
                 onCursorActivity: null,
            +    onGutterClick: null,
                 autoMatchBrackets: false,
                 workTime: 200,
                 workDelay: 300,
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>
            
              </article>
            
        • django
          • django.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
                    require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
                        "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("django:inner", function() {
                var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
                                "loop", "none", "self", "super", "if", "endif", "as", "not", "and",
                                "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal",
                                "ifnotequal", "endifnotequal", "extends", "include", "load", "length", "comment",
                                "endcomment", "empty"];
                keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
            
                function tokenBase (stream, state) {
                  stream.eatWhile(/[^\{]/);
                  var ch = stream.next();
                  if (ch == "{") {
                    if (ch = stream.eat(/\{|%|#/)) {
                      state.tokenize = inTag(ch);
                      return "tag";
                    }
                  }
                }
                function inTag (close) {
                  if (close == "{") {
                    close = "}";
                  }
                  return function (stream, state) {
                    var ch = stream.next();
                    if ((ch == close) && stream.eat("}")) {
                      state.tokenize = tokenBase;
                      return "tag";
                    }
                    if (stream.match(keywords)) {
                      return "keyword";
                    }
                    return close == "#" ? "comment" : "string";
                  };
                }
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  }
                };
              });
            
              CodeMirror.defineMode("django", function(config) {
                var htmlBase = CodeMirror.getMode(config, "text/html");
                var djangoInner = CodeMirror.getMode(config, "django:inner");
                return CodeMirror.overlayMode(htmlBase, djangoInner);
              });
            
              CodeMirror.defineMIME("text/x-django", "django");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Django template mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="django.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Django</a>
              </ul>
            </div>
            
            <article>
            <h2>Django template mode</h2>
            <form><textarea id="code" name="code">
            <!doctype html>
            <html>
                <head>
                    <title>My Django web application</title>
                </head>
                <body>
                    <h1>
                        {{ page.title }}
                    </h1>
                    <ul class="my-list">
                        {% for item in items %}
                            <li>{% item.name %}</li>
                        {% empty %}
                            <li>You have no items in your list.</li>
                        {% endfor %}
                    </ul>
                </body>
            </html>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "django",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Mode for HTML with embedded Django template markup.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-django</code></p>
              </article>
            
        • dockerfile
          • dockerfile.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              // Collect all Dockerfile directives
              var instructions = ["from", "maintainer", "run", "cmd", "expose", "env",
                                  "add", "copy", "entrypoint", "volume", "user",
                                  "workdir", "onbuild"],
                  instructionRegex = "(" + instructions.join('|') + ")",
                  instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"),
                  instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i");
            
              CodeMirror.defineSimpleMode("dockerfile", {
                start: [
                  // Block comment: This is a line starting with a comment
                  {
                    regex: /#.*$/,
                    token: "comment"
                  },
                  // Highlight an instruction without any arguments (for convenience)
                  {
                    regex: instructionOnlyLine,
                    token: "variable-2"
                  },
                  // Highlight an instruction followed by arguments
                  {
                    regex: instructionWithArguments,
                    token: ["variable-2", null],
                    next: "arguments"
                  },
                  {
                    regex: /./,
                    token: null
                  }
                ],
                arguments: [
                  {
                    // Line comment without instruction arguments is an error
                    regex: /#.*$/,
                    token: "error",
                    next: "start"
                  },
                  {
                    regex: /[^#]+\\$/,
                    token: null
                  },
                  {
                    // Match everything except for the inline comment
                    regex: /[^#]+/,
                    token: null,
                    next: "start"
                  },
                  {
                    regex: /$/,
                    token: null,
                    next: "start"
                  },
                  // Fail safe return to start
                  {
                    token: null,
                    next: "start"
                  }
                ]
              });
            
              CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dockerfile mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/simple.js"></script>
            <script src="dockerfile.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dockerfile</a>
              </ul>
            </div>
            
            <article>
            <h2>Dockerfile mode</h2>
            <form><textarea id="code" name="code"># Install Ghost blogging platform and run development environment
            #
            # VERSION 1.0.0
            
            FROM ubuntu:12.10
            MAINTAINER Amer Grgic "amer@livebyt.es"
            WORKDIR /data/ghost
            
            # Install dependencies for nginx installation
            RUN apt-get update
            RUN apt-get install -y python g++ make software-properties-common --force-yes
            RUN add-apt-repository ppa:chris-lea/node.js
            RUN apt-get update
            # Install unzip
            RUN apt-get install -y unzip
            # Install curl
            RUN apt-get install -y curl
            # Install nodejs & npm
            RUN apt-get install -y rlwrap
            RUN apt-get install -y nodejs 
            # Download Ghost v0.4.1
            RUN curl -L https://ghost.org/zip/ghost-latest.zip -o /tmp/ghost.zip
            # Unzip Ghost zip to /data/ghost
            RUN unzip -uo /tmp/ghost.zip -d /data/ghost
            # Add custom config js to /data/ghost
            ADD ./config.example.js /data/ghost/config.js
            # Install Ghost with NPM
            RUN cd /data/ghost/ && npm install --production
            # Expose port 2368
            EXPOSE 2368
            # Run Ghost
            CMD ["npm","start"]
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "dockerfile"
                  });
                </script>
            
                <p>Dockerfile syntax highlighting for CodeMirror. Depends on
                the <a href="../../demo/simplemode.html">simplemode</a> addon.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-dockerfile</code></p>
              </article>
            
        • dtd
          • dtd.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
              DTD mode
              Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
              Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
              GitHub: @peterkroon
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("dtd", function(config) {
              var indentUnit = config.indentUnit, type;
              function ret(style, tp) {type = tp; return style;}
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                if (ch == "<" && stream.eat("!") ) {
                  if (stream.eatWhile(/[\-]/)) {
                    state.tokenize = tokenSGMLComment;
                    return tokenSGMLComment(stream, state);
                  } else if (stream.eatWhile(/[\w]/)) return ret("keyword", "doindent");
                } else if (ch == "<" && stream.eat("?")) { //xml declaration
                  state.tokenize = inBlock("meta", "?>");
                  return ret("meta", ch);
                } else if (ch == "#" && stream.eatWhile(/[\w]/)) return ret("atom", "tag");
                else if (ch == "|") return ret("keyword", "seperator");
                else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch);//if(ch === ">") return ret(null, "endtag"); else
                else if (ch.match(/[\[\]]/)) return ret("rule", ch);
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) {
                  var sc = stream.current();
                  if( sc.substr(sc.length-1,sc.length).match(/\?|\+/) !== null )stream.backUp(1);
                  return ret("tag", "tag");
                } else if (ch == "%" || ch == "*" ) return ret("number", "number");
                else {
                  stream.eatWhile(/[\w\\\-_%.{,]/);
                  return ret(null, null);
                }
              }
            
              function tokenSGMLComment(stream, state) {
                var dashes = 0, ch;
                while ((ch = stream.next()) != null) {
                  if (dashes >= 2 && ch == ">") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  dashes = (ch == "-") ? dashes + 1 : 0;
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return ret("string", "tag");
                };
              }
            
              function inBlock(style, terminator) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    stream.next();
                  }
                  return style;
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          stack: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  var context = state.stack[state.stack.length-1];
                  if (stream.current() == "[" || type === "doindent" || type == "[") state.stack.push("rule");
                  else if (type === "endtag") state.stack[state.stack.length-1] = "endtag";
                  else if (stream.current() == "]" || type == "]" || (type == ">" && context == "rule")) state.stack.pop();
                  else if (type == "[") state.stack.push("[");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var n = state.stack.length;
            
                  if( textAfter.match(/\]\s+|\]/) )n=n-1;
                  else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){
                    if(textAfter.substr(0,1) === "<")n;
                    else if( type == "doindent" && textAfter.length > 1 )n;
                    else if( type == "doindent")n--;
                    else if( type == ">" && textAfter.length > 1)n;
                    else if( type == "tag" && textAfter !== ">")n;
                    else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--;
                    else if( type == "tag")n++;
                    else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--;
                    else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule")n;
                    else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1;
                    else if( textAfter === ">")n;
                    else n=n-1;
                    //over rule them all
                    if(type == null || type == "]")n--;
                  }
            
                  return state.baseIndent + n * indentUnit;
                },
            
                electricChars: "]>"
              };
            });
            
            CodeMirror.defineMIME("application/xml-dtd", "dtd");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: DTD mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="dtd.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">DTD</a>
              </ul>
            </div>
            
            <article>
            <h2>DTD mode</h2>
            <form><textarea id="code" name="code"><?xml version="1.0" encoding="UTF-8"?>
            
            <!ATTLIST title
              xmlns	CDATA	#FIXED	"http://docbook.org/ns/docbook"
              role	CDATA	#IMPLIED
              %db.common.attributes;
              %db.common.linking.attributes;
            >
            
            <!--
              Try: http://docbook.org/xml/5.0/dtd/docbook.dtd
            -->
            
            <!DOCTYPE xsl:stylesheet
              [
                <!ENTITY nbsp   "&amp;#160;">
                <!ENTITY copy   "&amp;#169;">
                <!ENTITY reg    "&amp;#174;">
                <!ENTITY trade  "&amp;#8482;">
                <!ENTITY mdash  "&amp;#8212;">
                <!ENTITY ldquo  "&amp;#8220;">
                <!ENTITY rdquo  "&amp;#8221;">
                <!ENTITY pound  "&amp;#163;">
                <!ENTITY yen    "&amp;#165;">
                <!ENTITY euro   "&amp;#8364;">
                <!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
              ]
            >
            
            <!ELEMENT title (#PCDATA|inlinemediaobject|remark|superscript|subscript|xref|link|olink|anchor|biblioref|alt|annotation|indexterm|abbrev|acronym|date|emphasis|footnote|footnoteref|foreignphrase|phrase|quote|wordasword|firstterm|glossterm|coref|trademark|productnumber|productname|database|application|hardware|citation|citerefentry|citetitle|citebiblioid|author|person|personname|org|orgname|editor|jobtitle|replaceable|package|parameter|termdef|nonterminal|systemitem|option|optional|property|inlineequation|tag|markup|token|symbol|literal|code|constant|email|uri|guiicon|guibutton|guimenuitem|guimenu|guisubmenu|guilabel|menuchoice|mousebutton|keycombo|keycap|keycode|keysym|shortcut|accel|prompt|envar|filename|command|computeroutput|userinput|function|varname|returnvalue|type|classname|exceptionname|interfacename|methodname|modifier|initializer|ooclass|ooexception|oointerface|errorcode|errortext|errorname|errortype)*>
            
            <!ENTITY % db.common.attributes "
              xml:id	ID	#IMPLIED
              version	CDATA	#IMPLIED
              xml:lang	CDATA	#IMPLIED
              xml:base	CDATA	#IMPLIED
              remap	CDATA	#IMPLIED
              xreflabel	CDATA	#IMPLIED
              revisionflag	(changed|added|deleted|off)	#IMPLIED
              dir	(ltr|rtl|lro|rlo)	#IMPLIED
              arch	CDATA	#IMPLIED
              audience	CDATA	#IMPLIED
              condition	CDATA	#IMPLIED
              conformance	CDATA	#IMPLIED
              os	CDATA	#IMPLIED
              revision	CDATA	#IMPLIED
              security	CDATA	#IMPLIED
              userlevel	CDATA	#IMPLIED
              vendor	CDATA	#IMPLIED
              wordsize	CDATA	#IMPLIED
              annotations	CDATA	#IMPLIED
            
            "></textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "dtd", alignCDATA: true},
                    lineNumbers: true,
                    lineWrapping: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/xml-dtd</code>.</p>
              </article>
            
        • dylan
          • dylan.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("dylan", function(_config) {
              // Words
              var words = {
                // Words that introduce unnamed definitions like "define interface"
                unnamedDefinition: ["interface"],
            
                // Words that introduce simple named definitions like "define library"
                namedDefinition: ["module", "library", "macro",
                                  "C-struct", "C-union",
                                  "C-function", "C-callable-wrapper"
                                 ],
            
                // Words that introduce type definitions like "define class".
                // These are also parameterized like "define method" and are
                // appended to otherParameterizedDefinitionWords
                typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"],
            
                // Words that introduce trickier definitions like "define method".
                // These require special definitions to be added to startExpressions
                otherParameterizedDefinition: ["method", "function",
                                               "C-variable", "C-address"
                                              ],
            
                // Words that introduce module constant definitions.
                // These must also be simple definitions and are
                // appended to otherSimpleDefinitionWords
                constantSimpleDefinition: ["constant"],
            
                // Words that introduce module variable definitions.
                // These must also be simple definitions and are
                // appended to otherSimpleDefinitionWords
                variableSimpleDefinition: ["variable"],
            
                // Other words that introduce simple definitions
                // (without implicit bodies).
                otherSimpleDefinition: ["generic", "domain",
                                        "C-pointer-type",
                                        "table"
                                       ],
            
                // Words that begin statements with implicit bodies.
                statement: ["if", "block", "begin", "method", "case",
                            "for", "select", "when", "unless", "until",
                            "while", "iterate", "profiling", "dynamic-bind"
                           ],
            
                // Patterns that act as separators in compound statements.
                // This may include any general pattern that must be indented
                // specially.
                separator: ["finally", "exception", "cleanup", "else",
                            "elseif", "afterwards"
                           ],
            
                // Keywords that do not require special indentation handling,
                // but which should be highlighted
                other: ["above", "below", "by", "from", "handler", "in",
                        "instance", "let", "local", "otherwise", "slot",
                        "subclass", "then", "to", "keyed-by", "virtual"
                       ],
            
                // Condition signaling function calls
                signalingCalls: ["signal", "error", "cerror",
                                 "break", "check-type", "abort"
                                ]
              };
            
              words["otherDefinition"] =
                words["unnamedDefinition"]
                .concat(words["namedDefinition"])
                .concat(words["otherParameterizedDefinition"]);
            
              words["definition"] =
                words["typeParameterizedDefinition"]
                .concat(words["otherDefinition"]);
            
              words["parameterizedDefinition"] =
                words["typeParameterizedDefinition"]
                .concat(words["otherParameterizedDefinition"]);
            
              words["simpleDefinition"] =
                words["constantSimpleDefinition"]
                .concat(words["variableSimpleDefinition"])
                .concat(words["otherSimpleDefinition"]);
            
              words["keyword"] =
                words["statement"]
                .concat(words["separator"])
                .concat(words["other"]);
            
              // Patterns
              var symbolPattern = "[-_a-zA-Z?!*@<>$%]+";
              var symbol = new RegExp("^" + symbolPattern);
              var patterns = {
                // Symbols with special syntax
                symbolKeyword: symbolPattern + ":",
                symbolClass: "<" + symbolPattern + ">",
                symbolGlobal: "\\*" + symbolPattern + "\\*",
                symbolConstant: "\\$" + symbolPattern
              };
              var patternStyles = {
                symbolKeyword: "atom",
                symbolClass: "tag",
                symbolGlobal: "variable-2",
                symbolConstant: "variable-3"
              };
            
              // Compile all patterns to regular expressions
              for (var patternName in patterns)
                if (patterns.hasOwnProperty(patternName))
                  patterns[patternName] = new RegExp("^" + patterns[patternName]);
            
              // Names beginning "with-" and "without-" are commonly
              // used as statement macro
              patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];
            
              var styles = {};
              styles["keyword"] = "keyword";
              styles["definition"] = "def";
              styles["simpleDefinition"] = "def";
              styles["signalingCalls"] = "builtin";
            
              // protected words lookup table
              var wordLookup = {};
              var styleLookup = {};
            
              [
                "keyword",
                "definition",
                "simpleDefinition",
                "signalingCalls"
              ].forEach(function(type) {
                words[type].forEach(function(word) {
                  wordLookup[word] = type;
                  styleLookup[word] = styles[type];
                });
              });
            
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              var type, content;
            
              function ret(_type, style, _content) {
                type = _type;
                content = _content;
                return style;
              }
            
              function tokenBase(stream, state) {
                // String
                var ch = stream.peek();
                if (ch == "'" || ch == '"') {
                  stream.next();
                  return chain(stream, state, tokenString(ch, "string", "string"));
                }
                // Comment
                else if (ch == "/") {
                  stream.next();
                  if (stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  } else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  } else {
                    stream.skipTo(" ");
                    return ret("operator", "operator");
                  }
                }
                // Decimal
                else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/);
                  return ret("number", "number");
                }
                // Hash
                else if (ch == "#") {
                  stream.next();
                  // Symbol with string syntax
                  ch = stream.peek();
                  if (ch == '"') {
                    stream.next();
                    return chain(stream, state, tokenString('"', "symbol", "string-2"));
                  }
                  // Binary number
                  else if (ch == "b") {
                    stream.next();
                    stream.eatWhile(/[01]/);
                    return ret("number", "number");
                  }
                  // Hex number
                  else if (ch == "x") {
                    stream.next();
                    stream.eatWhile(/[\da-f]/i);
                    return ret("number", "number");
                  }
                  // Octal number
                  else if (ch == "o") {
                    stream.next();
                    stream.eatWhile(/[0-7]/);
                    return ret("number", "number");
                  }
                  // Hash symbol
                  else {
                    stream.eatWhile(/[-a-zA-Z]/);
                    return ret("hash", "keyword");
                  }
                } else if (stream.match("end")) {
                  return ret("end", "keyword");
                }
                for (var name in patterns) {
                  if (patterns.hasOwnProperty(name)) {
                    var pattern = patterns[name];
                    if ((pattern instanceof Array && pattern.some(function(p) {
                      return stream.match(p);
                    })) || stream.match(pattern))
                      return ret(name, patternStyles[name], stream.current());
                  }
                }
                if (stream.match("define")) {
                  return ret("definition", "def");
                } else {
                  stream.eatWhile(/[\w\-]/);
                  // Keyword
                  if (wordLookup[stream.current()]) {
                    return ret(wordLookup[stream.current()], styleLookup[stream.current()], stream.current());
                  } else if (stream.current().match(symbol)) {
                    return ret("variable", "variable");
                  } else {
                    stream.next();
                    return ret("other", "variable-2");
                  }
                }
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false,
                ch;
                while ((ch = stream.next())) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote, type, style) {
                return function(stream, state) {
                  var next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote) {
                      end = true;
                      break;
                    }
                  }
                  if (end)
                    state.tokenize = tokenBase;
                  return ret(type, style);
                };
              }
            
              // Interface
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    currentIndent: 0
                  };
                },
                token: function(stream, state) {
                  if (stream.eatSpace())
                    return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
                blockCommentStart: "/*",
                blockCommentEnd: "*/"
              };
            });
            
            CodeMirror.defineMIME("text/x-dylan", "dylan");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dylan mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="dylan.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dylan</a>
              </ul>
            </div>
            
            <article>
            <h2>Dylan mode</h2>
            
            
            <div><textarea id="code" name="code">
            Module:       locators-internals
            Synopsis:     Abstract modeling of locations
            Author:       Andy Armstrong
            Copyright:    Original Code is Copyright (c) 1995-2004 Functional Objects, Inc.
                          All rights reserved.
            License:      See License.txt in this distribution for details.
            Warranty:     Distributed WITHOUT WARRANTY OF ANY KIND
            
            define open generic locator-server
                (locator :: <locator>) => (server :: false-or(<server-locator>));
            define open generic locator-host
                (locator :: <locator>) => (host :: false-or(<string>));
            define open generic locator-volume
                (locator :: <locator>) => (volume :: false-or(<string>));
            define open generic locator-directory
                (locator :: <locator>) => (directory :: false-or(<directory-locator>));
            define open generic locator-relative?
                (locator :: <locator>) => (relative? :: <boolean>);
            define open generic locator-path
                (locator :: <locator>) => (path :: <sequence>);
            define open generic locator-base
                (locator :: <locator>) => (base :: false-or(<string>));
            define open generic locator-extension
                (locator :: <locator>) => (extension :: false-or(<string>));
            
            /// Locator classes
            
            define open abstract class <directory-locator> (<physical-locator>)
            end class <directory-locator>;
            
            define open abstract class <file-locator> (<physical-locator>)
            end class <file-locator>;
            
            define method as
                (class == <directory-locator>, string :: <string>)
             => (locator :: <directory-locator>)
              as(<native-directory-locator>, string)
            end method as;
            
            define method make
                (class == <directory-locator>,
                 #key server :: false-or(<server-locator>) = #f,
                      path :: <sequence> = #[],
                      relative? :: <boolean> = #f,
                      name :: false-or(<string>) = #f)
             => (locator :: <directory-locator>)
              make(<native-directory-locator>,
                   server:    server,
                   path:      path,
                   relative?: relative?,
                   name:      name)
            end method make;
            
            define method as
                (class == <file-locator>, string :: <string>)
             => (locator :: <file-locator>)
              as(<native-file-locator>, string)
            end method as;
            
            define method make
                (class == <file-locator>,
                 #key directory :: false-or(<directory-locator>) = #f,
                      base :: false-or(<string>) = #f,
                      extension :: false-or(<string>) = #f,
                      name :: false-or(<string>) = #f)
             => (locator :: <file-locator>)
              make(<native-file-locator>,
                   directory: directory,
                   base:      base,
                   extension: extension,
                   name:      name)
            end method make;
            
            /// Locator coercion
            
            //---*** andrewa: This caching scheme doesn't work yet, so disable it.
            define constant $cache-locators?        = #f;
            define constant $cache-locator-strings? = #f;
            
            define constant $locator-to-string-cache = make(<object-table>, weak: #"key");
            define constant $string-to-locator-cache = make(<string-table>, weak: #"value");
            
            define open generic locator-as-string
                (class :: subclass(<string>), locator :: <locator>)
             => (string :: <string>);
            
            define open generic string-as-locator
                (class :: subclass(<locator>), string :: <string>)
             => (locator :: <locator>);
            
            define sealed sideways method as
                (class :: subclass(<string>), locator :: <locator>)
             => (string :: <string>)
              let string = element($locator-to-string-cache, locator, default: #f);
              if (string)
                as(class, string)
              else
                let string = locator-as-string(class, locator);
                if ($cache-locator-strings?)
                  element($locator-to-string-cache, locator) := string;
                else
                  string
                end
              end
            end method as;
            
            define sealed sideways method as
                (class :: subclass(<locator>), string :: <string>)
             => (locator :: <locator>)
              let locator = element($string-to-locator-cache, string, default: #f);
              if (instance?(locator, class))
                locator
              else
                let locator = string-as-locator(class, string);
                if ($cache-locators?)
                  element($string-to-locator-cache, string) := locator;
                else
                  locator
                end
              end
            end method as;
            
            /// Locator conditions
            
            define class <locator-error> (<format-string-condition>, <error>)
            end class <locator-error>;
            
            define function locator-error
                (format-string :: <string>, #rest format-arguments)
              error(make(<locator-error>, 
                         format-string:    format-string,
                         format-arguments: format-arguments))
            end function locator-error;
            
            /// Useful locator protocols
            
            define open generic locator-test
                (locator :: <directory-locator>) => (test :: <function>);
            
            define method locator-test
                (locator :: <directory-locator>) => (test :: <function>)
              \=
            end method locator-test;
            
            define open generic locator-might-have-links?
                (locator :: <directory-locator>) => (links? :: <boolean>);
            
            define method locator-might-have-links?
                (locator :: <directory-locator>) => (links? :: singleton(#f))
              #f
            end method locator-might-have-links?;
            
            define method locator-relative?
                (locator :: <file-locator>) => (relative? :: <boolean>)
              let directory = locator.locator-directory;
              ~directory | directory.locator-relative?
            end method locator-relative?;
            
            define method current-directory-locator?
                (locator :: <directory-locator>) => (current-directory? :: <boolean>)
              locator.locator-relative?
                & locator.locator-path = #[#"self"]
            end method current-directory-locator?;
            
            define method locator-directory
                (locator :: <directory-locator>) => (parent :: false-or(<directory-locator>))
              let path = locator.locator-path;
              unless (empty?(path))
                make(object-class(locator),
                     server:    locator.locator-server,
                     path:      copy-sequence(path, end: path.size - 1),
                     relative?: locator.locator-relative?)
              end
            end method locator-directory;
            
            /// Simplify locator
            
            define open generic simplify-locator
                (locator :: <physical-locator>)
             => (simplified-locator :: <physical-locator>);
            
            define method simplify-locator
                (locator :: <directory-locator>)
             => (simplified-locator :: <directory-locator>)
              let path = locator.locator-path;
              let relative? = locator.locator-relative?;
              let resolve-parent? = ~locator.locator-might-have-links?;
              let simplified-path
                = simplify-path(path, 
                                resolve-parent?: resolve-parent?,
                                relative?: relative?);
              if (path ~= simplified-path)
                make(object-class(locator),
                     server:    locator.locator-server,
                     path:      simplified-path,
                     relative?: locator.locator-relative?)
              else
                locator
              end
            end method simplify-locator;
            
            define method simplify-locator
                (locator :: <file-locator>) => (simplified-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let simplified-directory = directory & simplify-locator(directory);
              if (directory ~= simplified-directory)
                make(object-class(locator),
                     directory: simplified-directory,
                     base:      locator.locator-base,
                     extension: locator.locator-extension)
              else
                locator
              end
            end method simplify-locator;
            
            /// Subdirectory locator
            
            define open generic subdirectory-locator
                (locator :: <directory-locator>, #rest sub-path)
             => (subdirectory :: <directory-locator>);
            
            define method subdirectory-locator
                (locator :: <directory-locator>, #rest sub-path)
             => (subdirectory :: <directory-locator>)
              let old-path = locator.locator-path;
              let new-path = concatenate-as(<simple-object-vector>, old-path, sub-path);
              make(object-class(locator),
                   server:    locator.locator-server,
                   path:      new-path,
                   relative?: locator.locator-relative?)
            end method subdirectory-locator;
            
            /// Relative locator
            
            define open generic relative-locator
                (locator :: <physical-locator>, from-locator :: <physical-locator>)
             => (relative-locator :: <physical-locator>);
            
            define method relative-locator
                (locator :: <directory-locator>, from-locator :: <directory-locator>)
             => (relative-locator :: <directory-locator>)
              let path = locator.locator-path;
              let from-path = from-locator.locator-path;
              case
                ~locator.locator-relative? & from-locator.locator-relative? =>
                  locator-error
                    ("Cannot find relative path of absolute locator %= from relative locator %=",
                     locator, from-locator);
                locator.locator-server ~= from-locator.locator-server =>
                  locator;
                path = from-path =>
                  make(object-class(locator),
                       path: vector(#"self"),
                       relative?: #t);
                otherwise =>
                  make(object-class(locator),
                       path: relative-path(path, from-path, test: locator.locator-test),
                       relative?: #t);
              end
            end method relative-locator;
            
            define method relative-locator
                (locator :: <file-locator>, from-directory :: <directory-locator>)
             => (relative-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let relative-directory = directory & relative-locator(directory, from-directory);
              if (relative-directory ~= directory)
                simplify-locator
                  (make(object-class(locator),
                        directory: relative-directory,
                        base:      locator.locator-base,
                        extension: locator.locator-extension))
              else
                locator
              end
            end method relative-locator;
            
            define method relative-locator
                (locator :: <physical-locator>, from-locator :: <file-locator>)
             => (relative-locator :: <physical-locator>)
              let from-directory = from-locator.locator-directory;
              case
                from-directory =>
                  relative-locator(locator, from-directory);
                ~locator.locator-relative? =>
                  locator-error
                    ("Cannot find relative path of absolute locator %= from relative locator %=",
                     locator, from-locator);
                otherwise =>
                  locator;
              end
            end method relative-locator;
            
            /// Merge locators
            
            define open generic merge-locators
                (locator :: <physical-locator>, from-locator :: <physical-locator>)
             => (merged-locator :: <physical-locator>);
            
            /// Merge locators
            
            define method merge-locators
                (locator :: <directory-locator>, from-locator :: <directory-locator>)
             => (merged-locator :: <directory-locator>)
              if (locator.locator-relative?)
                let path = concatenate(from-locator.locator-path, locator.locator-path);
                simplify-locator
                  (make(object-class(locator),
                        server:    from-locator.locator-server,
                        path:      path,
                        relative?: from-locator.locator-relative?))
              else
                locator
              end
            end method merge-locators;
            
            define method merge-locators
                (locator :: <file-locator>, from-locator :: <directory-locator>)
             => (merged-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let merged-directory 
                = if (directory)
                    merge-locators(directory, from-locator)
                  else
                    simplify-locator(from-locator)
                  end;
              if (merged-directory ~= directory)
                make(object-class(locator),
                     directory: merged-directory,
                     base:      locator.locator-base,
                     extension: locator.locator-extension)
              else
                locator
              end
            end method merge-locators;
            
            define method merge-locators
                (locator :: <physical-locator>, from-locator :: <file-locator>)
             => (merged-locator :: <physical-locator>)
              let from-directory = from-locator.locator-directory;
              if (from-directory)
                merge-locators(locator, from-directory)
              else
                locator
              end
            end method merge-locators;
            
            /// Locator protocols
            
            define sideways method supports-open-locator?
                (locator :: <file-locator>) => (openable? :: <boolean>)
              ~locator.locator-relative?
            end method supports-open-locator?;
            
            define sideways method open-locator
                (locator :: <file-locator>, #rest keywords, #key, #all-keys)
             => (stream :: <stream>)
              apply(open-file-stream, locator, keywords)
            end method open-locator;
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-dylan",
                    lineNumbers: true,
                    matchBrackets: true,
                    continueComments: "Enter",
                    extraKeys: {"Ctrl-Q": "toggleComment"},
                    tabMode: "indent",
                    indentUnit: 2
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-dylan</code>.</p>
            </article>
            
        • ebnf
          • ebnf.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("ebnf", function (config) {
                var commentType = {slash: 0, parenthesis: 1};
                var stateType = {comment: 0, _string: 1, characterClass: 2};
                var bracesMode = null;
            
                if (config.bracesMode)
                  bracesMode = CodeMirror.getMode(config, config.bracesMode);
            
                return {
                  startState: function () {
                    return {
                      stringType: null,
                      commentType: null,
                      braced: 0,
                      lhs: true,
                      localState: null,
                      stack: [],
                      inDefinition: false
                    };
                  },
                  token: function (stream, state) {
                    if (!stream) return;
            
                    //check for state changes
                    if (state.stack.length === 0) {
                      //strings
                      if ((stream.peek() == '"') || (stream.peek() == "'")) {
                        state.stringType = stream.peek();
                        stream.next(); // Skip quote
                        state.stack.unshift(stateType._string);
                      } else if (stream.match(/^\/\*/)) { //comments starting with /*
                        state.stack.unshift(stateType.comment);
                        state.commentType = commentType.slash;
                      } else if (stream.match(/^\(\*/)) { //comments starting with (*
                        state.stack.unshift(stateType.comment);
                        state.commentType = commentType.parenthesis;
                      }
                    }
            
                    //return state
                    //stack has
                    switch (state.stack[0]) {
                    case stateType._string:
                      while (state.stack[0] === stateType._string && !stream.eol()) {
                        if (stream.peek() === state.stringType) {
                          stream.next(); // Skip quote
                          state.stack.shift(); // Clear flag
                        } else if (stream.peek() === "\\") {
                          stream.next();
                          stream.next();
                        } else {
                          stream.match(/^.[^\\\"\']*/);
                        }
                      }
                      return state.lhs ? "property string" : "string"; // Token style
            
                    case stateType.comment:
                      while (state.stack[0] === stateType.comment && !stream.eol()) {
                        if (state.commentType === commentType.slash && stream.match(/\*\//)) {
                          state.stack.shift(); // Clear flag
                          state.commentType = null;
                        } else if (state.commentType === commentType.parenthesis && stream.match(/\*\)/)) {
                          state.stack.shift(); // Clear flag
                          state.commentType = null;
                        } else {
                          stream.match(/^.[^\*]*/);
                        }
                      }
                      return "comment";
            
                    case stateType.characterClass:
                      while (state.stack[0] === stateType.characterClass && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
                          state.stack.shift();
                        }
                      }
                      return "operator";
                    }
            
                    var peek = stream.peek();
            
                    if (bracesMode !== null && (state.braced || peek === "{")) {
                      if (state.localState === null)
                        state.localState = bracesMode.startState();
            
                      var token = bracesMode.token(stream, state.localState),
                      text = stream.current();
            
                      if (!token) {
                        for (var i = 0; i < text.length; i++) {
                          if (text[i] === "{") {
                            if (state.braced === 0) {
                              token = "matchingbracket";
                            }
                            state.braced++;
                          } else if (text[i] === "}") {
                            state.braced--;
                            if (state.braced === 0) {
                              token = "matchingbracket";
                            }
                          }
                        }
                      }
                      return token;
                    }
            
                    //no stack
                    switch (peek) {
                    case "[":
                      stream.next();
                      state.stack.unshift(stateType.characterClass);
                      return "bracket";
                    case ":":
                    case "|":
                    case ";":
                      stream.next();
                      return "operator";
                    case "%":
                      if (stream.match("%%")) {
                        return "header";
                      } else if (stream.match(/[%][A-Za-z]+/)) {
                        return "keyword";
                      } else if (stream.match(/[%][}]/)) {
                        return "matchingbracket";
                      }
                      break;
                    case "/":
                      if (stream.match(/[\/][A-Za-z]+/)) {
                      return "keyword";
                    }
                    case "\\":
                      if (stream.match(/[\][a-z]+/)) {
                        return "string-2";
                      }
                    case ".":
                      if (stream.match(".")) {
                        return "atom";
                      }
                    case "*":
                    case "-":
                    case "+":
                    case "^":
                      if (stream.match(peek)) {
                        return "atom";
                      }
                    case "$":
                      if (stream.match("$$")) {
                        return "builtin";
                      } else if (stream.match(/[$][0-9]+/)) {
                        return "variable-3";
                      }
                    case "<":
                      if (stream.match(/<<[a-zA-Z_]+>>/)) {
                        return "builtin";
                      }
                    }
            
                    if (stream.match(/^\/\//)) {
                      stream.skipToEnd();
                      return "comment";
                    } else if (stream.match(/return/)) {
                      return "operator";
                    } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {
                      if (stream.match(/(?=[\(.])/)) {
                        return "variable";
                      } else if (stream.match(/(?=[\s\n]*[:=])/)) {
                        return "def";
                      }
                      return "variable-2";
                    } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) {
                      stream.next();
                      return "bracket";
                    } else if (!stream.eatSpace()) {
                      stream.next();
                    }
                    return null;
                  }
                };
              });
            
              CodeMirror.defineMIME("text/x-ebnf", "ebnf");
            });
            
          • index.html
            <!doctype html>
            <html>
              <head>
                <title>CodeMirror: EBNF Mode</title>
                <meta charset="utf-8"/>
                <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="../javascript/javascript.js"></script>
                <script src="ebnf.js"></script>
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              </head>
              <body>
                <div id=nav>
                  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
                  <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                  </ul>
                  <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="#">EBNF Mode</a>
                  </ul>
                </div>
            
                <article>
                  <h2>EBNF Mode (bracesMode setting = "javascript")</h2>
                  <form><textarea id="code" name="code">
            /* description: Parses end executes mathematical expressions. */
            
            /* lexical grammar */
            %lex
            
            %%
            \s+                   /* skip whitespace */
            [0-9]+("."[0-9]+)?\b  return 'NUMBER';
            "*"                   return '*';
            "/"                   return '/';
            "-"                   return '-';
            "+"                   return '+';
            "^"                   return '^';
            "("                   return '(';
            ")"                   return ')';
            "PI"                  return 'PI';
            "E"                   return 'E';
            &lt;&lt;EOF&gt;&gt;               return 'EOF';
            
            /lex
            
            /* operator associations and precedence */
            
            %left '+' '-'
            %left '*' '/'
            %left '^'
            %left UMINUS
            
            %start expressions
            
            %% /* language grammar */
            
            expressions
            : e EOF
            {print($1); return $1;}
            ;
            
            e
            : e '+' e
            {$$ = $1+$3;}
            | e '-' e
            {$$ = $1-$3;}
            | e '*' e
            {$$ = $1*$3;}
            | e '/' e
            {$$ = $1/$3;}
            | e '^' e
            {$$ = Math.pow($1, $3);}
            | '-' e %prec UMINUS
            {$$ = -$2;}
            | '(' e ')'
            {$$ = $2;}
            | NUMBER
            {$$ = Number(yytext);}
            | E
            {$$ = Math.E;}
            | PI
            {$$ = Math.PI;}
            ;</textarea></form>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "ebnf"},
                      lineNumbers: true,
                      bracesMode: 'javascript'
                    });
                  </script>
                  <h3>The EBNF Mode</h3>
                  <p> Created by <a href="https://github.com/robertleeplummerjr">Robert Plummer</a></p>
                </article>
              </body>
            </html>
            
        • ecl
          • ecl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ecl", function(config) {
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              function metaHook(stream, state) {
                if (!state.startOfLine) return false;
                stream.skipToEnd();
                return "meta";
              }
            
              var indentUnit = config.indentUnit;
              var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode");
              var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait");
              var variable_2 = words("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath");
              var variable_3 = words("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode");
              var builtin = words("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when");
              var blockKeywords = words("catch class do else finally for if switch try while");
              var atoms = words("true false null");
              var hooks = {"#": metaHook};
              var multiLineStrings;
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var cur = stream.current().toLowerCase();
                if (keyword.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                } else if (variable.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable";
                } else if (variable_2.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable-2";
                } else if (variable_3.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable-3";
                } else if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                } else { //Data types are of from KEYWORD##
                            var i = cur.length - 1;
                            while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))
                                    --i;
            
                            if (i > 0) {
                                    var cur2 = cur.substr(0, i + 1);
                            if (variable_3.propertyIsEnumerable(cur2)) {
                                    if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement";
                                    return "variable-3";
                            }
                        }
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return 0;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-ecl", "ecl");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ECL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ecl.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">ECL</a>
              </ul>
            </div>
            
            <article>
            <h2>ECL mode</h2>
            <form><textarea id="code" name="code">
            /*
            sample useless code to demonstrate ecl syntax highlighting
            this is a multiline comment!
            */
            
            //  this is a singleline comment!
            
            import ut;
            r := 
              record
               string22 s1 := '123';
               integer4 i1 := 123;
              end;
            #option('tmp', true);
            d := dataset('tmp::qb', r, thor);
            output(d);
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p>Based on CodeMirror's clike mode.  For more information see <a href="http://hpccsystems.com">HPCC Systems</a> web site.</p>
                <p><strong>MIME types defined:</strong> <code>text/x-ecl</code>.</p>
            
              </article>
            
        • eiffel
          • eiffel.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("eiffel", function() {
              function wordObj(words) {
                var o = {};
                for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
                return o;
              }
              var keywords = wordObj([
                'note',
                'across',
                'when',
                'variant',
                'until',
                'unique',
                'undefine',
                'then',
                'strip',
                'select',
                'retry',
                'rescue',
                'require',
                'rename',
                'reference',
                'redefine',
                'prefix',
                'once',
                'old',
                'obsolete',
                'loop',
                'local',
                'like',
                'is',
                'inspect',
                'infix',
                'include',
                'if',
                'frozen',
                'from',
                'external',
                'export',
                'ensure',
                'end',
                'elseif',
                'else',
                'do',
                'creation',
                'create',
                'check',
                'alias',
                'agent',
                'separate',
                'invariant',
                'inherit',
                'indexing',
                'feature',
                'expanded',
                'deferred',
                'class',
                'Void',
                'True',
                'Result',
                'Precursor',
                'False',
                'Current',
                'create',
                'attached',
                'detachable',
                'as',
                'and',
                'implies',
                'not',
                'or'
              ]);
              var operators = wordObj([":=", "and then","and", "or","<<",">>"]);
              var curPunc;
            
              function chain(newtok, stream, state) {
                state.tokenize.push(newtok);
                return newtok(stream, state);
              }
            
              function tokenBase(stream, state) {
                curPunc = null;
                if (stream.eatSpace()) return null;
                var ch = stream.next();
                if (ch == '"'||ch == "'") {
                  return chain(readQuoted(ch, "string"), stream, state);
                } else if (ch == "-"&&stream.eat("-")) {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == ":"&&stream.eat("=")) {
                  return "operator";
                } else if (/[0-9]/.test(ch)) {
                  stream.eatWhile(/[xXbBCc0-9\.]/);
                  stream.eat(/[\?\!]/);
                  return "ident";
                } else if (/[a-zA-Z_0-9]/.test(ch)) {
                  stream.eatWhile(/[a-zA-Z_0-9]/);
                  stream.eat(/[\?\!]/);
                  return "ident";
                } else if (/[=+\-\/*^%<>~]/.test(ch)) {
                  stream.eatWhile(/[=+\-\/*^%<>~]/);
                  return "operator";
                } else {
                  return null;
                }
              }
            
              function readQuoted(quote, style,  unescaped) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && (unescaped || !escaped)) {
                      state.tokenize.pop();
                      break;
                    }
                    escaped = !escaped && ch == "%";
                  }
                  return style;
                };
              }
            
              return {
                startState: function() {
                  return {tokenize: [tokenBase]};
                },
            
                token: function(stream, state) {
                  var style = state.tokenize[state.tokenize.length-1](stream, state);
                  if (style == "ident") {
                    var word = stream.current();
                    style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
                      : operators.propertyIsEnumerable(stream.current()) ? "operator"
                      : /^[A-Z][A-Z_0-9]*$/g.test(word) ? "tag"
                      : /^0[bB][0-1]+$/g.test(word) ? "number"
                      : /^0[cC][0-7]+$/g.test(word) ? "number"
                      : /^0[xX][a-fA-F0-9]+$/g.test(word) ? "number"
                      : /^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(word) ? "number"
                      : /^[0-9]+$/g.test(word) ? "number"
                      : "variable";
                  }
                  return style;
                },
                lineComment: "--"
              };
            });
            
            CodeMirror.defineMIME("text/x-eiffel", "eiffel");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Eiffel mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="eiffel.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Eiffel</a>
              </ul>
            </div>
            
            <article>
            <h2>Eiffel mode</h2>
            <form><textarea id="code" name="code">
            note
                description: "[
                    Project-wide universal properties.
                    This class is an ancestor to all developer-written classes.
                    ANY may be customized for individual projects or teams.
                    ]"
            
                library: "Free implementation of ELKS library"
                status: "See notice at end of class."
                legal: "See notice at end of class."
                date: "$Date: 2013-01-25 11:49:00 -0800 (Fri, 25 Jan 2013) $"
                revision: "$Revision: 712 $"
            
            class
                ANY
            
            feature -- Customization
            
            feature -- Access
            
                generator: STRING
                        -- Name of current object's generating class
                        -- (base class of the type of which it is a direct instance)
                    external
                        "built_in"
                    ensure
                        generator_not_void: Result /= Void
                        generator_not_empty: not Result.is_empty
                    end
            
                generating_type: TYPE [detachable like Current]
                        -- Type of current object
                        -- (type of which it is a direct instance)
                    do
                        Result := {detachable like Current}
                    ensure
                        generating_type_not_void: Result /= Void
                    end
            
            feature -- Status report
            
                conforms_to (other: ANY): BOOLEAN
                        -- Does type of current object conform to type
                        -- of `other' (as per Eiffel: The Language, chapter 13)?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    end
            
                same_type (other: ANY): BOOLEAN
                        -- Is type of current object identical to type of `other'?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        definition: Result = (conforms_to (other) and
                                                    other.conforms_to (Current))
                    end
            
            feature -- Comparison
            
                is_equal (other: like Current): BOOLEAN
                        -- Is `other' attached to an object considered
                        -- equal to current object?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        symmetric: Result implies other ~ Current
                        consistent: standard_is_equal (other) implies Result
                    end
            
                frozen standard_is_equal (other: like Current): BOOLEAN
                        -- Is `other' attached to an object of the same type
                        -- as current object, and field-by-field identical to it?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        same_type: Result implies same_type (other)
                        symmetric: Result implies other.standard_is_equal (Current)
                    end
            
                frozen equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void or attached
                        -- to objects considered equal?
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then
                                        a.is_equal (b)
                        end
                    ensure
                        definition: Result = (a = Void and b = Void) or else
                                    ((a /= Void and b /= Void) and then
                                    a.is_equal (b))
                    end
            
                frozen standard_equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void or attached to
                        -- field-by-field identical objects of the same type?
                        -- Always uses default object comparison criterion.
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then
                                        a.standard_is_equal (b)
                        end
                    ensure
                        definition: Result = (a = Void and b = Void) or else
                                    ((a /= Void and b /= Void) and then
                                    a.standard_is_equal (b))
                    end
            
                frozen is_deep_equal (other: like Current): BOOLEAN
                        -- Are `Current' and `other' attached to isomorphic object structures?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        shallow_implies_deep: standard_is_equal (other) implies Result
                        same_type: Result implies same_type (other)
                        symmetric: Result implies other.is_deep_equal (Current)
                    end
            
                frozen deep_equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void
                        -- or attached to isomorphic object structures?
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then a.is_deep_equal (b)
                        end
                    ensure
                        shallow_implies_deep: standard_equal (a, b) implies Result
                        both_or_none_void: (a = Void) implies (Result = (b = Void))
                        same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))
                        symmetric: Result implies deep_equal (b, a)
                    end
            
            feature -- Duplication
            
                frozen twin: like Current
                        -- New object equal to `Current'
                        -- `twin' calls `copy'; to change copying/twinning semantics, redefine `copy'.
                    external
                        "built_in"
                    ensure
                        twin_not_void: Result /= Void
                        is_equal: Result ~ Current
                    end
            
                copy (other: like Current)
                        -- Update current object using fields of object attached
                        -- to `other', so as to yield equal objects.
                    require
                        other_not_void: other /= Void
                        type_identity: same_type (other)
                    external
                        "built_in"
                    ensure
                        is_equal: Current ~ other
                    end
            
                frozen standard_copy (other: like Current)
                        -- Copy every field of `other' onto corresponding field
                        -- of current object.
                    require
                        other_not_void: other /= Void
                        type_identity: same_type (other)
                    external
                        "built_in"
                    ensure
                        is_standard_equal: standard_is_equal (other)
                    end
            
                frozen clone (other: detachable ANY): like other
                        -- Void if `other' is void; otherwise new object
                        -- equal to `other'
                        --
                        -- For non-void `other', `clone' calls `copy';
                        -- to change copying/cloning semantics, redefine `copy'.
                    obsolete
                        "Use `twin' instead."
                    do
                        if other /= Void then
                            Result := other.twin
                        end
                    ensure
                        equal: Result ~ other
                    end
            
                frozen standard_clone (other: detachable ANY): like other
                        -- Void if `other' is void; otherwise new object
                        -- field-by-field identical to `other'.
                        -- Always uses default copying semantics.
                    obsolete
                        "Use `standard_twin' instead."
                    do
                        if other /= Void then
                            Result := other.standard_twin
                        end
                    ensure
                        equal: standard_equal (Result, other)
                    end
            
                frozen standard_twin: like Current
                        -- New object field-by-field identical to `other'.
                        -- Always uses default copying semantics.
                    external
                        "built_in"
                    ensure
                        standard_twin_not_void: Result /= Void
                        equal: standard_equal (Result, Current)
                    end
            
                frozen deep_twin: like Current
                        -- New object structure recursively duplicated from Current.
                    external
                        "built_in"
                    ensure
                        deep_twin_not_void: Result /= Void
                        deep_equal: deep_equal (Current, Result)
                    end
            
                frozen deep_clone (other: detachable ANY): like other
                        -- Void if `other' is void: otherwise, new object structure
                        -- recursively duplicated from the one attached to `other'
                    obsolete
                        "Use `deep_twin' instead."
                    do
                        if other /= Void then
                            Result := other.deep_twin
                        end
                    ensure
                        deep_equal: deep_equal (other, Result)
                    end
            
                frozen deep_copy (other: like Current)
                        -- Effect equivalent to that of:
                        --      `copy' (`other' . `deep_twin')
                    require
                        other_not_void: other /= Void
                    do
                        copy (other.deep_twin)
                    ensure
                        deep_equal: deep_equal (Current, other)
                    end
            
            feature {NONE} -- Retrieval
            
                frozen internal_correct_mismatch
                        -- Called from runtime to perform a proper dynamic dispatch on `correct_mismatch'
                        -- from MISMATCH_CORRECTOR.
                    local
                        l_msg: STRING
                        l_exc: EXCEPTIONS
                    do
                        if attached {MISMATCH_CORRECTOR} Current as l_corrector then
                            l_corrector.correct_mismatch
                        else
                            create l_msg.make_from_string ("Mismatch: ")
                            create l_exc
                            l_msg.append (generating_type.name)
                            l_exc.raise_retrieval_exception (l_msg)
                        end
                    end
            
            feature -- Output
            
                io: STD_FILES
                        -- Handle to standard file setup
                    once
                        create Result
                        Result.set_output_default
                    ensure
                        io_not_void: Result /= Void
                    end
            
                out: STRING
                        -- New string containing terse printable representation
                        -- of current object
                    do
                        Result := tagged_out
                    ensure
                        out_not_void: Result /= Void
                    end
            
                frozen tagged_out: STRING
                        -- New string containing terse printable representation
                        -- of current object
                    external
                        "built_in"
                    ensure
                        tagged_out_not_void: Result /= Void
                    end
            
                print (o: detachable ANY)
                        -- Write terse external representation of `o'
                        -- on standard output.
                    do
                        if o /= Void then
                            io.put_string (o.out)
                        end
                    end
            
            feature -- Platform
            
                Operating_environment: OPERATING_ENVIRONMENT
                        -- Objects available from the operating system
                    once
                        create Result
                    ensure
                        operating_environment_not_void: Result /= Void
                    end
            
            feature {NONE} -- Initialization
            
                default_create
                        -- Process instances of classes with no creation clause.
                        -- (Default: do nothing.)
                    do
                    end
            
            feature -- Basic operations
            
                default_rescue
                        -- Process exception for routines with no Rescue clause.
                        -- (Default: do nothing.)
                    do
                    end
            
                frozen do_nothing
                        -- Execute a null action.
                    do
                    end
            
                frozen default: detachable like Current
                        -- Default value of object's type
                    do
                    end
            
                frozen default_pointer: POINTER
                        -- Default value of type `POINTER'
                        -- (Avoid the need to write `p'.`default' for
                        -- some `p' of type `POINTER'.)
                    do
                    ensure
                        -- Result = Result.default
                    end
            
                frozen as_attached: attached like Current
                        -- Attached version of Current
                        -- (Can be used during transitional period to convert
                        -- non-void-safe classes to void-safe ones.)
                    do
                        Result := Current
                    end
            
            invariant
                reflexive_equality: standard_is_equal (Current)
                reflexive_conformance: conforms_to (Current)
            
            note
                copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
                license:   "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
                source: "[
                        Eiffel Software
                        5949 Hollister Ave., Goleta, CA 93117 USA
                        Telephone 805-685-1006, Fax 805-685-6869
                        Website http://www.eiffel.com
                        Customer support http://support.eiffel.com
                    ]"
            
            end
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-eiffel",
                    indentUnit: 4,
                    lineNumbers: true,
                    theme: "neat"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-eiffel</code>.</p>
             
             <p> Created by <a href="https://github.com/ynh">YNH</a>.</p>
              </article>
            
        • erlang
          • erlang.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*jshint unused:true, eqnull:true, curly:true, bitwise:true */
            /*jshint undef:true, latedef:true, trailing:true */
            /*global CodeMirror:true */
            
            // erlang mode.
            // tokenizer -> token types -> CodeMirror styles
            // tokenizer maintains a parse stack
            // indenter uses the parse stack
            
            // TODO indenter:
            //   bit syntax
            //   old guard/bif/conversion clashes (e.g. "float/1")
            //   type/spec/opaque
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMIME("text/x-erlang", "erlang");
            
            CodeMirror.defineMode("erlang", function(cmCfg) {
              "use strict";
            
            /////////////////////////////////////////////////////////////////////////////
            // constants
            
              var typeWords = [
                "-type", "-spec", "-export_type", "-opaque"];
            
              var keywordWords = [
                "after","begin","catch","case","cond","end","fun","if",
                "let","of","query","receive","try","when"];
            
              var separatorRE    = /[\->,;]/;
              var separatorWords = [
                "->",";",","];
            
              var operatorAtomWords = [
                "and","andalso","band","bnot","bor","bsl","bsr","bxor",
                "div","not","or","orelse","rem","xor"];
            
              var operatorSymbolRE    = /[\+\-\*\/<>=\|:!]/;
              var operatorSymbolWords = [
                "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"];
            
              var openParenRE    = /[<\(\[\{]/;
              var openParenWords = [
                "<<","(","[","{"];
            
              var closeParenRE    = /[>\)\]\}]/;
              var closeParenWords = [
                "}","]",")",">>"];
            
              var guardWords = [
                "is_atom","is_binary","is_bitstring","is_boolean","is_float",
                "is_function","is_integer","is_list","is_number","is_pid",
                "is_port","is_record","is_reference","is_tuple",
                "atom","binary","bitstring","boolean","function","integer","list",
                "number","pid","port","record","reference","tuple"];
            
              var bifWords = [
                "abs","adler32","adler32_combine","alive","apply","atom_to_binary",
                "atom_to_list","binary_to_atom","binary_to_existing_atom",
                "binary_to_list","binary_to_term","bit_size","bitstring_to_list",
                "byte_size","check_process_code","contact_binary","crc32",
                "crc32_combine","date","decode_packet","delete_module",
                "disconnect_node","element","erase","exit","float","float_to_list",
                "garbage_collect","get","get_keys","group_leader","halt","hd",
                "integer_to_list","internal_bif","iolist_size","iolist_to_binary",
                "is_alive","is_atom","is_binary","is_bitstring","is_boolean",
                "is_float","is_function","is_integer","is_list","is_number","is_pid",
                "is_port","is_process_alive","is_record","is_reference","is_tuple",
                "length","link","list_to_atom","list_to_binary","list_to_bitstring",
                "list_to_existing_atom","list_to_float","list_to_integer",
                "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded",
                "monitor_node","node","node_link","node_unlink","nodes","notalive",
                "now","open_port","pid_to_list","port_close","port_command",
                "port_connect","port_control","pre_loaded","process_flag",
                "process_info","processes","purge_module","put","register",
                "registered","round","self","setelement","size","spawn","spawn_link",
                "spawn_monitor","spawn_opt","split_binary","statistics",
                "term_to_binary","time","throw","tl","trunc","tuple_size",
                "tuple_to_list","unlink","unregister","whereis"];
            
            // upper case: [A-Z] [Ø-Þ] [À-Ö]
            // lower case: [a-z] [ß-ö] [ø-ÿ]
              var anumRE       = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/;
              var escapesRE    =
                /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;
            
            /////////////////////////////////////////////////////////////////////////////
            // tokenizer
            
              function tokenizer(stream,state) {
                // in multi-line string
                if (state.in_string) {
                  state.in_string = (!doubleQuote(stream));
                  return rval(state,stream,"string");
                }
            
                // in multi-line atom
                if (state.in_atom) {
                  state.in_atom = (!singleQuote(stream));
                  return rval(state,stream,"atom");
                }
            
                // whitespace
                if (stream.eatSpace()) {
                  return rval(state,stream,"whitespace");
                }
            
                // attributes and type specs
                if (!peekToken(state) &&
                    stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) {
                  if (is_member(stream.current(),typeWords)) {
                    return rval(state,stream,"type");
                  }else{
                    return rval(state,stream,"attribute");
                  }
                }
            
                var ch = stream.next();
            
                // comment
                if (ch == '%') {
                  stream.skipToEnd();
                  return rval(state,stream,"comment");
                }
            
                // colon
                if (ch == ":") {
                  return rval(state,stream,"colon");
                }
            
                // macro
                if (ch == '?') {
                  stream.eatSpace();
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"macro");
                }
            
                // record
                if (ch == "#") {
                  stream.eatSpace();
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"record");
                }
            
                // dollar escape
                if (ch == "$") {
                  if (stream.next() == "\\" && !stream.match(escapesRE)) {
                    return rval(state,stream,"error");
                  }
                  return rval(state,stream,"number");
                }
            
                // dot
                if (ch == ".") {
                  return rval(state,stream,"dot");
                }
            
                // quoted atom
                if (ch == '\'') {
                  if (!(state.in_atom = (!singleQuote(stream)))) {
                    if (stream.match(/\s*\/\s*[0-9]/,false)) {
                      stream.match(/\s*\/\s*[0-9]/,true);
                      return rval(state,stream,"fun");      // 'f'/0 style fun
                    }
                    if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) {
                      return rval(state,stream,"function");
                    }
                  }
                  return rval(state,stream,"atom");
                }
            
                // string
                if (ch == '"') {
                  state.in_string = (!doubleQuote(stream));
                  return rval(state,stream,"string");
                }
            
                // variable
                if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) {
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"variable");
                }
            
                // atom/keyword/BIF/function
                if (/[a-z_ß-öø-ÿ]/.test(ch)) {
                  stream.eatWhile(anumRE);
            
                  if (stream.match(/\s*\/\s*[0-9]/,false)) {
                    stream.match(/\s*\/\s*[0-9]/,true);
                    return rval(state,stream,"fun");      // f/0 style fun
                  }
            
                  var w = stream.current();
            
                  if (is_member(w,keywordWords)) {
                    return rval(state,stream,"keyword");
                  }else if (is_member(w,operatorAtomWords)) {
                    return rval(state,stream,"operator");
                  }else if (stream.match(/\s*\(/,false)) {
                    // 'put' and 'erlang:put' are bifs, 'foo:put' is not
                    if (is_member(w,bifWords) &&
                        ((peekToken(state).token != ":") ||
                         (peekToken(state,2).token == "erlang"))) {
                      return rval(state,stream,"builtin");
                    }else if (is_member(w,guardWords)) {
                      return rval(state,stream,"guard");
                    }else{
                      return rval(state,stream,"function");
                    }
                  }else if (is_member(w,operatorAtomWords)) {
                    return rval(state,stream,"operator");
                  }else if (lookahead(stream) == ":") {
                    if (w == "erlang") {
                      return rval(state,stream,"builtin");
                    } else {
                      return rval(state,stream,"function");
                    }
                  }else if (is_member(w,["true","false"])) {
                    return rval(state,stream,"boolean");
                  }else if (is_member(w,["true","false"])) {
                    return rval(state,stream,"boolean");
                  }else{
                    return rval(state,stream,"atom");
                  }
                }
            
                // number
                var digitRE      = /[0-9]/;
                var radixRE      = /[0-9a-zA-Z]/;         // 36#zZ style int
                if (digitRE.test(ch)) {
                  stream.eatWhile(digitRE);
                  if (stream.eat('#')) {                // 36#aZ  style integer
                    if (!stream.eatWhile(radixRE)) {
                      stream.backUp(1);                 //"36#" - syntax error
                    }
                  } else if (stream.eat('.')) {       // float
                    if (!stream.eatWhile(digitRE)) {
                      stream.backUp(1);        // "3." - probably end of function
                    } else {
                      if (stream.eat(/[eE]/)) {        // float with exponent
                        if (stream.eat(/[-+]/)) {
                          if (!stream.eatWhile(digitRE)) {
                            stream.backUp(2);            // "2e-" - syntax error
                          }
                        } else {
                          if (!stream.eatWhile(digitRE)) {
                            stream.backUp(1);            // "2e" - syntax error
                          }
                        }
                      }
                    }
                  }
                  return rval(state,stream,"number");   // normal integer
                }
            
                // open parens
                if (nongreedy(stream,openParenRE,openParenWords)) {
                  return rval(state,stream,"open_paren");
                }
            
                // close parens
                if (nongreedy(stream,closeParenRE,closeParenWords)) {
                  return rval(state,stream,"close_paren");
                }
            
                // separators
                if (greedy(stream,separatorRE,separatorWords)) {
                  return rval(state,stream,"separator");
                }
            
                // operators
                if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) {
                  return rval(state,stream,"operator");
                }
            
                return rval(state,stream,null);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // utilities
              function nongreedy(stream,re,words) {
                if (stream.current().length == 1 && re.test(stream.current())) {
                  stream.backUp(1);
                  while (re.test(stream.peek())) {
                    stream.next();
                    if (is_member(stream.current(),words)) {
                      return true;
                    }
                  }
                  stream.backUp(stream.current().length-1);
                }
                return false;
              }
            
              function greedy(stream,re,words) {
                if (stream.current().length == 1 && re.test(stream.current())) {
                  while (re.test(stream.peek())) {
                    stream.next();
                  }
                  while (0 < stream.current().length) {
                    if (is_member(stream.current(),words)) {
                      return true;
                    }else{
                      stream.backUp(1);
                    }
                  }
                  stream.next();
                }
                return false;
              }
            
              function doubleQuote(stream) {
                return quote(stream, '"', '\\');
              }
            
              function singleQuote(stream) {
                return quote(stream,'\'','\\');
              }
            
              function quote(stream,quoteChar,escapeChar) {
                while (!stream.eol()) {
                  var ch = stream.next();
                  if (ch == quoteChar) {
                    return true;
                  }else if (ch == escapeChar) {
                    stream.next();
                  }
                }
                return false;
              }
            
              function lookahead(stream) {
                var m = stream.match(/([\n\s]+|%[^\n]*\n)*(.)/,false);
                return m ? m.pop() : "";
              }
            
              function is_member(element,list) {
                return (-1 < list.indexOf(element));
              }
            
              function rval(state,stream,type) {
            
                // parse stack
                pushToken(state,realToken(type,stream));
            
                // map erlang token type to CodeMirror style class
                //     erlang             -> CodeMirror tag
                switch (type) {
                  case "atom":        return "atom";
                  case "attribute":   return "attribute";
                  case "boolean":     return "atom";
                  case "builtin":     return "builtin";
                  case "close_paren": return null;
                  case "colon":       return null;
                  case "comment":     return "comment";
                  case "dot":         return null;
                  case "error":       return "error";
                  case "fun":         return "meta";
                  case "function":    return "tag";
                  case "guard":       return "property";
                  case "keyword":     return "keyword";
                  case "macro":       return "variable-2";
                  case "number":      return "number";
                  case "open_paren":  return null;
                  case "operator":    return "operator";
                  case "record":      return "bracket";
                  case "separator":   return null;
                  case "string":      return "string";
                  case "type":        return "def";
                  case "variable":    return "variable";
                  default:            return null;
                }
              }
            
              function aToken(tok,col,ind,typ) {
                return {token:  tok,
                        column: col,
                        indent: ind,
                        type:   typ};
              }
            
              function realToken(type,stream) {
                return aToken(stream.current(),
                             stream.column(),
                             stream.indentation(),
                             type);
              }
            
              function fakeToken(type) {
                return aToken(type,0,0,type);
              }
            
              function peekToken(state,depth) {
                var len = state.tokenStack.length;
                var dep = (depth ? depth : 1);
            
                if (len < dep) {
                  return false;
                }else{
                  return state.tokenStack[len-dep];
                }
              }
            
              function pushToken(state,token) {
            
                if (!(token.type == "comment" || token.type == "whitespace")) {
                  state.tokenStack = maybe_drop_pre(state.tokenStack,token);
                  state.tokenStack = maybe_drop_post(state.tokenStack);
                }
              }
            
              function maybe_drop_pre(s,token) {
                var last = s.length-1;
            
                if (0 < last && s[last].type === "record" && token.type === "dot") {
                  s.pop();
                }else if (0 < last && s[last].type === "group") {
                  s.pop();
                  s.push(token);
                }else{
                  s.push(token);
                }
                return s;
              }
            
              function maybe_drop_post(s) {
                var last = s.length-1;
            
                if (s[last].type === "dot") {
                  return [];
                }
                if (s[last].type === "fun" && s[last-1].token === "fun") {
                  return s.slice(0,last-1);
                }
                switch (s[s.length-1].token) {
                  case "}":    return d(s,{g:["{"]});
                  case "]":    return d(s,{i:["["]});
                  case ")":    return d(s,{i:["("]});
                  case ">>":   return d(s,{i:["<<"]});
                  case "end":  return d(s,{i:["begin","case","fun","if","receive","try"]});
                  case ",":    return d(s,{e:["begin","try","when","->",
                                              ",","(","[","{","<<"]});
                  case "->":   return d(s,{r:["when"],
                                           m:["try","if","case","receive"]});
                  case ";":    return d(s,{E:["case","fun","if","receive","try","when"]});
                  case "catch":return d(s,{e:["try"]});
                  case "of":   return d(s,{e:["case"]});
                  case "after":return d(s,{e:["receive","try"]});
                  default:     return s;
                }
              }
            
              function d(stack,tt) {
                // stack is a stack of Token objects.
                // tt is an object; {type:tokens}
                // type is a char, tokens is a list of token strings.
                // The function returns (possibly truncated) stack.
                // It will descend the stack, looking for a Token such that Token.token
                //  is a member of tokens. If it does not find that, it will normally (but
                //  see "E" below) return stack. If it does find a match, it will remove
                //  all the Tokens between the top and the matched Token.
                // If type is "m", that is all it does.
                // If type is "i", it will also remove the matched Token and the top Token.
                // If type is "g", like "i", but add a fake "group" token at the top.
                // If type is "r", it will remove the matched Token, but not the top Token.
                // If type is "e", it will keep the matched Token but not the top Token.
                // If type is "E", it behaves as for type "e", except if there is no match,
                //  in which case it will return an empty stack.
            
                for (var type in tt) {
                  var len = stack.length-1;
                  var tokens = tt[type];
                  for (var i = len-1; -1 < i ; i--) {
                    if (is_member(stack[i].token,tokens)) {
                      var ss = stack.slice(0,i);
                      switch (type) {
                          case "m": return ss.concat(stack[i]).concat(stack[len]);
                          case "r": return ss.concat(stack[len]);
                          case "i": return ss;
                          case "g": return ss.concat(fakeToken("group"));
                          case "E": return ss.concat(stack[i]);
                          case "e": return ss.concat(stack[i]);
                      }
                    }
                  }
                }
                return (type == "E" ? [] : stack);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // indenter
            
              function indenter(state,textAfter) {
                var t;
                var unit = cmCfg.indentUnit;
                var wordAfter = wordafter(textAfter);
                var currT = peekToken(state,1);
                var prevT = peekToken(state,2);
            
                if (state.in_string || state.in_atom) {
                  return CodeMirror.Pass;
                }else if (!prevT) {
                  return 0;
                }else if (currT.token == "when") {
                  return currT.column+unit;
                }else if (wordAfter === "when" && prevT.type === "function") {
                  return prevT.indent+unit;
                }else if (wordAfter === "(" && currT.token === "fun") {
                  return  currT.column+3;
                }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) {
                  return t.column;
                }else if (is_member(wordAfter,["end","after","of"])) {
                  t = getToken(state,["begin","case","fun","if","receive","try"]);
                  return t ? t.column : CodeMirror.Pass;
                }else if (is_member(wordAfter,closeParenWords)) {
                  t = getToken(state,openParenWords);
                  return t ? t.column : CodeMirror.Pass;
                }else if (is_member(currT.token,[",","|","||"]) ||
                          is_member(wordAfter,[",","|","||"])) {
                  t = postcommaToken(state);
                  return t ? t.column+t.token.length : unit;
                }else if (currT.token == "->") {
                  if (is_member(prevT.token, ["receive","case","if","try"])) {
                    return prevT.column+unit+unit;
                  }else{
                    return prevT.column+unit;
                  }
                }else if (is_member(currT.token,openParenWords)) {
                  return currT.column+currT.token.length;
                }else{
                  t = defaultToken(state);
                  return truthy(t) ? t.column+unit : 0;
                }
              }
            
              function wordafter(str) {
                var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/);
            
                return truthy(m) && (m.index === 0) ? m[0] : "";
              }
            
              function postcommaToken(state) {
                var objs = state.tokenStack.slice(0,-1);
                var i = getTokenIndex(objs,"type",["open_paren"]);
            
                return truthy(objs[i]) ? objs[i] : false;
              }
            
              function defaultToken(state) {
                var objs = state.tokenStack;
                var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]);
                var oper = getTokenIndex(objs,"type",["operator"]);
            
                if (truthy(stop) && truthy(oper) && stop < oper) {
                  return objs[stop+1];
                } else if (truthy(stop)) {
                  return objs[stop];
                } else {
                  return false;
                }
              }
            
              function getToken(state,tokens) {
                var objs = state.tokenStack;
                var i = getTokenIndex(objs,"token",tokens);
            
                return truthy(objs[i]) ? objs[i] : false;
              }
            
              function getTokenIndex(objs,propname,propvals) {
            
                for (var i = objs.length-1; -1 < i ; i--) {
                  if (is_member(objs[i][propname],propvals)) {
                    return i;
                  }
                }
                return false;
              }
            
              function truthy(x) {
                return (x !== false) && (x != null);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // this object defines the mode
            
              return {
                startState:
                  function() {
                    return {tokenStack: [],
                            in_string:  false,
                            in_atom:    false};
                  },
            
                token:
                  function(stream, state) {
                    return tokenizer(stream, state);
                  },
            
                indent:
                  function(state, textAfter) {
                    return indenter(state,textAfter);
                  },
            
                lineComment: "%"
              };
            });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Erlang mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/erlang-dark.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="erlang.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Erlang</a>
              </ul>
            </div>
            
            <article>
            <h2>Erlang mode</h2>
            <form><textarea id="code" name="code">
            %% -*- mode: erlang; erlang-indent-level: 2 -*-
            %%% Created :  7 May 2012 by mats cronqvist <masse@klarna.com>
            
            %% @doc
            %% Demonstrates how to print a record.
            %% @end
            
            -module('ex').
            -author('mats cronqvist').
            -export([demo/0,
                     rec_info/1]).
            
            -record(demo,{a="One",b="Two",c="Three",d="Four"}).
            
            rec_info(demo) -> record_info(fields,demo).
            
            demo() -> expand_recs(?MODULE,#demo{a="A",b="BB"}).
            
            expand_recs(M,List) when is_list(List) ->
              [expand_recs(M,L)||L<-List];
            expand_recs(M,Tup) when is_tuple(Tup) ->
              case tuple_size(Tup) of
                L when L < 1 -> Tup;
                L ->
                  try
                    Fields = M:rec_info(element(1,Tup)),
                    L = length(Fields)+1,
                    lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))
                  catch
                    _:_ -> list_to_tuple(expand_recs(M,tuple_to_list(Tup)))
                  end
              end;
            expand_recs(_,Term) ->
              Term.
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    extraKeys: {"Tab":  "indentAuto"},
                    theme: "erlang-dark"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-erlang</code>.</p>
              </article>
            
        • forth
          • forth.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Author: Aliaksei Chapyzhenka
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function toWordList(words) {
                var ret = [];
                words.split(' ').forEach(function(e){
                  ret.push({name: e});
                });
                return ret;
              }
            
              var coreWordList = toWordList(
            'INVERT AND OR XOR\
             2* 2/ LSHIFT RSHIFT\
             0= = 0< < > U< MIN MAX\
             2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\
             >R R> R@\
             + - 1+ 1- ABS NEGATE\
             S>D * M* UM*\
             FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\
             HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\
             ALIGN ALIGNED +! ALLOT\
             CHAR [CHAR] [ ] BL\
             FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\
             ; DOES> >BODY\
             EVALUATE\
             SOURCE >IN\
             <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\
             FILL MOVE\
             . CR EMIT SPACE SPACES TYPE U. .R U.R\
             ACCEPT\
             TRUE FALSE\
             <> U> 0<> 0>\
             NIP TUCK ROLL PICK\
             2>R 2R@ 2R>\
             WITHIN UNUSED MARKER\
             I J\
             TO\
             COMPILE, [COMPILE]\
             SAVE-INPUT RESTORE-INPUT\
             PAD ERASE\
             2LITERAL DNEGATE\
             D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\
             M+ M*/ D. D.R 2ROT DU<\
             CATCH THROW\
             FREE RESIZE ALLOCATE\
             CS-PICK CS-ROLL\
             GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\
             PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\
             -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL');
            
              var immediateWordList = toWordList('IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE');
            
              CodeMirror.defineMode('forth', function() {
                function searchWordList (wordList, word) {
                  var i;
                  for (i = wordList.length - 1; i >= 0; i--) {
                    if (wordList[i].name === word.toUpperCase()) {
                      return wordList[i];
                    }
                  }
                  return undefined;
                }
              return {
                startState: function() {
                  return {
                    state: '',
                    base: 10,
                    coreWordList: coreWordList,
                    immediateWordList: immediateWordList,
                    wordList: []
                  };
                },
                token: function (stream, stt) {
                  var mat;
                  if (stream.eatSpace()) {
                    return null;
                  }
                  if (stt.state === '') { // interpretation
                    if (stream.match(/^(\]|:NONAME)(\s|$)/i)) {
                      stt.state = ' compilation';
                      return 'builtin compilation';
                    }
                    mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/);
                    if (mat) {
                      stt.wordList.push({name: mat[2].toUpperCase()});
                      stt.state = ' compilation';
                      return 'def' + stt.state;
                    }
                    mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i);
                    if (mat) {
                      stt.wordList.push({name: mat[2].toUpperCase()});
                      return 'def' + stt.state;
                    }
                    mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/);
                    if (mat) {
                      return 'builtin' + stt.state;
                    }
                    } else { // compilation
                    // ; [
                    if (stream.match(/^(\;|\[)(\s)/)) {
                      stt.state = '';
                      stream.backUp(1);
                      return 'builtin compilation';
                    }
                    if (stream.match(/^(\;|\[)($)/)) {
                      stt.state = '';
                      return 'builtin compilation';
                    }
                    if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) {
                      return 'builtin';
                    }
                  }
            
                  // dynamic wordlist
                  mat = stream.match(/^(\S+)(\s+|$)/);
                  if (mat) {
                    if (searchWordList(stt.wordList, mat[1]) !== undefined) {
                      return 'variable' + stt.state;
                    }
            
                    // comments
                    if (mat[1] === '\\') {
                      stream.skipToEnd();
                        return 'comment' + stt.state;
                      }
            
                      // core words
                      if (searchWordList(stt.coreWordList, mat[1]) !== undefined) {
                        return 'builtin' + stt.state;
                      }
                      if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) {
                        return 'keyword' + stt.state;
                      }
            
                      if (mat[1] === '(') {
                        stream.eatWhile(function (s) { return s !== ')'; });
                        stream.eat(')');
                        return 'comment' + stt.state;
                      }
            
                      // // strings
                      if (mat[1] === '.(') {
                        stream.eatWhile(function (s) { return s !== ')'; });
                        stream.eat(')');
                        return 'string' + stt.state;
                      }
                      if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') {
                        stream.eatWhile(function (s) { return s !== '"'; });
                        stream.eat('"');
                        return 'string' + stt.state;
                      }
            
                      // numbers
                      if (mat[1] - 0xfffffffff) {
                        return 'number' + stt.state;
                      }
                      // if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) {
                      //     return 'number' + stt.state;
                      // }
            
                      return 'atom' + stt.state;
                    }
                  }
                };
              });
              CodeMirror.defineMIME("text/x-forth", "forth");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Forth mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel=stylesheet href="../../theme/colorforth.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="forth.js"></script>
            <style>
            .CodeMirror {
                font-family: 'Droid Sans Mono', monospace;
                font-size: 14px;
            }
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Forth</a>
              </ul>
            </div>
            
            <article>
            
            <h2>Forth mode</h2>
            
            <form><textarea id="code" name="code">
            \ Insertion sort
            
            : cell-  1 cells - ;
            
            : insert ( start end -- start )
              dup @ >r ( r: v )
              begin
                2dup <
              while
                r@ over cell- @ <
              while
                cell-
                dup @ over cell+ !
              repeat then
              r> swap ! ;
            
            : sort ( array len -- )
              1 ?do
                dup i cells + insert
              loop drop ;</textarea>
              </form>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                lineWrapping: true,
                indentUnit: 2,
                tabSize: 2,
                autofocus: true,
                theme: "colorforth",
                mode: "text/x-forth"
              });
            </script>
            
            <p>Simple mode that handle Forth-Syntax (<a href="http://en.wikipedia.org/wiki/Forth_%28programming_language%29">Forth on WikiPedia</a>).</p>
            
            <p><strong>MIME types defined:</strong> <code>text/x-forth</code>.</p>
            
            </article>
            
        • fortran
          • fortran.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("fortran", function() {
              function words(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) {
                  keys[array[i]] = true;
                }
                return keys;
              }
            
              var keywords = words([
                              "abstract", "accept", "allocatable", "allocate",
                              "array", "assign", "asynchronous", "backspace",
                              "bind", "block", "byte", "call", "case",
                              "class", "close", "common", "contains",
                              "continue", "cycle", "data", "deallocate",
                              "decode", "deferred", "dimension", "do",
                              "elemental", "else", "encode", "end",
                              "endif", "entry", "enumerator", "equivalence",
                              "exit", "external", "extrinsic", "final",
                              "forall", "format", "function", "generic",
                              "go", "goto", "if", "implicit", "import", "include",
                              "inquire", "intent", "interface", "intrinsic",
                              "module", "namelist", "non_intrinsic",
                              "non_overridable", "none", "nopass",
                              "nullify", "open", "optional", "options",
                              "parameter", "pass", "pause", "pointer",
                              "print", "private", "program", "protected",
                              "public", "pure", "read", "recursive", "result",
                              "return", "rewind", "save", "select", "sequence",
                              "stop", "subroutine", "target", "then", "to", "type",
                              "use", "value", "volatile", "where", "while",
                              "write"]);
              var builtins = words(["abort", "abs", "access", "achar", "acos",
                                      "adjustl", "adjustr", "aimag", "aint", "alarm",
                                      "all", "allocated", "alog", "amax", "amin",
                                      "amod", "and", "anint", "any", "asin",
                                      "associated", "atan", "besj", "besjn", "besy",
                                      "besyn", "bit_size", "btest", "cabs", "ccos",
                                      "ceiling", "cexp", "char", "chdir", "chmod",
                                      "clog", "cmplx", "command_argument_count",
                                      "complex", "conjg", "cos", "cosh", "count",
                                      "cpu_time", "cshift", "csin", "csqrt", "ctime",
                                      "c_funloc", "c_loc", "c_associated", "c_null_ptr",
                                      "c_null_funptr", "c_f_pointer", "c_null_char",
                                      "c_alert", "c_backspace", "c_form_feed",
                                      "c_new_line", "c_carriage_return",
                                      "c_horizontal_tab", "c_vertical_tab", "dabs",
                                      "dacos", "dasin", "datan", "date_and_time",
                                      "dbesj", "dbesj", "dbesjn", "dbesy", "dbesy",
                                      "dbesyn", "dble", "dcos", "dcosh", "ddim", "derf",
                                      "derfc", "dexp", "digits", "dim", "dint", "dlog",
                                      "dlog", "dmax", "dmin", "dmod", "dnint",
                                      "dot_product", "dprod", "dsign", "dsinh",
                                      "dsin", "dsqrt", "dtanh", "dtan", "dtime",
                                      "eoshift", "epsilon", "erf", "erfc", "etime",
                                      "exit", "exp", "exponent", "extends_type_of",
                                      "fdate", "fget", "fgetc", "float", "floor",
                                      "flush", "fnum", "fputc", "fput", "fraction",
                                      "fseek", "fstat", "ftell", "gerror", "getarg",
                                      "get_command", "get_command_argument",
                                      "get_environment_variable", "getcwd",
                                      "getenv", "getgid", "getlog", "getpid",
                                      "getuid", "gmtime", "hostnm", "huge", "iabs",
                                      "iachar", "iand", "iargc", "ibclr", "ibits",
                                      "ibset", "ichar", "idate", "idim", "idint",
                                      "idnint", "ieor", "ierrno", "ifix", "imag",
                                      "imagpart", "index", "int", "ior", "irand",
                                      "isatty", "ishft", "ishftc", "isign",
                                      "iso_c_binding", "is_iostat_end", "is_iostat_eor",
                                      "itime", "kill", "kind", "lbound", "len", "len_trim",
                                      "lge", "lgt", "link", "lle", "llt", "lnblnk", "loc",
                                      "log", "logical", "long", "lshift", "lstat", "ltime",
                                      "matmul", "max", "maxexponent", "maxloc", "maxval",
                                      "mclock", "merge", "move_alloc", "min", "minexponent",
                                      "minloc", "minval", "mod", "modulo", "mvbits",
                                      "nearest", "new_line", "nint", "not", "or", "pack",
                                      "perror", "precision", "present", "product", "radix",
                                      "rand", "random_number", "random_seed", "range",
                                      "real", "realpart", "rename", "repeat", "reshape",
                                      "rrspacing", "rshift", "same_type_as", "scale",
                                      "scan", "second", "selected_int_kind",
                                      "selected_real_kind", "set_exponent", "shape",
                                      "short", "sign", "signal", "sinh", "sin", "sleep",
                                      "sngl", "spacing", "spread", "sqrt", "srand", "stat",
                                      "sum", "symlnk", "system", "system_clock", "tan",
                                      "tanh", "time", "tiny", "transfer", "transpose",
                                      "trim", "ttynam", "ubound", "umask", "unlink",
                                      "unpack", "verify", "xor", "zabs", "zcos", "zexp",
                                      "zlog", "zsin", "zsqrt"]);
            
                var dataTypes =  words(["c_bool", "c_char", "c_double", "c_double_complex",
                                 "c_float", "c_float_complex", "c_funptr", "c_int",
                                 "c_int16_t", "c_int32_t", "c_int64_t", "c_int8_t",
                                 "c_int_fast16_t", "c_int_fast32_t", "c_int_fast64_t",
                                 "c_int_fast8_t", "c_int_least16_t", "c_int_least32_t",
                                 "c_int_least64_t", "c_int_least8_t", "c_intmax_t",
                                 "c_intptr_t", "c_long", "c_long_double",
                                 "c_long_double_complex", "c_long_long", "c_ptr",
                                 "c_short", "c_signed_char", "c_size_t", "character",
                                 "complex", "double", "integer", "logical", "real"]);
              var isOperatorChar = /[+\-*&=<>\/\:]/;
              var litOperator = new RegExp("(\.and\.|\.or\.|\.eq\.|\.lt\.|\.le\.|\.gt\.|\.ge\.|\.ne\.|\.not\.|\.eqv\.|\.neqv\.)", "i");
            
              function tokenBase(stream, state) {
            
                if (stream.match(litOperator)){
                    return 'operator';
                }
            
                var ch = stream.next();
                if (ch == "!") {
                  stream.skipToEnd();
                  return "comment";
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]\(\),]/.test(ch)) {
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var word = stream.current().toLowerCase();
            
                if (keywords.hasOwnProperty(word)){
                        return 'keyword';
                }
                if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) {
                        return 'builtin';
                }
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                        end = true;
                        break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !escaped) state.tokenize = null;
                  return "string";
                };
              }
            
              // Interface
            
              return {
                startState: function() {
                  return {tokenize: null};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  return style;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-fortran", "fortran");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Fortran mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="fortran.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Fortran</a>
              </ul>
            </div>
            
            <article>
            <h2>Fortran mode</h2>
            
            
            <div><textarea id="code" name="code">
            ! Example Fortran code
              program average
            
              ! Read in some numbers and take the average
              ! As written, if there are no data points, an average of zero is returned
              ! While this may not be desired behavior, it keeps this example simple
            
              implicit none
            
              real, dimension(:), allocatable :: points
              integer                         :: number_of_points
              real                            :: average_points=0., positive_average=0., negative_average=0.
            
              write (*,*) "Input number of points to average:"
              read  (*,*) number_of_points
            
              allocate (points(number_of_points))
            
              write (*,*) "Enter the points to average:"
              read  (*,*) points
            
              ! Take the average by summing points and dividing by number_of_points
              if (number_of_points > 0) average_points = sum(points) / number_of_points
            
              ! Now form average over positive and negative points only
              if (count(points > 0.) > 0) then
                 positive_average = sum(points, points > 0.) / count(points > 0.)
              end if
            
              if (count(points < 0.) > 0) then
                 negative_average = sum(points, points < 0.) / count(points < 0.)
              end if
            
              deallocate (points)
            
              ! Print result to terminal
              write (*,'(a,g12.4)') 'Average = ', average_points
              write (*,'(a,g12.4)') 'Average of positive points = ', positive_average
              write (*,'(a,g12.4)') 'Average of negative points = ', negative_average
            
              end program average
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-fortran"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-Fortran</code>.</p>
              </article>
            
        • gas
          • gas.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gas", function(_config, parserConfig) {
              'use strict';
            
              // If an architecture is specified, its initialization function may
              // populate this array with custom parsing functions which will be
              // tried in the event that the standard functions do not find a match.
              var custom = [];
            
              // The symbol used to start a line comment changes based on the target
              // architecture.
              // If no architecture is pased in "parserConfig" then only multiline
              // comments will have syntax support.
              var lineCommentStartSymbol = "";
            
              // These directives are architecture independent.
              // Machine specific directives should go in their respective
              // architecture initialization function.
              // Reference:
              // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops
              var directives = {
                ".abort" : "builtin",
                ".align" : "builtin",
                ".altmacro" : "builtin",
                ".ascii" : "builtin",
                ".asciz" : "builtin",
                ".balign" : "builtin",
                ".balignw" : "builtin",
                ".balignl" : "builtin",
                ".bundle_align_mode" : "builtin",
                ".bundle_lock" : "builtin",
                ".bundle_unlock" : "builtin",
                ".byte" : "builtin",
                ".cfi_startproc" : "builtin",
                ".comm" : "builtin",
                ".data" : "builtin",
                ".def" : "builtin",
                ".desc" : "builtin",
                ".dim" : "builtin",
                ".double" : "builtin",
                ".eject" : "builtin",
                ".else" : "builtin",
                ".elseif" : "builtin",
                ".end" : "builtin",
                ".endef" : "builtin",
                ".endfunc" : "builtin",
                ".endif" : "builtin",
                ".equ" : "builtin",
                ".equiv" : "builtin",
                ".eqv" : "builtin",
                ".err" : "builtin",
                ".error" : "builtin",
                ".exitm" : "builtin",
                ".extern" : "builtin",
                ".fail" : "builtin",
                ".file" : "builtin",
                ".fill" : "builtin",
                ".float" : "builtin",
                ".func" : "builtin",
                ".global" : "builtin",
                ".gnu_attribute" : "builtin",
                ".hidden" : "builtin",
                ".hword" : "builtin",
                ".ident" : "builtin",
                ".if" : "builtin",
                ".incbin" : "builtin",
                ".include" : "builtin",
                ".int" : "builtin",
                ".internal" : "builtin",
                ".irp" : "builtin",
                ".irpc" : "builtin",
                ".lcomm" : "builtin",
                ".lflags" : "builtin",
                ".line" : "builtin",
                ".linkonce" : "builtin",
                ".list" : "builtin",
                ".ln" : "builtin",
                ".loc" : "builtin",
                ".loc_mark_labels" : "builtin",
                ".local" : "builtin",
                ".long" : "builtin",
                ".macro" : "builtin",
                ".mri" : "builtin",
                ".noaltmacro" : "builtin",
                ".nolist" : "builtin",
                ".octa" : "builtin",
                ".offset" : "builtin",
                ".org" : "builtin",
                ".p2align" : "builtin",
                ".popsection" : "builtin",
                ".previous" : "builtin",
                ".print" : "builtin",
                ".protected" : "builtin",
                ".psize" : "builtin",
                ".purgem" : "builtin",
                ".pushsection" : "builtin",
                ".quad" : "builtin",
                ".reloc" : "builtin",
                ".rept" : "builtin",
                ".sbttl" : "builtin",
                ".scl" : "builtin",
                ".section" : "builtin",
                ".set" : "builtin",
                ".short" : "builtin",
                ".single" : "builtin",
                ".size" : "builtin",
                ".skip" : "builtin",
                ".sleb128" : "builtin",
                ".space" : "builtin",
                ".stab" : "builtin",
                ".string" : "builtin",
                ".struct" : "builtin",
                ".subsection" : "builtin",
                ".symver" : "builtin",
                ".tag" : "builtin",
                ".text" : "builtin",
                ".title" : "builtin",
                ".type" : "builtin",
                ".uleb128" : "builtin",
                ".val" : "builtin",
                ".version" : "builtin",
                ".vtable_entry" : "builtin",
                ".vtable_inherit" : "builtin",
                ".warning" : "builtin",
                ".weak" : "builtin",
                ".weakref" : "builtin",
                ".word" : "builtin"
              };
            
              var registers = {};
            
              function x86(_parserConfig) {
                lineCommentStartSymbol = "#";
            
                registers.ax  = "variable";
                registers.eax = "variable-2";
                registers.rax = "variable-3";
            
                registers.bx  = "variable";
                registers.ebx = "variable-2";
                registers.rbx = "variable-3";
            
                registers.cx  = "variable";
                registers.ecx = "variable-2";
                registers.rcx = "variable-3";
            
                registers.dx  = "variable";
                registers.edx = "variable-2";
                registers.rdx = "variable-3";
            
                registers.si  = "variable";
                registers.esi = "variable-2";
                registers.rsi = "variable-3";
            
                registers.di  = "variable";
                registers.edi = "variable-2";
                registers.rdi = "variable-3";
            
                registers.sp  = "variable";
                registers.esp = "variable-2";
                registers.rsp = "variable-3";
            
                registers.bp  = "variable";
                registers.ebp = "variable-2";
                registers.rbp = "variable-3";
            
                registers.ip  = "variable";
                registers.eip = "variable-2";
                registers.rip = "variable-3";
            
                registers.cs  = "keyword";
                registers.ds  = "keyword";
                registers.ss  = "keyword";
                registers.es  = "keyword";
                registers.fs  = "keyword";
                registers.gs  = "keyword";
              }
            
              function armv6(_parserConfig) {
                // Reference:
                // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf
                // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
                lineCommentStartSymbol = "@";
                directives.syntax = "builtin";
            
                registers.r0  = "variable";
                registers.r1  = "variable";
                registers.r2  = "variable";
                registers.r3  = "variable";
                registers.r4  = "variable";
                registers.r5  = "variable";
                registers.r6  = "variable";
                registers.r7  = "variable";
                registers.r8  = "variable";
                registers.r9  = "variable";
                registers.r10 = "variable";
                registers.r11 = "variable";
                registers.r12 = "variable";
            
                registers.sp  = "variable-2";
                registers.lr  = "variable-2";
                registers.pc  = "variable-2";
                registers.r13 = registers.sp;
                registers.r14 = registers.lr;
                registers.r15 = registers.pc;
            
                custom.push(function(ch, stream) {
                  if (ch === '#') {
                    stream.eatWhile(/\w/);
                    return "number";
                  }
                });
              }
            
              var arch = (parserConfig.architecture || "x86").toLowerCase();
              if (arch === "x86") {
                x86(parserConfig);
              } else if (arch === "arm" || arch === "armv6") {
                armv6(parserConfig);
              }
            
              function nextUntilUnescaped(stream, end) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (next === end && !escaped) {
                    return false;
                  }
                  escaped = !escaped && next === "\\";
                }
                return escaped;
              }
            
              function clikeComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (ch === "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch === "*");
                }
                return "comment";
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: null
                  };
                },
            
                token: function(stream, state) {
                  if (state.tokenize) {
                    return state.tokenize(stream, state);
                  }
            
                  if (stream.eatSpace()) {
                    return null;
                  }
            
                  var style, cur, ch = stream.next();
            
                  if (ch === "/") {
                    if (stream.eat("*")) {
                      state.tokenize = clikeComment;
                      return clikeComment(stream, state);
                    }
                  }
            
                  if (ch === lineCommentStartSymbol) {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  if (ch === '"') {
                    nextUntilUnescaped(stream, '"');
                    return "string";
                  }
            
                  if (ch === '.') {
                    stream.eatWhile(/\w/);
                    cur = stream.current().toLowerCase();
                    style = directives[cur];
                    return style || null;
                  }
            
                  if (ch === '=') {
                    stream.eatWhile(/\w/);
                    return "tag";
                  }
            
                  if (ch === '{') {
                    return "braket";
                  }
            
                  if (ch === '}') {
                    return "braket";
                  }
            
                  if (/\d/.test(ch)) {
                    if (ch === "0" && stream.eat("x")) {
                      stream.eatWhile(/[0-9a-fA-F]/);
                      return "number";
                    }
                    stream.eatWhile(/\d/);
                    return "number";
                  }
            
                  if (/\w/.test(ch)) {
                    stream.eatWhile(/\w/);
                    if (stream.eat(":")) {
                      return 'tag';
                    }
                    cur = stream.current().toLowerCase();
                    style = registers[cur];
                    return style || null;
                  }
            
                  for (var i = 0; i < custom.length; i++) {
                    style = custom[i](ch, stream, state);
                    if (style) {
                      return style;
                    }
                  }
                },
            
                lineComment: lineCommentStartSymbol,
                blockCommentStart: "/*",
                blockCommentEnd: "*/"
              };
            });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Gas mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="gas.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Gas</a>
              </ul>
            </div>
            
            <article>
            <h2>Gas mode</h2>
            <form>
            <textarea id="code" name="code">
            .syntax unified
            .global main
            
            /* 
             *  A
             *  multi-line
             *  comment.
             */
            
            @ A single line comment.
            
            main:
                    push    {sp, lr}
                    ldr     r0, =message
                    bl      puts
                    mov     r0, #0
                    pop     {sp, pc}
            
            message:
                    .asciz "Hello world!<br />"
            </textarea>
                    </form>
            
                    <script>
                        var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                            lineNumbers: true,
                            mode: {name: "gas", architecture: "ARMv6"},
                        });
                    </script>
            
                    <p>Handles AT&amp;T assembler syntax (more specifically this handles
                    the GNU Assembler (gas) syntax.)
                    It takes a single optional configuration parameter:
                    <code>architecture</code>, which can be one of <code>"ARM"</code>,
                    <code>"ARMv6"</code> or <code>"x86"</code>.
                    Including the parameter adds syntax for the registers and special
                    directives for the supplied architecture.
            
                    <p><strong>MIME types defined:</strong> <code>text/x-gas</code></p>
                </article>
            
        • gfm
          • gfm.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gfm", function(config, modeConfig) {
              var codeDepth = 0;
              function blankLine(state) {
                state.code = false;
                return null;
              }
              var gfmOverlay = {
                startState: function() {
                  return {
                    code: false,
                    codeBlock: false,
                    ateSpace: false
                  };
                },
                copyState: function(s) {
                  return {
                    code: s.code,
                    codeBlock: s.codeBlock,
                    ateSpace: s.ateSpace
                  };
                },
                token: function(stream, state) {
                  state.combineTokens = null;
            
                  // Hack to prevent formatting override inside code blocks (block and inline)
                  if (state.codeBlock) {
                    if (stream.match(/^```/)) {
                      state.codeBlock = false;
                      return null;
                    }
                    stream.skipToEnd();
                    return null;
                  }
                  if (stream.sol()) {
                    state.code = false;
                  }
                  if (stream.sol() && stream.match(/^```/)) {
                    stream.skipToEnd();
                    state.codeBlock = true;
                    return null;
                  }
                  // If this block is changed, it may need to be updated in Markdown mode
                  if (stream.peek() === '`') {
                    stream.next();
                    var before = stream.pos;
                    stream.eatWhile('`');
                    var difference = 1 + stream.pos - before;
                    if (!state.code) {
                      codeDepth = difference;
                      state.code = true;
                    } else {
                      if (difference === codeDepth) { // Must be exact
                        state.code = false;
                      }
                    }
                    return null;
                  } else if (state.code) {
                    stream.next();
                    return null;
                  }
                  // Check if space. If so, links can be formatted later on
                  if (stream.eatSpace()) {
                    state.ateSpace = true;
                    return null;
                  }
                  if (stream.sol() || state.ateSpace) {
                    state.ateSpace = false;
                    if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
                      // User/Project@SHA
                      // User@SHA
                      // SHA
                      state.combineTokens = true;
                      return "link";
                    } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
                      // User/Project#Num
                      // User#Num
                      // #Num
                      state.combineTokens = true;
                      return "link";
                    }
                  }
                  if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i) &&
                     stream.string.slice(stream.start - 2, stream.start) != "](") {
                    // URLs
                    // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
                    // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
                    state.combineTokens = true;
                    return "link";
                  }
                  stream.next();
                  return null;
                },
                blankLine: blankLine
              };
            
              var markdownConfig = {
                underscoresBreakWords: false,
                taskLists: true,
                fencedCodeBlocks: true,
                strikethrough: true
              };
              for (var attr in modeConfig) {
                markdownConfig[attr] = modeConfig[attr];
              }
              markdownConfig.name = "markdown";
              CodeMirror.defineMIME("gfmBase", markdownConfig);
              return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
            }, "markdown");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: GFM mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../markdown/markdown.js"></script>
            <script src="gfm.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="../meta.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">GFM</a>
              </ul>
            </div>
            
            <article>
            <h2>GFM mode</h2>
            <form><textarea id="code" name="code">
            GitHub Flavored Markdown
            ========================
            
            Everything from markdown plus GFM features:
            
            ## URL autolinking
            
            Underscores_are_allowed_between_words.
            
            ## Strikethrough text
            
            GFM adds syntax to strikethrough text, which is missing from standard Markdown.
            
            ~~Mistaken text.~~
            ~~**works with other fomatting**~~
            
            ~~spans across
            lines~~
            
            ## Fenced code blocks (and syntax highlighting)
            
            ```javascript
            for (var i = 0; i &lt; items.length; i++) {
                console.log(items[i], i); // log them
            }
            ```
            
            ## Task Lists
            
            - [ ] Incomplete task list item
            - [x] **Completed** task list item
            
            ## A bit of GitHub spice
            
            * SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * \#Num: #1
            * User/#Num: mojombo#1
            * User/Project#Num: mojombo/god#1
            
            See http://github.github.com/github-flavored-markdown/.
            
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'gfm',
                    lineNumbers: true,
                    theme: "default"
                  });
                </script>
            
                <p>Optionally depends on other modes for properly highlighted code blocks.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#gfm_*">normal</a>,  <a href="../../test/index.html#verbose,gfm_*">verbose</a>.</p>
            
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "gfm");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
              var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "gfm", highlightFormatting: true});
              function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
            
              FT("codeBackticks",
                 "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
            
              FT("doubleBackticks",
                 "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
            
              FT("codeBlock",
                 "[comment&formatting&formatting-code-block ```css]",
                 "[tag foo]",
                 "[comment&formatting&formatting-code-block ```]");
            
              FT("taskList",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2  foo]",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2  foo]");
            
              FT("formatting_strikethrough",
                 "[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]");
            
              FT("formatting_strikethrough",
                 "foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]");
            
              MT("emInWordAsterisk",
                 "foo[em *bar*]hello");
            
              MT("emInWordUnderscore",
                 "foo_bar_hello");
            
              MT("emStrongUnderscore",
                 "[strong __][em&strong _foo__][em _] bar");
            
              MT("fencedCodeBlocks",
                 "[comment ```]",
                 "[comment foo]",
                 "",
                 "[comment ```]",
                 "bar");
            
              MT("fencedCodeBlockModeSwitching",
                 "[comment ```javascript]",
                 "[variable foo]",
                 "",
                 "[comment ```]",
                 "bar");
            
              MT("taskListAsterisk",
                 "[variable-2 * []] foo]", // Invalid; must have space or x between []
                 "[variable-2 * [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 * [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 * ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 * ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListPlus",
                 "[variable-2 + []] foo]", // Invalid; must have space or x between []
                 "[variable-2 + [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 + [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 + ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 + ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListDash",
                 "[variable-2 - []] foo]", // Invalid; must have space or x between []
                 "[variable-2 - [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 - [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 - ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 - ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListNumber",
                 "[variable-2 1. []] foo]", // Invalid; must have space or x between []
                 "[variable-2 2. [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 3. [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 4. ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 1. ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("SHA",
                 "foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar");
            
              MT("SHAEmphasis",
                 "[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("shortSHA",
                 "foo [link be6a8cc] bar");
            
              MT("tooShortSHA",
                 "foo be6a8c bar");
            
              MT("longSHA",
                 "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar");
            
              MT("badSHA",
                 "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar");
            
              MT("userSHA",
                 "foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello");
            
              MT("userSHAEmphasis",
                 "[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("userProjectSHA",
                 "foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world");
            
              MT("userProjectSHAEmphasis",
                 "[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("num",
                 "foo [link #1] bar");
            
              MT("numEmphasis",
                 "[em *foo ][em&link #1][em *]");
            
              MT("badNum",
                 "foo #1bar hello");
            
              MT("userNum",
                 "foo [link bar#1] hello");
            
              MT("userNumEmphasis",
                 "[em *foo ][em&link bar#1][em *]");
            
              MT("userProjectNum",
                 "foo [link bar/hello#1] world");
            
              MT("userProjectNumEmphasis",
                 "[em *foo ][em&link bar/hello#1][em *]");
            
              MT("vanillaLink",
                 "foo [link http://www.example.com/] bar");
            
              MT("vanillaLinkPunctuation",
                 "foo [link http://www.example.com/]. bar");
            
              MT("vanillaLinkExtension",
                 "foo [link http://www.example.com/index.html] bar");
            
              MT("vanillaLinkEmphasis",
                 "foo [em *][em&link http://www.example.com/index.html][em *] bar");
            
              MT("notALink",
                 "[comment ```css]",
                 "[tag foo] {[property color]:[keyword black];}",
                 "[comment ```][link http://www.example.com/]");
            
              MT("notALink",
                 "[comment ``foo `bar` http://www.example.com/``] hello");
            
              MT("notALink",
                 "[comment `foo]",
                 "[link http://www.example.com/]",
                 "[comment `foo]",
                 "",
                 "[link http://www.example.com/]");
            
              MT("headerCodeBlockGithub",
                 "[header&header-1 # heading]",
                 "",
                 "[comment ```]",
                 "[comment code]",
                 "[comment ```]",
                 "",
                 "Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]",
                 "Issue: [link #1]",
                 "Link: [link http://www.example.com/]");
            
              MT("strikethrough",
                 "[strikethrough ~~foo~~]");
            
              MT("strikethroughWithStartingSpace",
                 "~~ foo~~");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo~~~]");
            
              MT("strikethroughUnclosedStrayTildes",
                 "[strikethrough ~~foo ~~]");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo ~~ bar]");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo ~~ bar~~]hello");
            
              MT("strikethroughOneLetter",
                 "[strikethrough ~~a~~]");
            
              MT("strikethroughWrapped",
                 "[strikethrough ~~foo]",
                 "[strikethrough foo~~]");
            
              MT("strikethroughParagraph",
                 "[strikethrough ~~foo]",
                 "",
                 "foo[strikethrough ~~bar]");
            
              MT("strikethroughEm",
                 "[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]");
            
              MT("strikethroughEm",
                 "[em *][em&strikethrough ~~foo~~][em *]");
            
              MT("strikethroughStrong",
                 "[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]");
            
              MT("strikethroughStrong",
                 "[strong **][strong&strikethrough ~~foo~~][strong **]");
            
            })();
            
        • gherkin
          • gherkin.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
            Gherkin mode - http://www.cukes.info/
            Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
            */
            
            // Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js
            //var Quotes = {
            //  SINGLE: 1,
            //  DOUBLE: 2
            //};
            
            //var regex = {
            //  keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/
            //};
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gherkin", function () {
              return {
                startState: function () {
                  return {
                    lineNumber: 0,
                    tableHeaderLine: false,
                    allowFeature: true,
                    allowBackground: false,
                    allowScenario: false,
                    allowSteps: false,
                    allowPlaceholders: false,
                    allowMultilineArgument: false,
                    inMultilineString: false,
                    inMultilineTable: false,
                    inKeywordLine: false
                  };
                },
                token: function (stream, state) {
                  if (stream.sol()) {
                    state.lineNumber++;
                    state.inKeywordLine = false;
                    if (state.inMultilineTable) {
                        state.tableHeaderLine = false;
                        if (!stream.match(/\s*\|/, false)) {
                          state.allowMultilineArgument = false;
                          state.inMultilineTable = false;
                        }
                    }
                  }
            
                  stream.eatSpace();
            
                  if (state.allowMultilineArgument) {
            
                    // STRING
                    if (state.inMultilineString) {
                      if (stream.match('"""')) {
                        state.inMultilineString = false;
                        state.allowMultilineArgument = false;
                      } else {
                        stream.match(/.*/);
                      }
                      return "string";
                    }
            
                    // TABLE
                    if (state.inMultilineTable) {
                      if (stream.match(/\|\s*/)) {
                        return "bracket";
                      } else {
                        stream.match(/[^\|]*/);
                        return state.tableHeaderLine ? "header" : "string";
                      }
                    }
            
                    // DETECT START
                    if (stream.match('"""')) {
                      // String
                      state.inMultilineString = true;
                      return "string";
                    } else if (stream.match("|")) {
                      // Table
                      state.inMultilineTable = true;
                      state.tableHeaderLine = true;
                      return "bracket";
                    }
            
                  }
            
                  // LINE COMMENT
                  if (stream.match(/#.*/)) {
                    return "comment";
            
                  // TAG
                  } else if (!state.inKeywordLine && stream.match(/@\S+/)) {
                    return "tag";
            
                  // FEATURE
                  } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) {
                    state.allowScenario = true;
                    state.allowBackground = true;
                    state.allowPlaceholders = false;
                    state.allowSteps = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // BACKGROUND
                  } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // SCENARIO OUTLINE
                  } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) {
                    state.allowPlaceholders = true;
                    state.allowSteps = true;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // EXAMPLES
                  } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = true;
                    return "keyword";
            
                  // SCENARIO
                  } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // STEPS
                  } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) {
                    state.inStep = true;
                    state.allowPlaceholders = true;
                    state.allowMultilineArgument = true;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // INLINE STRING
                  } else if (stream.match(/"[^"]*"?/)) {
                    return "string";
            
                  // PLACEHOLDER
                  } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) {
                    return "variable";
            
                  // Fall through
                  } else {
                    stream.next();
                    stream.eatWhile(/[^@"<#]/);
                    return null;
                  }
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-feature", "gherkin");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Gherkin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="gherkin.js"></script>
            <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Gherkin</a>
              </ul>
            </div>
            
            <article>
            <h2>Gherkin mode</h2>
            <form><textarea id="code" name="code">
            Feature: Using Google
              Background: 
                Something something
                Something else
              Scenario: Has a homepage
                When I navigate to the google home page
                Then the home page should contain the menu and the search form
              Scenario: Searching for a term 
                When I navigate to the google home page
                When I search for Tofu
                Then the search results page is displayed
                Then the search results page contains 10 individual search results
                Then the search results contain a link to the wikipedia tofu page
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-feature</code>.</p>
            
              </article>
            
        • go
          • go.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("go", function(config) {
              var indentUnit = config.indentUnit;
            
              var keywords = {
                "break":true, "case":true, "chan":true, "const":true, "continue":true,
                "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
                "func":true, "go":true, "goto":true, "if":true, "import":true,
                "interface":true, "map":true, "package":true, "range":true, "return":true,
                "select":true, "struct":true, "switch":true, "type":true, "var":true,
                "bool":true, "byte":true, "complex64":true, "complex128":true,
                "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
                "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
                "uint64":true, "int":true, "uint":true, "uintptr":true
              };
            
              var atoms = {
                "true":true, "false":true, "iota":true, "nil":true, "append":true,
                "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
                "len":true, "make":true, "new":true, "panic":true, "print":true,
                "println":true, "real":true, "recover":true
              };
            
              var isOperatorChar = /[+\-*&^%:=<>!|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'" || ch == "`") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\d\.]/.test(ch)) {
                  if (ch == ".") {
                    stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
                  } else if (ch == "0") {
                    stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
                  } else {
                    stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
                  }
                  return "number";
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (cur == "case" || cur == "default") curPunc = "case";
                  return "keyword";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || quote == "`"))
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                if (!state.context.prev) return;
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    if (ctx.type == "case") ctx.type = "}";
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "case") ctx.type = "case";
                  else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
                  else if (curPunc == ctx.type) popContext(state);
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return 0;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
                    state.context.type = "}";
                    return ctx.indented;
                  }
                  var closing = firstChar == ctx.type;
                  if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}):",
                fold: "brace",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
            CodeMirror.defineMIME("text/x-go", "go");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Go mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="go.js"></script>
            <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Go</a>
              </ul>
            </div>
            
            <article>
            <h2>Go mode</h2>
            <form><textarea id="code" name="code">
            // Prime Sieve in Go.
            // Taken from the Go specification.
            // Copyright © The Go Authors.
            
            package main
            
            import "fmt"
            
            // Send the sequence 2, 3, 4, ... to channel 'ch'.
            func generate(ch chan&lt;- int) {
            	for i := 2; ; i++ {
            		ch &lt;- i  // Send 'i' to channel 'ch'
            	}
            }
            
            // Copy the values from channel 'src' to channel 'dst',
            // removing those divisible by 'prime'.
            func filter(src &lt;-chan int, dst chan&lt;- int, prime int) {
            	for i := range src {    // Loop over values received from 'src'.
            		if i%prime != 0 {
            			dst &lt;- i  // Send 'i' to channel 'dst'.
            		}
            	}
            }
            
            // The prime sieve: Daisy-chain filter processes together.
            func sieve() {
            	ch := make(chan int)  // Create a new channel.
            	go generate(ch)       // Start generate() as a subprocess.
            	for {
            		prime := &lt;-ch
            		fmt.Print(prime, "\n")
            		ch1 := make(chan int)
            		go filter(ch, ch1, prime)
            		ch = ch1
            	}
            }
            
            func main() {
            	sieve()
            }
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "elegant",
                    matchBrackets: true,
                    indentUnit: 8,
                    tabSize: 8,
                    indentWithTabs: true,
                    mode: "text/x-go"
                  });
                </script>
            
                <p><strong>MIME type:</strong> <code>text/x-go</code></p>
              </article>
            
        • groovy
          • groovy.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("groovy", function(config) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = words(
                "abstract as assert boolean break byte case catch char class const continue def default " +
                "do double else enum extends final finally float for goto if implements import in " +
                "instanceof int interface long native new package private protected public return " +
                "short static strictfp super switch synchronized threadsafe throw throws transient " +
                "try void volatile while");
              var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
              var atoms = words("null true false this");
            
              var curPunc;
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  return startString(ch, stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize.push(tokenComment);
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (expectExpression(state.lastToken)) {
                    return startString(ch, stream, state);
                  }
                }
                if (ch == "-" && stream.eat(">")) {
                  curPunc = "->";
                  return null;
                }
                if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
                  stream.eatWhile(/[+\-*&%=<>|~]/);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
                if (state.lastToken == ".") return "property";
                if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
                var cur = stream.current();
                if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                return "variable";
              }
              tokenBase.isBase = true;
            
              function startString(quote, stream, state) {
                var tripleQuoted = false;
                if (quote != "/" && stream.eat(quote)) {
                  if (stream.eat(quote)) tripleQuoted = true;
                  else return "string";
                }
                function t(stream, state) {
                  var escaped = false, next, end = !tripleQuoted;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      if (!tripleQuoted) { break; }
                      if (stream.match(quote + quote)) { end = true; break; }
                    }
                    if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
                      state.tokenize.push(tokenBaseUntilBrace());
                      return "string";
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end) state.tokenize.pop();
                  return "string";
                }
                state.tokenize.push(t);
                return t(stream, state);
              }
            
              function tokenBaseUntilBrace() {
                var depth = 1;
                function t(stream, state) {
                  if (stream.peek() == "}") {
                    depth--;
                    if (depth == 0) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length-1](stream, state);
                    }
                  } else if (stream.peek() == "{") {
                    depth++;
                  }
                  return tokenBase(stream, state);
                }
                t.isBase = true;
                return t;
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize.pop();
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function expectExpression(last) {
                return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
                  last == "newstatement" || last == "keyword" || last == "proplabel";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: [tokenBase],
                    context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true,
                    lastToken: null
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    // Automatic semicolon insertion
                    if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
                      popContext(state); ctx = state.context;
                    }
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = state.tokenize[state.tokenize.length-1](stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  // Handle indentation for {x -> \n ... }
                  else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
                    popContext(state);
                    state.context.align = false;
                  }
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  state.lastToken = curPunc || style;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
                  if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : config.indentUnit);
                },
            
                electricChars: "{}",
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME("text/x-groovy", "groovy");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Groovy mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="groovy.js"></script>
            <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Groovy</a>
              </ul>
            </div>
            
            <article>
            <h2>Groovy mode</h2>
            <form><textarea id="code" name="code">
            //Pattern for groovy script
            def p = ~/.*\.groovy/
            new File( 'd:\\scripts' ).eachFileMatch(p) {f ->
              // imports list
              def imports = []
              f.eachLine {
                // condition to detect an import instruction
                ln -> if ( ln =~ '^import .*' ) {
                  imports << "${ln - 'import '}"
                }
              }
              // print thmen
              if ( ! imports.empty ) {
                println f
                imports.each{ println "   $it" }
              }
            }
            
            /* Coin changer demo code from http://groovy.codehaus.org */
            
            enum UsCoin {
              quarter(25), dime(10), nickel(5), penny(1)
              UsCoin(v) { value = v }
              final value
            }
            
            enum OzzieCoin {
              fifty(50), twenty(20), ten(10), five(5)
              OzzieCoin(v) { value = v }
              final value
            }
            
            def plural(word, count) {
              if (count == 1) return word
              word[-1] == 'y' ? word[0..-2] + "ies" : word + "s"
            }
            
            def change(currency, amount) {
              currency.values().inject([]){ list, coin ->
                 int count = amount / coin.value
                 amount = amount % coin.value
                 list += "$count ${plural(coin.toString(), count)}"
              }
            }
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-groovy"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-groovy</code></p>
              </article>
            
        • haml
          • haml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
              // full haml mode. This handled embeded ruby and html fragments too
              CodeMirror.defineMode("haml", function(config) {
                var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
                var rubyMode = CodeMirror.getMode(config, "ruby");
            
                function rubyInQuote(endQuote) {
                  return function(stream, state) {
                    var ch = stream.peek();
                    if (ch == endQuote && state.rubyState.tokenize.length == 1) {
                      // step out of ruby context as it seems to complete processing all the braces
                      stream.next();
                      state.tokenize = html;
                      return "closeAttributeTag";
                    } else {
                      return ruby(stream, state);
                    }
                  };
                }
            
                function ruby(stream, state) {
                  if (stream.match("-#")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  return rubyMode.token(stream, state.rubyState);
                }
            
                function html(stream, state) {
                  var ch = stream.peek();
            
                  // handle haml declarations. All declarations that cant be handled here
                  // will be passed to html mode
                  if (state.previousToken.style == "comment" ) {
                    if (state.indented > state.previousToken.indented) {
                      stream.skipToEnd();
                      return "commentLine";
                    }
                  }
            
                  if (state.startOfLine) {
                    if (ch == "!" && stream.match("!!")) {
                      stream.skipToEnd();
                      return "tag";
                    } else if (stream.match(/^%[\w:#\.]+=/)) {
                      state.tokenize = ruby;
                      return "hamlTag";
                    } else if (stream.match(/^%[\w:]+/)) {
                      return "hamlTag";
                    } else if (ch == "/" ) {
                      stream.skipToEnd();
                      return "comment";
                    }
                  }
            
                  if (state.startOfLine || state.previousToken.style == "hamlTag") {
                    if ( ch == "#" || ch == ".") {
                      stream.match(/[\w-#\.]*/);
                      return "hamlAttribute";
                    }
                  }
            
                  // donot handle --> as valid ruby, make it HTML close comment instead
                  if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {
                    state.tokenize = ruby;
                    return state.tokenize(stream, state);
                  }
            
                  if (state.previousToken.style == "hamlTag" ||
                      state.previousToken.style == "closeAttributeTag" ||
                      state.previousToken.style == "hamlAttribute") {
                    if (ch == "(") {
                      state.tokenize = rubyInQuote(")");
                      return state.tokenize(stream, state);
                    } else if (ch == "{") {
                      state.tokenize = rubyInQuote("}");
                      return state.tokenize(stream, state);
                    }
                  }
            
                  return htmlMode.token(stream, state.htmlState);
                }
            
                return {
                  // default to html mode
                  startState: function() {
                    var htmlState = htmlMode.startState();
                    var rubyState = rubyMode.startState();
                    return {
                      htmlState: htmlState,
                      rubyState: rubyState,
                      indented: 0,
                      previousToken: { style: null, indented: 0},
                      tokenize: html
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
                      rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
                      indented: state.indented,
                      previousToken: state.previousToken,
                      tokenize: state.tokenize
                    };
                  },
            
                  token: function(stream, state) {
                    if (stream.sol()) {
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                    }
                    if (stream.eatSpace()) return null;
                    var style = state.tokenize(stream, state);
                    state.startOfLine = false;
                    // dont record comment line as we only want to measure comment line with
                    // the opening comment block
                    if (style && style != "commentLine") {
                      state.previousToken = { style: style, indented: state.indented };
                    }
                    // if current state is ruby and the previous token is not `,` reset the
                    // tokenize to html
                    if (stream.eol() && state.tokenize == ruby) {
                      stream.backUp(1);
                      var ch = stream.peek();
                      stream.next();
                      if (ch && ch != ",") {
                        state.tokenize = html;
                      }
                    }
                    // reprocess some of the specific style tag when finish setting previousToken
                    if (style == "hamlTag") {
                      style = "tag";
                    } else if (style == "commentLine") {
                      style = "comment";
                    } else if (style == "hamlAttribute") {
                      style = "attribute";
                    } else if (style == "closeAttributeTag") {
                      style = null;
                    }
                    return style;
                  }
                };
              }, "htmlmixed", "ruby");
            
              CodeMirror.defineMIME("text/x-haml", "haml");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HAML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../ruby/ruby.js"></script>
            <script src="haml.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HAML</a>
              </ul>
            </div>
            
            <article>
            <h2>HAML mode</h2>
            <form><textarea id="code" name="code">
            !!!
            #content
            .left.column(title="title"){:href => "/hello", :test => "#{hello}_#{world}"}
                <!-- This is a comment -->
                %h2 Welcome to our site!
                %p= puts "HAML MODE"
              .right.column
                = render :partial => "sidebar"
            
            .container
              .row
                .span8
                  %h1.title= @page_title
            %p.title= @page_title
            %p
              /
                The same as HTML comment
                Hello multiline comment
            
              -# haml comment
                  This wont be displayed
                  nor will this
              Date/Time:
              - now = DateTime.now
              %strong= now
              - if now > DateTime.parse("December 31, 2006")
                = "Happy new " + "year!"
            
            %title
              = @title
              \= @title
              <h1>Title</h1>
              <h1 title="HELLO">
                Title
              </h1>
                </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-haml"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haml</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#haml_*">normal</a>,  <a href="../../test/index.html#verbose,haml_*">verbose</a>.</p>
            
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Requires at least one media query
              MT("elementName",
                 "[tag %h1] Hey There");
            
              MT("oneElementPerLine",
                 "[tag %h1] Hey There %h2");
            
              MT("idSelector",
                 "[tag %h1][attribute #test] Hey There");
            
              MT("classSelector",
                 "[tag %h1][attribute .hello] Hey There");
            
              MT("docType",
                 "[tag !!! XML]");
            
              MT("comment",
                 "[comment / Hello WORLD]");
            
              MT("notComment",
                 "[tag %h1] This is not a / comment ");
            
              MT("attributes",
                 "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}");
            
              MT("htmlCode",
                 "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
            
              MT("rubyBlock",
                 "[operator =][variable-2 @item]");
            
              MT("selectorRubyBlock",
                 "[tag %a.selector=] [variable-2 @item]");
            
              MT("nestedRubyBlock",
                  "[tag %a]",
                  "   [operator =][variable puts] [string \"test\"]");
            
              MT("multilinePlaintext",
                  "[tag %p]",
                  "  Hello,",
                  "  World");
            
              MT("multilineRuby",
                  "[tag %p]",
                  "  [comment -# this is a comment]",
                  "     [comment and this is a comment too]",
                  "  Date/Time",
                  "  [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]",
                  "  [tag %strong=] [variable now]",
                  "  [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
                  "     [operator =][string \"Happy\"]",
                  "     [operator =][string \"Belated\"]",
                  "     [operator =][string \"Birthday\"]");
            
              MT("multilineComment",
                  "[comment /]",
                  "  [comment Multiline]",
                  "  [comment Comment]");
            
              MT("hamlComment",
                 "[comment -# this is a comment]");
            
              MT("multilineHamlComment",
                 "[comment -# this is a comment]",
                 "   [comment and this is a comment too]");
            
              MT("multilineHTMLComment",
                "[comment <!--]",
                "  [comment what a comment]",
                "  [comment -->]");
            
              MT("hamlAfterRubyTag",
                "[attribute .block]",
                "  [tag %strong=] [variable now]",
                "  [attribute .test]",
                "     [operator =][variable now]",
                "  [attribute .right]");
            
              MT("stretchedRuby",
                 "[operator =] [variable puts] [string \"Hello\"],",
                 "   [string \"World\"]");
            
              MT("interpolationInHashAttribute",
                 //"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
                 "[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
            
              MT("interpolationInHTMLAttribute",
                 "[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test");
            })();
            
        • haskell
          • haskell.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("haskell", function(_config, modeConfig) {
            
              function switchState(source, setState, f) {
                setState(f);
                return f(source, setState);
              }
            
              // These should all be Unicode extended, as per the Haskell 2010 report
              var smallRE = /[a-z_]/;
              var largeRE = /[A-Z]/;
              var digitRE = /\d/;
              var hexitRE = /[0-9A-Fa-f]/;
              var octitRE = /[0-7]/;
              var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/;
              var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
              var specialRE = /[(),;[\]`{}]/;
              var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
            
              function normal(source, setState) {
                if (source.eatWhile(whiteCharRE)) {
                  return null;
                }
            
                var ch = source.next();
                if (specialRE.test(ch)) {
                  if (ch == '{' && source.eat('-')) {
                    var t = "comment";
                    if (source.eat('#')) {
                      t = "meta";
                    }
                    return switchState(source, setState, ncomment(t, 1));
                  }
                  return null;
                }
            
                if (ch == '\'') {
                  if (source.eat('\\')) {
                    source.next();  // should handle other escapes here
                  }
                  else {
                    source.next();
                  }
                  if (source.eat('\'')) {
                    return "string";
                  }
                  return "error";
                }
            
                if (ch == '"') {
                  return switchState(source, setState, stringLiteral);
                }
            
                if (largeRE.test(ch)) {
                  source.eatWhile(idRE);
                  if (source.eat('.')) {
                    return "qualifier";
                  }
                  return "variable-2";
                }
            
                if (smallRE.test(ch)) {
                  source.eatWhile(idRE);
                  return "variable";
                }
            
                if (digitRE.test(ch)) {
                  if (ch == '0') {
                    if (source.eat(/[xX]/)) {
                      source.eatWhile(hexitRE); // should require at least 1
                      return "integer";
                    }
                    if (source.eat(/[oO]/)) {
                      source.eatWhile(octitRE); // should require at least 1
                      return "number";
                    }
                  }
                  source.eatWhile(digitRE);
                  var t = "number";
                  if (source.match(/^\.\d+/)) {
                    t = "number";
                  }
                  if (source.eat(/[eE]/)) {
                    t = "number";
                    source.eat(/[-+]/);
                    source.eatWhile(digitRE); // should require at least 1
                  }
                  return t;
                }
            
                if (ch == "." && source.eat("."))
                  return "keyword";
            
                if (symbolRE.test(ch)) {
                  if (ch == '-' && source.eat(/-/)) {
                    source.eatWhile(/-/);
                    if (!source.eat(symbolRE)) {
                      source.skipToEnd();
                      return "comment";
                    }
                  }
                  var t = "variable";
                  if (ch == ':') {
                    t = "variable-2";
                  }
                  source.eatWhile(symbolRE);
                  return t;
                }
            
                return "error";
              }
            
              function ncomment(type, nest) {
                if (nest == 0) {
                  return normal;
                }
                return function(source, setState) {
                  var currNest = nest;
                  while (!source.eol()) {
                    var ch = source.next();
                    if (ch == '{' && source.eat('-')) {
                      ++currNest;
                    }
                    else if (ch == '-' && source.eat('}')) {
                      --currNest;
                      if (currNest == 0) {
                        setState(normal);
                        return type;
                      }
                    }
                  }
                  setState(ncomment(type, currNest));
                  return type;
                };
              }
            
              function stringLiteral(source, setState) {
                while (!source.eol()) {
                  var ch = source.next();
                  if (ch == '"') {
                    setState(normal);
                    return "string";
                  }
                  if (ch == '\\') {
                    if (source.eol() || source.eat(whiteCharRE)) {
                      setState(stringGap);
                      return "string";
                    }
                    if (source.eat('&')) {
                    }
                    else {
                      source.next(); // should handle other escapes here
                    }
                  }
                }
                setState(normal);
                return "error";
              }
            
              function stringGap(source, setState) {
                if (source.eat('\\')) {
                  return switchState(source, setState, stringLiteral);
                }
                source.next();
                setState(normal);
                return "error";
              }
            
            
              var wellKnownWords = (function() {
                var wkw = {};
                function setType(t) {
                  return function () {
                    for (var i = 0; i < arguments.length; i++)
                      wkw[arguments[i]] = t;
                  };
                }
            
                setType("keyword")(
                  "case", "class", "data", "default", "deriving", "do", "else", "foreign",
                  "if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
                  "module", "newtype", "of", "then", "type", "where", "_");
            
                setType("keyword")(
                  "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
            
                setType("builtin")(
                  "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
                  "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
            
                setType("builtin")(
                  "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
                  "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
                  "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
                  "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
                  "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
                  "String", "True");
            
                setType("builtin")(
                  "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
                  "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
                  "compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
                  "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
                  "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
                  "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
                  "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
                  "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
                  "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
                  "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
                  "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
                  "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
                  "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
                  "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
                  "otherwise", "pi", "pred", "print", "product", "properFraction",
                  "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
                  "readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
                  "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
                  "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
                  "sequence", "sequence_", "show", "showChar", "showList", "showParen",
                  "showString", "shows", "showsPrec", "significand", "signum", "sin",
                  "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
                  "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
                  "toRational", "truncate", "uncurry", "undefined", "unlines", "until",
                  "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
                  "zip3", "zipWith", "zipWith3");
            
                var override = modeConfig.overrideKeywords;
                if (override) for (var word in override) if (override.hasOwnProperty(word))
                  wkw[word] = override[word];
            
                return wkw;
              })();
            
            
            
              return {
                startState: function ()  { return { f: normal }; },
                copyState:  function (s) { return { f: s.f }; },
            
                token: function(stream, state) {
                  var t = state.f(stream, function(s) { state.f = s; });
                  var w = stream.current();
                  return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
                },
            
                blockCommentStart: "{-",
                blockCommentEnd: "-}",
                lineComment: "--"
              };
            
            });
            
            CodeMirror.defineMIME("text/x-haskell", "haskell");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Haskell mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="haskell.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Haskell</a>
              </ul>
            </div>
            
            <article>
            <h2>Haskell mode</h2>
            <form><textarea id="code" name="code">
            module UniquePerms (
                uniquePerms
                )
            where
            
            -- | Find all unique permutations of a list where there might be duplicates.
            uniquePerms :: (Eq a) => [a] -> [[a]]
            uniquePerms = permBag . makeBag
            
            -- | An unordered collection where duplicate values are allowed,
            -- but represented with a single value and a count.
            type Bag a = [(a, Int)]
            
            makeBag :: (Eq a) => [a] -> Bag a
            makeBag [] = []
            makeBag (a:as) = mix a $ makeBag as
              where
                mix a []                        = [(a,1)]
                mix a (bn@(b,n):bs) | a == b    = (b,n+1):bs
                                    | otherwise = bn : mix a bs
            
            permBag :: Bag a -> [[a]]
            permBag [] = [[]]
            permBag bs = concatMap (\(f,cs) -> map (f:) $ permBag cs) . oneOfEach $ bs
              where
                oneOfEach [] = []
                oneOfEach (an@(a,n):bs) =
                    let bs' = if n == 1 then bs else (a,n-1):bs
                    in (a,bs') : mapSnd (an:) (oneOfEach bs)
                
                apSnd f (a,b) = (a, f b)
                mapSnd = map . apSnd
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "elegant"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haskell</code>.</p>
              </article>
            
        • haxe
          • haxe.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("haxe", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
            
              // Tokenizer
            
              var keywords = function(){
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
                var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"};
              var type = kw("typedef");
                return {
                  "if": A, "while": A, "else": B, "do": B, "try": B,
                  "return": C, "break": C, "continue": C, "new": C, "throw": C,
                  "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
                "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
                  "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
                  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
                  "in": operator, "never": kw("property_access"), "trace":kw("trace"),
                "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
                  "true": atom, "false": atom, "null": atom
                };
              }();
            
              var isOperatorChar = /[+\-*&%=<>!?|]/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              function nextUntilUnescaped(stream, end) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (next == end && !escaped)
                    return false;
                  escaped = !escaped && next == "\\";
                }
                return escaped;
              }
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
              function ret(tp, style, cont) {
                type = tp; content = cont;
                return style;
              }
            
              function haxeTokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'")
                  return chain(stream, state, haxeTokenString(ch));
                else if (/[\[\]{}\(\),;\:\.]/.test(ch))
                  return ret(ch);
                else if (ch == "0" && stream.eat(/x/i)) {
                  stream.eatWhile(/[\da-f]/i);
                  return ret("number", "number");
                }
                else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
                  stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
                  return ret("number", "number");
                }
                else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
                  nextUntilUnescaped(stream, "/");
                  stream.eatWhile(/[gimsu]/);
                  return ret("regexp", "string-2");
                }
                else if (ch == "/") {
                  if (stream.eat("*")) {
                    return chain(stream, state, haxeTokenComment);
                  }
                  else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", null, stream.current());
                  }
                }
                else if (ch == "#") {
                    stream.skipToEnd();
                    return ret("conditional", "meta");
                }
                else if (ch == "@") {
                  stream.eat(/:/);
                  stream.eatWhile(/[\w_]/);
                  return ret ("metadata", "meta");
                }
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return ret("operator", null, stream.current());
                }
                else {
                var word;
                if(/[A-Z]/.test(ch))
                {
                  stream.eatWhile(/[\w_<>]/);
                  word = stream.current();
                  return ret("type", "variable-3", word);
                }
                else
                {
                    stream.eatWhile(/[\w_]/);
                    var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
                    return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
                                   ret("variable", "variable", word);
                }
                }
              }
            
              function haxeTokenString(quote) {
                return function(stream, state) {
                  if (!nextUntilUnescaped(stream, quote))
                    state.tokenize = haxeTokenBase;
                  return ret("string", "string");
                };
              }
            
              function haxeTokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = haxeTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              // Parser
            
              var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
            
              function HaxeLexical(indented, column, type, align, prev, info) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.prev = prev;
                this.info = info;
                if (align != null) this.align = align;
              }
            
              function inScope(state, varname) {
                for (var v = state.localVars; v; v = v.next)
                  if (v.name == varname) return true;
              }
            
              function parseHaxe(state, style, type, content, stream) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
            
                if (!state.lexical.hasOwnProperty("align"))
                  state.lexical.align = true;
            
                while(true) {
                  var combinator = cc.length ? cc.pop() : statement;
                  if (combinator(type, content)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    if (cx.marked) return cx.marked;
                    if (type == "variable" && inScope(state, content)) return "variable-2";
                if (type == "variable" && imported(state, content)) return "variable-3";
                    return style;
                  }
                }
              }
            
              function imported(state, typename)
              {
              if (/[a-z]/.test(typename.charAt(0)))
                return false;
              var len = state.importedtypes.length;
              for (var i = 0; i<len; i++)
                if(state.importedtypes[i]==typename) return true;
              }
            
            
              function registerimport(importname) {
              var state = cx.state;
              for (var t = state.importedtypes; t; t = t.next)
                if(t.name == importname) return;
              state.importedtypes = { name: importname, next: state.importedtypes };
              }
              // Combinator utils
            
              var cx = {state: null, column: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
              function register(varname) {
                var state = cx.state;
                if (state.context) {
                  cx.marked = "def";
                  for (var v = state.localVars; v; v = v.next)
                    if (v.name == varname) return;
                  state.localVars = {name: varname, next: state.localVars};
                }
              }
            
              // Combinators
            
              var defaultVars = {name: "this", next: null};
              function pushcontext() {
                if (!cx.state.context) cx.state.localVars = defaultVars;
                cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
              }
              function popcontext() {
                cx.state.localVars = cx.state.context.vars;
                cx.state.context = cx.state.context.prev;
              }
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state;
                  state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              poplex.lex = true;
            
              function expect(wanted) {
                function f(type) {
                  if (type == wanted) return cont();
                  else if (wanted == ";") return pass();
                  else return cont(f);
                };
                return f;
              }
            
              function statement(type) {
                if (type == "@") return cont(metadef);
                if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
                if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
                if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
                if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext);
                if (type == ";") return cont();
                if (type == "attribute") return cont(maybeattribute);
                if (type == "function") return cont(functiondef);
                if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
                                                  poplex, statement, poplex);
                if (type == "variable") return cont(pushlex("stat"), maybelabel);
                if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
                                                     block, poplex, poplex);
                if (type == "case") return cont(expression, expect(":"));
                if (type == "default") return cont(expect(":"));
                if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
                                                    statement, poplex, popcontext);
                if (type == "import") return cont(importdef, expect(";"));
                if (type == "typedef") return cont(typedef);
                return pass(pushlex("stat"), expression, expect(";"), poplex);
              }
              function expression(type) {
                if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
                if (type == "function") return cont(functiondef);
                if (type == "keyword c") return cont(maybeexpression);
                if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
                if (type == "operator") return cont(expression);
                if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
                if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
                return cont();
              }
              function maybeexpression(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expression);
              }
            
              function maybeoperator(type, value) {
                if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
                if (type == "operator" || type == ":") return cont(expression);
                if (type == ";") return;
                if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
                if (type == ".") return cont(property, maybeoperator);
                if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
              }
            
              function maybeattribute(type) {
                if (type == "attribute") return cont(maybeattribute);
                if (type == "function") return cont(functiondef);
                if (type == "var") return cont(vardef1);
              }
            
              function metadef(type) {
                if(type == ":") return cont(metadef);
                if(type == "variable") return cont(metadef);
                if(type == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement);
              }
              function metaargs(type) {
                if(type == "variable") return cont();
              }
            
              function importdef (type, value) {
              if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
              else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);
              }
            
              function typedef (type, value)
              {
              if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
              else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }
              }
            
              function maybelabel(type) {
                if (type == ":") return cont(poplex, statement);
                return pass(maybeoperator, expect(";"), poplex);
              }
              function property(type) {
                if (type == "variable") {cx.marked = "property"; return cont();}
              }
              function objprop(type) {
                if (type == "variable") cx.marked = "property";
                if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
              }
              function commasep(what, end) {
                function proceed(type) {
                  if (type == ",") return cont(what, proceed);
                  if (type == end) return cont();
                  return cont(expect(end));
                }
                return function(type) {
                  if (type == end) return cont();
                  else return pass(what, proceed);
                };
              }
              function block(type) {
                if (type == "}") return cont();
                return pass(statement, block);
              }
              function vardef1(type, value) {
                if (type == "variable"){register(value); return cont(typeuse, vardef2);}
                return cont();
              }
              function vardef2(type, value) {
                if (value == "=") return cont(expression, vardef2);
                if (type == ",") return cont(vardef1);
              }
              function forspec1(type, value) {
              if (type == "variable") {
                register(value);
              }
              return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
              }
              function forin(_type, value) {
                if (value == "in") return cont();
              }
              function functiondef(type, value) {
                if (type == "variable") {register(value); return cont(functiondef);}
                if (value == "new") return cont(functiondef);
                if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
              }
              function typeuse(type) {
                if(type == ":") return cont(typestring);
              }
              function typestring(type) {
                if(type == "type") return cont();
                if(type == "variable") return cont();
                if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
              }
              function typeprop(type) {
                if(type == "variable") return cont(typeuse);
              }
              function funarg(type, value) {
                if (type == "variable") {register(value); return cont(typeuse);}
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
                  return {
                    tokenize: haxeTokenBase,
                    reAllowed: true,
                    kwAllowed: true,
                    cc: [],
                    lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
                    localVars: parserConfig.localVars,
                importedtypes: defaulttypes,
                    context: parserConfig.localVars && {vars: parserConfig.localVars},
                    indented: 0
                  };
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (type == "comment") return style;
                  state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
                  state.kwAllowed = type != '.';
                  return parseHaxe(state, style, type, content, stream);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != haxeTokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
                  if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
                  var type = lexical.type, closing = firstChar == type;
                  if (type == "vardef") return lexical.indented + 4;
                  else if (type == "form" && firstChar == "{") return lexical.indented;
                  else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
                  else if (lexical.info == "switch" && !closing)
                    return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
                  else if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  else return lexical.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
            CodeMirror.defineMIME("text/x-haxe", "haxe");
            
            CodeMirror.defineMode("hxml", function () {
            
              return {
                startState: function () {
                  return {
                    define: false,
                    inString: false
                  };
                },
                token: function (stream, state) {
                  var ch = stream.peek();
                  var sol = stream.sol();
            
                  ///* comments */
                  if (ch == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (sol && ch == "-") {
                    var style = "variable-2";
            
                    stream.eat(/-/);
            
                    if (stream.peek() == "-") {
                      stream.eat(/-/);
                      style = "keyword a";
                    }
            
                    if (stream.peek() == "D") {
                      stream.eat(/[D]/);
                      style = "keyword c";
                      state.define = true;
                    }
            
                    stream.eatWhile(/[A-Z]/i);
                    return style;
                  }
            
                  var ch = stream.peek();
            
                  if (state.inString == false && ch == "'") {
                    state.inString = true;
                    ch = stream.next();
                  }
            
                  if (state.inString == true) {
                    if (stream.skipTo("'")) {
            
                    } else {
                      stream.skipToEnd();
                    }
            
                    if (stream.peek() == "'") {
                      stream.next();
                      state.inString = false;
                    }
            
                    return "string";
                  }
            
                  stream.next();
                  return null;
                },
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-hxml", "hxml");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Haxe mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="haxe.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Haxe</a>
              </ul>
            </div>
            
            <article>
            <h2>Haxe mode</h2>
            
            
            <div><p><textarea id="code-haxe" name="code">
            import one.two.Three;
            
            @attr("test")
            class Foo&lt;T&gt; extends Three
            {
            	public function new()
            	{
            		noFoo = 12;
            	}
            	
            	public static inline function doFoo(obj:{k:Int, l:Float}):Int
            	{
            		for(i in 0...10)
            		{
            			obj.k++;
            			trace(i);
            			var var1 = new Array();
            			if(var1.length > 1)
            				throw "Error";
            		}
            		// The following line should not be colored, the variable is scoped out
            		var1;
            		/* Multi line
            		 * Comment test
            		 */
            		return obj.k;
            	}
            	private function bar():Void
            	{
            		#if flash
            		var t1:String = "1.21";
            		#end
            		try {
            			doFoo({k:3, l:1.2});
            		}
            		catch (e : String) {
            			trace(e);
            		}
            		var t2:Float = cast(3.2);
            		var t3:haxe.Timer = new haxe.Timer();
            		var t4 = {k:Std.int(t2), l:Std.parseFloat(t1)};
            		var t5 = ~/123+.*$/i;
            		doFoo(t4);
            		untyped t1 = 4;
            		bob = new Foo&lt;Int&gt;
            	}
            	public var okFoo(default, never):Float;
            	var noFoo(getFoo, null):Int;
            	function getFoo():Int {
            		return noFoo;
            	}
            	
            	public var three:Int;
            }
            enum Color
            {
            	red;
            	green;
            	blue;
            	grey( v : Int );
            	rgb (r:Int,g:Int,b:Int);
            }
            </textarea></p>
            
            <p>Hxml mode:</p>
            
            <p><textarea id="code-hxml">
            -cp test
            -js path/to/file.js
            #-remap nme:flash
            --next
            -D source-map-content
            -cmd 'test'
            -lib lime
            </textarea></p>
            </div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code-haxe"), {
                  	mode: "haxe",
                    lineNumbers: true,
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                  
                  editor = CodeMirror.fromTextArea(document.getElementById("code-hxml"), {
                  	mode: "hxml",
                    lineNumbers: true,
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haxe, text/x-hxml</code>.</p>
              </article>
            
        • htmlembedded
          • htmlembedded.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
            
              //config settings
              var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,
                  scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;
            
              //inner modes
              var scriptingMode, htmlMixedMode;
            
              //tokenizer when in html mode
              function htmlDispatch(stream, state) {
                  if (stream.match(scriptStartRegex, false)) {
                      state.token=scriptingDispatch;
                      return scriptingMode.token(stream, state.scriptState);
                      }
                  else
                      return htmlMixedMode.token(stream, state.htmlState);
                }
            
              //tokenizer when in scripting mode
              function scriptingDispatch(stream, state) {
                  if (stream.match(scriptEndRegex, false))  {
                      state.token=htmlDispatch;
                      return htmlMixedMode.token(stream, state.htmlState);
                     }
                  else
                      return scriptingMode.token(stream, state.scriptState);
                     }
            
            
              return {
                startState: function() {
                  scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);
                  htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed");
                  return {
                      token :  parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
                      htmlState : CodeMirror.startState(htmlMixedMode),
                      scriptState : CodeMirror.startState(scriptingMode)
                  };
                },
            
                token: function(stream, state) {
                  return state.token(stream, state);
                },
            
                indent: function(state, textAfter) {
                  if (state.token == htmlDispatch)
                    return htmlMixedMode.indent(state.htmlState, textAfter);
                  else if (scriptingMode.indent)
                    return scriptingMode.indent(state.scriptState, textAfter);
                },
            
                copyState: function(state) {
                  return {
                   token : state.token,
                   htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),
                   scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)
                  };
                },
            
                innerMode: function(state) {
                  if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};
                  else return {state: state.htmlState, mode: htmlMixedMode};
                }
              };
            }, "htmlmixed");
            
            CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
            CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
            CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
            CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Html Embedded Scripts mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="htmlembedded.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Html Embedded Scripts</a>
              </ul>
            </div>
            
            <article>
            <h2>Html Embedded Scripts mode</h2>
            <form><textarea id="code" name="code">
            <%
            function hello(who) {
            	return "Hello " + who;
            }
            %>
            This is an example of EJS (embedded javascript)
            <p>The program says <%= hello("world") %>.</p>
            <script>
            	alert("And here is some normal JS code"); // also colored
            </script>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "application/x-ejs",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
                JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>
            
                <p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET), 
                <code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
              </article>
            
        • htmlmixed
          • htmlmixed.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
              var htmlMode = CodeMirror.getMode(config, {name: "xml",
                                                         htmlMode: true,
                                                         multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
                                                         multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
              var cssMode = CodeMirror.getMode(config, "css");
            
              var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
              scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
                                mode: CodeMirror.getMode(config, "javascript")});
              if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
                var conf = scriptTypesConf[i];
                scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
              }
              scriptTypes.push({matches: /./,
                                mode: CodeMirror.getMode(config, "text/plain")});
            
              function html(stream, state) {
                var tagName = state.htmlState.tagName;
                if (tagName) tagName = tagName.toLowerCase();
                var style = htmlMode.token(stream, state.htmlState);
                if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
                  // Script block: mode to change to depends on type attribute
                  var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
                  scriptType = scriptType ? scriptType[1] : "";
                  if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
                  for (var i = 0; i < scriptTypes.length; ++i) {
                    var tp = scriptTypes[i];
                    if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
                      if (tp.mode) {
                        state.token = script;
                        state.localMode = tp.mode;
                        state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
                      }
                      break;
                    }
                  }
                } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
                  state.token = css;
                  state.localMode = cssMode;
                  state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
                }
                return style;
              }
              function maybeBackup(stream, pat, style) {
                var cur = stream.current();
                var close = cur.search(pat), m;
                if (close > -1) stream.backUp(cur.length - close);
                else if (m = cur.match(/<\/?$/)) {
                  stream.backUp(cur.length);
                  if (!stream.match(pat, false)) stream.match(cur);
                }
                return style;
              }
              function script(stream, state) {
                if (stream.match(/^<\/\s*script\s*>/i, false)) {
                  state.token = html;
                  state.localState = state.localMode = null;
                  return null;
                }
                return maybeBackup(stream, /<\/\s*script\s*>/,
                                   state.localMode.token(stream, state.localState));
              }
              function css(stream, state) {
                if (stream.match(/^<\/\s*style\s*>/i, false)) {
                  state.token = html;
                  state.localState = state.localMode = null;
                  return null;
                }
                return maybeBackup(stream, /<\/\s*style\s*>/,
                                   cssMode.token(stream, state.localState));
              }
            
              return {
                startState: function() {
                  var state = htmlMode.startState();
                  return {token: html, localMode: null, localState: null, htmlState: state};
                },
            
                copyState: function(state) {
                  if (state.localState)
                    var local = CodeMirror.copyState(state.localMode, state.localState);
                  return {token: state.token, localMode: state.localMode, localState: local,
                          htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
                },
            
                token: function(stream, state) {
                  return state.token(stream, state);
                },
            
                indent: function(state, textAfter) {
                  if (!state.localMode || /^\s*<\//.test(textAfter))
                    return htmlMode.indent(state.htmlState, textAfter);
                  else if (state.localMode.indent)
                    return state.localMode.indent(state.localState, textAfter);
                  else
                    return CodeMirror.Pass;
                },
            
                innerMode: function(state) {
                  return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
                }
              };
            }, "xml", "javascript", "css");
            
            CodeMirror.defineMIME("text/html", "htmlmixed");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HTML mixed mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/selection/selection-pointer.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../vbscript/vbscript.js"></script>
            <script src="htmlmixed.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HTML mixed</a>
              </ul>
            </div>
            
            <article>
            <h2>HTML mixed mode</h2>
            <form><textarea id="code" name="code">
            <html style="color: green">
              <!-- this is a comment -->
              <head>
                <title>Mixed HTML Example</title>
                <style type="text/css">
                  h1 {font-family: comic sans; color: #f0f;}
                  div {background: yellow !important;}
                  body {
                    max-width: 50em;
                    margin: 1em 2em 1em 5em;
                  }
                </style>
              </head>
              <body>
                <h1>Mixed HTML Example</h1>
                <script>
                  function jsFunc(arg1, arg2) {
                    if (arg1 && arg2) document.body.innerHTML = "achoo";
                  }
                </script>
              </body>
            </html>
            </textarea></form>
                <script>
                  // Define an extended mixed-mode that understands vbscript and
                  // leaves mustache/handlebars embedded templates in html mode
                  var mixedMode = {
                    name: "htmlmixed",
                    scriptTypes: [{matches: /\/x-handlebars-template|\/x-mustache/i,
                                   mode: null},
                                  {matches: /(text|application)\/(x-)?vb(a|script)/i,
                                   mode: "vbscript"}]
                  };
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: mixedMode,
                    selectionPointer: true
                  });
                </script>
            
                <p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>
            
                <p>It takes an optional mode configuration
                option, <code>scriptTypes</code>, which can be used to add custom
                behavior for specific <code>&lt;script type="..."></code> tags. If
                given, it should hold an array of <code>{matches, mode}</code>
                objects, where <code>matches</code> is a string or regexp that
                matches the script type, and <code>mode</code> is
                either <code>null</code>, for script types that should stay in
                HTML mode, or a <a href="../../doc/manual.html#option_mode">mode
                spec</a> corresponding to the mode that should be used for the
                script.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/html</code>
                (redefined, only takes effect if you load this parser after the
                XML parser).</p>
            
              </article>
            
        • http
          • http.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("http", function() {
              function failFirstLine(stream, state) {
                stream.skipToEnd();
                state.cur = header;
                return "error";
              }
            
              function start(stream, state) {
                if (stream.match(/^HTTP\/\d\.\d/)) {
                  state.cur = responseStatusCode;
                  return "keyword";
                } else if (stream.match(/^[A-Z]+/) && /[ \t]/.test(stream.peek())) {
                  state.cur = requestPath;
                  return "keyword";
                } else {
                  return failFirstLine(stream, state);
                }
              }
            
              function responseStatusCode(stream, state) {
                var code = stream.match(/^\d+/);
                if (!code) return failFirstLine(stream, state);
            
                state.cur = responseStatusText;
                var status = Number(code[0]);
                if (status >= 100 && status < 200) {
                  return "positive informational";
                } else if (status >= 200 && status < 300) {
                  return "positive success";
                } else if (status >= 300 && status < 400) {
                  return "positive redirect";
                } else if (status >= 400 && status < 500) {
                  return "negative client-error";
                } else if (status >= 500 && status < 600) {
                  return "negative server-error";
                } else {
                  return "error";
                }
              }
            
              function responseStatusText(stream, state) {
                stream.skipToEnd();
                state.cur = header;
                return null;
              }
            
              function requestPath(stream, state) {
                stream.eatWhile(/\S/);
                state.cur = requestProtocol;
                return "string-2";
              }
            
              function requestProtocol(stream, state) {
                if (stream.match(/^HTTP\/\d\.\d$/)) {
                  state.cur = header;
                  return "keyword";
                } else {
                  return failFirstLine(stream, state);
                }
              }
            
              function header(stream) {
                if (stream.sol() && !stream.eat(/[ \t]/)) {
                  if (stream.match(/^.*?:/)) {
                    return "atom";
                  } else {
                    stream.skipToEnd();
                    return "error";
                  }
                } else {
                  stream.skipToEnd();
                  return "string";
                }
              }
            
              function body(stream) {
                stream.skipToEnd();
                return null;
              }
            
              return {
                token: function(stream, state) {
                  var cur = state.cur;
                  if (cur != header && cur != body && stream.eatSpace()) return null;
                  return cur(stream, state);
                },
            
                blankLine: function(state) {
                  state.cur = body;
                },
            
                startState: function() {
                  return {cur: start};
                }
              };
            });
            
            CodeMirror.defineMIME("message/http", "http");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HTTP mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="http.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HTTP</a>
              </ul>
            </div>
            
            <article>
            <h2>HTTP mode</h2>
            
            
            <div><textarea id="code" name="code">
            POST /somewhere HTTP/1.1
            Host: example.com
            If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
            Content-Type: application/x-www-form-urlencoded;
            	charset=utf-8
            User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Ubuntu/12.04 Chromium/20.0.1132.47 Chrome/20.0.1132.47 Safari/536.11
            
            This is the request body!
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>message/http</code>.</p>
              </article>
            
        • idl
          • idl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function wordRegexp(words) {
                return new RegExp('^((' + words.join(')|(') + '))\\b', 'i');
              };
            
              var builtinArray = [
                'a_correlate', 'abs', 'acos', 'adapt_hist_equal', 'alog',
                'alog2', 'alog10', 'amoeba', 'annotate', 'app_user_dir',
                'app_user_dir_query', 'arg_present', 'array_equal', 'array_indices',
                'arrow', 'ascii_template', 'asin', 'assoc', 'atan',
                'axis', 'axis', 'bandpass_filter', 'bandreject_filter', 'barplot',
                'bar_plot', 'beseli', 'beselj', 'beselk', 'besely',
                'beta', 'biginteger', 'bilinear', 'bin_date', 'binary_template',
                'bindgen', 'binomial', 'bit_ffs', 'bit_population', 'blas_axpy',
                'blk_con', 'boolarr', 'boolean', 'boxplot', 'box_cursor',
                'breakpoint', 'broyden', 'bubbleplot', 'butterworth', 'bytarr',
                'byte', 'byteorder', 'bytscl', 'c_correlate', 'calendar',
                'caldat', 'call_external', 'call_function', 'call_method',
                'call_procedure', 'canny', 'catch', 'cd', 'cdf', 'ceil',
                'chebyshev', 'check_math', 'chisqr_cvf', 'chisqr_pdf', 'choldc',
                'cholsol', 'cindgen', 'cir_3pnt', 'clipboard', 'close',
                'clust_wts', 'cluster', 'cluster_tree', 'cmyk_convert', 'code_coverage',
                'color_convert', 'color_exchange', 'color_quan', 'color_range_map',
                'colorbar', 'colorize_sample', 'colormap_applicable',
                'colormap_gradient', 'colormap_rotation', 'colortable',
                'comfit', 'command_line_args', 'common', 'compile_opt', 'complex',
                'complexarr', 'complexround', 'compute_mesh_normals', 'cond', 'congrid',
                'conj', 'constrained_min', 'contour', 'contour', 'convert_coord',
                'convol', 'convol_fft', 'coord2to3', 'copy_lun', 'correlate',
                'cos', 'cosh', 'cpu', 'cramer', 'createboxplotdata',
                'create_cursor', 'create_struct', 'create_view', 'crossp', 'crvlength',
                'ct_luminance', 'cti_test', 'cursor', 'curvefit', 'cv_coord',
                'cvttobm', 'cw_animate', 'cw_animate_getp', 'cw_animate_load',
                'cw_animate_run', 'cw_arcball', 'cw_bgroup', 'cw_clr_index',
                'cw_colorsel', 'cw_defroi', 'cw_field', 'cw_filesel', 'cw_form',
                'cw_fslider', 'cw_light_editor', 'cw_light_editor_get',
                'cw_light_editor_set', 'cw_orient', 'cw_palette_editor',
                'cw_palette_editor_get', 'cw_palette_editor_set', 'cw_pdmenu',
                'cw_rgbslider', 'cw_tmpl', 'cw_zoom', 'db_exists',
                'dblarr', 'dcindgen', 'dcomplex', 'dcomplexarr', 'define_key',
                'define_msgblk', 'define_msgblk_from_file', 'defroi', 'defsysv',
                'delvar', 'dendro_plot', 'dendrogram', 'deriv', 'derivsig',
                'determ', 'device', 'dfpmin', 'diag_matrix', 'dialog_dbconnect',
                'dialog_message', 'dialog_pickfile', 'dialog_printersetup',
                'dialog_printjob', 'dialog_read_image',
                'dialog_write_image', 'dictionary', 'digital_filter', 'dilate', 'dindgen',
                'dissolve', 'dist', 'distance_measure', 'dlm_load', 'dlm_register',
                'doc_library', 'double', 'draw_roi', 'edge_dog', 'efont',
                'eigenql', 'eigenvec', 'ellipse', 'elmhes', 'emboss',
                'empty', 'enable_sysrtn', 'eof', 'eos', 'erase',
                'erf', 'erfc', 'erfcx', 'erode', 'errorplot',
                'errplot', 'estimator_filter', 'execute', 'exit', 'exp',
                'expand', 'expand_path', 'expint', 'extrac', 'extract_slice',
                'f_cvf', 'f_pdf', 'factorial', 'fft', 'file_basename',
                'file_chmod', 'file_copy', 'file_delete', 'file_dirname',
                'file_expand_path', 'file_gunzip', 'file_gzip', 'file_info',
                'file_lines', 'file_link', 'file_mkdir', 'file_move',
                'file_poll_input', 'file_readlink', 'file_same',
                'file_search', 'file_tar', 'file_test', 'file_untar', 'file_unzip',
                'file_which', 'file_zip', 'filepath', 'findgen', 'finite',
                'fix', 'flick', 'float', 'floor', 'flow3',
                'fltarr', 'flush', 'format_axis_values', 'forward_function', 'free_lun',
                'fstat', 'fulstr', 'funct', 'function', 'fv_test',
                'fx_root', 'fz_roots', 'gamma', 'gamma_ct', 'gauss_cvf',
                'gauss_pdf', 'gauss_smooth', 'gauss2dfit', 'gaussfit',
                'gaussian_function', 'gaussint', 'get_drive_list', 'get_dxf_objects',
                'get_kbrd', 'get_login_info',
                'get_lun', 'get_screen_size', 'getenv', 'getwindows', 'greg2jul',
                'grib', 'grid_input', 'grid_tps', 'grid3', 'griddata',
                'gs_iter', 'h_eq_ct', 'h_eq_int', 'hanning', 'hash',
                'hdf', 'hdf5', 'heap_free', 'heap_gc', 'heap_nosave',
                'heap_refcount', 'heap_save', 'help', 'hilbert', 'hist_2d',
                'hist_equal', 'histogram', 'hls', 'hough', 'hqr',
                'hsv', 'i18n_multibytetoutf8',
                'i18n_multibytetowidechar', 'i18n_utf8tomultibyte',
                'i18n_widechartomultibyte',
                'ibeta', 'icontour', 'iconvertcoord', 'idelete', 'identity',
                'idl_base64', 'idl_container', 'idl_validname',
                'idlexbr_assistant', 'idlitsys_createtool',
                'idlunit', 'iellipse', 'igamma', 'igetcurrent', 'igetdata',
                'igetid', 'igetproperty', 'iimage', 'image', 'image_cont',
                'image_statistics', 'image_threshold', 'imaginary', 'imap', 'indgen',
                'int_2d', 'int_3d', 'int_tabulated', 'intarr', 'interpol',
                'interpolate', 'interval_volume', 'invert', 'ioctl', 'iopen',
                'ir_filter', 'iplot', 'ipolygon', 'ipolyline', 'iputdata',
                'iregister', 'ireset', 'iresolve', 'irotate', 'isa',
                'isave', 'iscale', 'isetcurrent', 'isetproperty', 'ishft',
                'isocontour', 'isosurface', 'isurface', 'itext', 'itranslate',
                'ivector', 'ivolume', 'izoom', 'journal', 'json_parse',
                'json_serialize', 'jul2greg', 'julday', 'keyword_set', 'krig2d',
                'kurtosis', 'kw_test', 'l64indgen', 'la_choldc', 'la_cholmprove',
                'la_cholsol', 'la_determ', 'la_eigenproblem', 'la_eigenql', 'la_eigenvec',
                'la_elmhes', 'la_gm_linear_model', 'la_hqr', 'la_invert',
                'la_least_square_equality', 'la_least_squares', 'la_linear_equation',
                'la_ludc', 'la_lumprove', 'la_lusol',
                'la_svd', 'la_tridc', 'la_trimprove', 'la_triql', 'la_trired',
                'la_trisol', 'label_date', 'label_region', 'ladfit', 'laguerre',
                'lambda', 'lambdap', 'lambertw', 'laplacian', 'least_squares_filter',
                'leefilt', 'legend', 'legendre', 'linbcg', 'lindgen',
                'linfit', 'linkimage', 'list', 'll_arc_distance', 'lmfit',
                'lmgr', 'lngamma', 'lnp_test', 'loadct', 'locale_get',
                'logical_and', 'logical_or', 'logical_true', 'lon64arr', 'lonarr',
                'long', 'long64', 'lsode', 'lu_complex', 'ludc',
                'lumprove', 'lusol', 'm_correlate', 'machar', 'make_array',
                'make_dll', 'make_rt', 'map', 'mapcontinents', 'mapgrid',
                'map_2points', 'map_continents', 'map_grid', 'map_image', 'map_patch',
                'map_proj_forward', 'map_proj_image', 'map_proj_info',
                'map_proj_init', 'map_proj_inverse',
                'map_set', 'matrix_multiply', 'matrix_power', 'max', 'md_test',
                'mean', 'meanabsdev', 'mean_filter', 'median', 'memory',
                'mesh_clip', 'mesh_decimate', 'mesh_issolid',
                'mesh_merge', 'mesh_numtriangles',
                'mesh_obj', 'mesh_smooth', 'mesh_surfacearea',
                'mesh_validate', 'mesh_volume',
                'message', 'min', 'min_curve_surf', 'mk_html_help', 'modifyct',
                'moment', 'morph_close', 'morph_distance',
                'morph_gradient', 'morph_hitormiss',
                'morph_open', 'morph_thin', 'morph_tophat', 'multi', 'n_elements',
                'n_params', 'n_tags', 'ncdf', 'newton', 'noise_hurl',
                'noise_pick', 'noise_scatter', 'noise_slur', 'norm', 'obj_class',
                'obj_destroy', 'obj_hasmethod', 'obj_isa', 'obj_new', 'obj_valid',
                'objarr', 'on_error', 'on_ioerror', 'online_help', 'openr',
                'openu', 'openw', 'oplot', 'oploterr', 'orderedhash',
                'p_correlate', 'parse_url', 'particle_trace', 'path_cache', 'path_sep',
                'pcomp', 'plot', 'plot3d', 'plot', 'plot_3dbox',
                'plot_field', 'ploterr', 'plots', 'polar_contour', 'polar_surface',
                'polyfill', 'polyshade', 'pnt_line', 'point_lun', 'polarplot',
                'poly', 'poly_2d', 'poly_area', 'poly_fit', 'polyfillv',
                'polygon', 'polyline', 'polywarp', 'popd', 'powell',
                'pref_commit', 'pref_get', 'pref_set', 'prewitt', 'primes',
                'print', 'printf', 'printd', 'pro', 'product',
                'profile', 'profiler', 'profiles', 'project_vol', 'ps_show_fonts',
                'psafm', 'pseudo', 'ptr_free', 'ptr_new', 'ptr_valid',
                'ptrarr', 'pushd', 'qgrid3', 'qhull', 'qromb',
                'qromo', 'qsimp', 'query_*', 'query_ascii', 'query_bmp',
                'query_csv', 'query_dicom', 'query_gif', 'query_image', 'query_jpeg',
                'query_jpeg2000', 'query_mrsid', 'query_pict', 'query_png', 'query_ppm',
                'query_srf', 'query_tiff', 'query_video', 'query_wav', 'r_correlate',
                'r_test', 'radon', 'randomn', 'randomu', 'ranks',
                'rdpix', 'read', 'readf', 'read_ascii', 'read_binary',
                'read_bmp', 'read_csv', 'read_dicom', 'read_gif', 'read_image',
                'read_interfile', 'read_jpeg', 'read_jpeg2000', 'read_mrsid', 'read_pict',
                'read_png', 'read_ppm', 'read_spr', 'read_srf', 'read_sylk',
                'read_tiff', 'read_video', 'read_wav', 'read_wave', 'read_x11_bitmap',
                'read_xwd', 'reads', 'readu', 'real_part', 'rebin',
                'recall_commands', 'recon3', 'reduce_colors', 'reform', 'region_grow',
                'register_cursor', 'regress', 'replicate',
                'replicate_inplace', 'resolve_all',
                'resolve_routine', 'restore', 'retall', 'return', 'reverse',
                'rk4', 'roberts', 'rot', 'rotate', 'round',
                'routine_filepath', 'routine_info', 'rs_test', 's_test', 'save',
                'savgol', 'scale3', 'scale3d', 'scatterplot', 'scatterplot3d',
                'scope_level', 'scope_traceback', 'scope_varfetch',
                'scope_varname', 'search2d',
                'search3d', 'sem_create', 'sem_delete', 'sem_lock', 'sem_release',
                'set_plot', 'set_shading', 'setenv', 'sfit', 'shade_surf',
                'shade_surf_irr', 'shade_volume', 'shift', 'shift_diff', 'shmdebug',
                'shmmap', 'shmunmap', 'shmvar', 'show3', 'showfont',
                'signum', 'simplex', 'sin', 'sindgen', 'sinh',
                'size', 'skewness', 'skip_lun', 'slicer3', 'slide_image',
                'smooth', 'sobel', 'socket', 'sort', 'spawn',
                'sph_4pnt', 'sph_scat', 'spher_harm', 'spl_init', 'spl_interp',
                'spline', 'spline_p', 'sprsab', 'sprsax', 'sprsin',
                'sprstp', 'sqrt', 'standardize', 'stddev', 'stop',
                'strarr', 'strcmp', 'strcompress', 'streamline', 'streamline',
                'stregex', 'stretch', 'string', 'strjoin', 'strlen',
                'strlowcase', 'strmatch', 'strmessage', 'strmid', 'strpos',
                'strput', 'strsplit', 'strtrim', 'struct_assign', 'struct_hide',
                'strupcase', 'surface', 'surface', 'surfr', 'svdc',
                'svdfit', 'svsol', 'swap_endian', 'swap_endian_inplace', 'symbol',
                'systime', 't_cvf', 't_pdf', 't3d', 'tag_names',
                'tan', 'tanh', 'tek_color', 'temporary', 'terminal_size',
                'tetra_clip', 'tetra_surface', 'tetra_volume', 'text', 'thin',
                'thread', 'threed', 'tic', 'time_test2', 'timegen',
                'timer', 'timestamp', 'timestamptovalues', 'tm_test', 'toc',
                'total', 'trace', 'transpose', 'tri_surf', 'triangulate',
                'trigrid', 'triql', 'trired', 'trisol', 'truncate_lun',
                'ts_coef', 'ts_diff', 'ts_fcast', 'ts_smooth', 'tv',
                'tvcrs', 'tvlct', 'tvrd', 'tvscl', 'typename',
                'uindgen', 'uint', 'uintarr', 'ul64indgen', 'ulindgen',
                'ulon64arr', 'ulonarr', 'ulong', 'ulong64', 'uniq',
                'unsharp_mask', 'usersym', 'value_locate', 'variance', 'vector',
                'vector_field', 'vel', 'velovect', 'vert_t3d', 'voigt',
                'volume', 'voronoi', 'voxel_proj', 'wait', 'warp_tri',
                'watershed', 'wdelete', 'wf_draw', 'where', 'widget_base',
                'widget_button', 'widget_combobox', 'widget_control',
                'widget_displaycontextmenu', 'widget_draw',
                'widget_droplist', 'widget_event', 'widget_info',
                'widget_label', 'widget_list',
                'widget_propertysheet', 'widget_slider', 'widget_tab',
                'widget_table', 'widget_text',
                'widget_tree', 'widget_tree_move', 'widget_window',
                'wiener_filter', 'window',
                'window', 'write_bmp', 'write_csv', 'write_gif', 'write_image',
                'write_jpeg', 'write_jpeg2000', 'write_nrif', 'write_pict', 'write_png',
                'write_ppm', 'write_spr', 'write_srf', 'write_sylk', 'write_tiff',
                'write_video', 'write_wav', 'write_wave', 'writeu', 'wset',
                'wshow', 'wtn', 'wv_applet', 'wv_cwt', 'wv_cw_wavelet',
                'wv_denoise', 'wv_dwt', 'wv_fn_coiflet',
                'wv_fn_daubechies', 'wv_fn_gaussian',
                'wv_fn_haar', 'wv_fn_morlet', 'wv_fn_paul',
                'wv_fn_symlet', 'wv_import_data',
                'wv_import_wavelet', 'wv_plot3d_wps', 'wv_plot_multires',
                'wv_pwt', 'wv_tool_denoise',
                'xbm_edit', 'xdisplayfile', 'xdxf', 'xfont', 'xinteranimate',
                'xloadct', 'xmanager', 'xmng_tmpl', 'xmtool', 'xobjview',
                'xobjview_rotate', 'xobjview_write_image',
                'xpalette', 'xpcolor', 'xplot3d',
                'xregistered', 'xroi', 'xsq_test', 'xsurface', 'xvaredit',
                'xvolume', 'xvolume_rotate', 'xvolume_write_image',
                'xyouts', 'zlib_compress', 'zlib_uncompress', 'zoom', 'zoom_24'
              ];
              var builtins = wordRegexp(builtinArray);
            
              var keywordArray = [
                'begin', 'end', 'endcase', 'endfor',
                'endwhile', 'endif', 'endrep', 'endforeach',
                'break', 'case', 'continue', 'for',
                'foreach', 'goto', 'if', 'then', 'else',
                'repeat', 'until', 'switch', 'while',
                'do', 'pro', 'function'
              ];
              var keywords = wordRegexp(keywordArray);
            
              CodeMirror.registerHelper("hintWords", "idl", builtinArray.concat(keywordArray));
            
              var identifiers = new RegExp('^[_a-z\xa1-\uffff][_a-z0-9\xa1-\uffff]*', 'i');
            
              var singleOperators = /[+\-*&=<>\/@#~$]/;
              var boolOperators = new RegExp('(and|or|eq|lt|le|gt|ge|ne|not)', 'i');
            
              function tokenBase(stream) {
                // whitespaces
                if (stream.eatSpace()) return null;
            
                // Handle one line Comments
                if (stream.match(';')) {
                  stream.skipToEnd();
                  return 'comment';
                }
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.+-]/, false)) {
                  if (stream.match(/^[+-]?0x[0-9a-fA-F]+/))
                    return 'number';
                  if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/))
                    return 'number';
                  if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?/))
                    return 'number';
                }
            
                // Handle Strings
                if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; }
                if (stream.match(/^'([^']|(''))*'/)) { return 'string'; }
            
                // Handle words
                if (stream.match(keywords)) { return 'keyword'; }
                if (stream.match(builtins)) { return 'builtin'; }
                if (stream.match(identifiers)) { return 'variable'; }
            
                if (stream.match(singleOperators) || stream.match(boolOperators)) {
                  return 'operator'; }
            
                // Handle non-detected items
                stream.next();
                return null;
              };
            
              CodeMirror.defineMode('idl', function() {
                return {
                  token: function(stream) {
                    return tokenBase(stream);
                  }
                };
              });
            
              CodeMirror.defineMIME('text/x-idl', 'idl');
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: IDL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="idl.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">IDL</a>
              </ul>
            </div>
            
            <article>
            <h2>IDL mode</h2>
            
                <div><textarea id="code" name="code">
            ;; Example IDL code
            FUNCTION mean_and_stddev,array
              ;; This program reads in an array of numbers
              ;; and returns a structure containing the
              ;; average and standard deviation
            
              ave = 0.0
              count = 0.0
            
              for i=0,N_ELEMENTS(array)-1 do begin
                  ave = ave + array[i]
                  count = count + 1
              endfor
              
              ave = ave/count
            
              std = stddev(array)  
            
              return, {average:ave,std:std}
            
            END
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "idl",
                           version: 1,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-idl</code>.</p>
            </article>
            
        • jade
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Jade Templating Mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="jade.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Jade Templating Mode</a>
              </ul>
            </div>
            
            <article>
            <h2>Jade Templating Mode</h2>
            <form><textarea id="code" name="code">
            doctype html
              html
                head
                  title= "Jade Templating CodeMirror Mode Example"
                  link(rel='stylesheet', href='/css/bootstrap.min.css')
                  link(rel='stylesheet', href='/css/index.css')
                  script(type='text/javascript', src='/js/jquery-1.9.1.min.js')
                  script(type='text/javascript', src='/js/bootstrap.min.js')
                body
                  div.header
                    h1 Welcome to this Example
                  div.spots
                    if locals.spots
                      each spot in spots
                        div.spot.well
                     div
                       if spot.logo
                         img.img-rounded.logo(src=spot.logo)
                       else
                         img.img-rounded.logo(src="img/placeholder.png")
                     h3
                       a(href=spot.hash) ##{spot.hash}
                       if spot.title
                         span.title #{spot.title}
                       if spot.desc
                         div #{spot.desc}
                    else
                      h3 There are no spots currently available.
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "jade", alignCDATA: true},
                    lineNumbers: true
                  });
                </script>
                <h3>The Jade Templating Mode</h3>
                  <p> Created by Forbes Lindesay. Managed as part of a Brackets extension at <a href="https://github.com/ForbesLindesay/jade-brackets">https://github.com/ForbesLindesay/jade-brackets</a>.</p>
                <p><strong>MIME type defined:</strong> <code>text/x-jade</code>.</p>
              </article>
            
          • jade.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('jade', function (config) {
              // token types
              var KEYWORD = 'keyword';
              var DOCTYPE = 'meta';
              var ID = 'builtin';
              var CLASS = 'qualifier';
            
              var ATTRS_NEST = {
                '{': '}',
                '(': ')',
                '[': ']'
              };
            
              var jsMode = CodeMirror.getMode(config, 'javascript');
            
              function State() {
                this.javaScriptLine = false;
                this.javaScriptLineExcludesColon = false;
            
                this.javaScriptArguments = false;
                this.javaScriptArgumentsDepth = 0;
            
                this.isInterpolating = false;
                this.interpolationNesting = 0;
            
                this.jsState = jsMode.startState();
            
                this.restOfLine = '';
            
                this.isIncludeFiltered = false;
                this.isEach = false;
            
                this.lastTag = '';
                this.scriptType = '';
            
                // Attributes Mode
                this.isAttrs = false;
                this.attrsNest = [];
                this.inAttributeName = true;
                this.attributeIsType = false;
                this.attrValue = '';
            
                // Indented Mode
                this.indentOf = Infinity;
                this.indentToken = '';
            
                this.innerMode = null;
                this.innerState = null;
            
                this.innerModeForLine = false;
              }
              /**
               * Safely copy a state
               *
               * @return {State}
               */
              State.prototype.copy = function () {
                var res = new State();
                res.javaScriptLine = this.javaScriptLine;
                res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;
                res.javaScriptArguments = this.javaScriptArguments;
                res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;
                res.isInterpolating = this.isInterpolating;
                res.interpolationNesting = this.intpolationNesting;
            
                res.jsState = CodeMirror.copyState(jsMode, this.jsState);
            
                res.innerMode = this.innerMode;
                if (this.innerMode && this.innerState) {
                  res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);
                }
            
                res.restOfLine = this.restOfLine;
            
                res.isIncludeFiltered = this.isIncludeFiltered;
                res.isEach = this.isEach;
                res.lastTag = this.lastTag;
                res.scriptType = this.scriptType;
                res.isAttrs = this.isAttrs;
                res.attrsNest = this.attrsNest.slice();
                res.inAttributeName = this.inAttributeName;
                res.attributeIsType = this.attributeIsType;
                res.attrValue = this.attrValue;
                res.indentOf = this.indentOf;
                res.indentToken = this.indentToken;
            
                res.innerModeForLine = this.innerModeForLine;
            
                return res;
              };
            
              function javaScript(stream, state) {
                if (stream.sol()) {
                  // if javaScriptLine was set at end of line, ignore it
                  state.javaScriptLine = false;
                  state.javaScriptLineExcludesColon = false;
                }
                if (state.javaScriptLine) {
                  if (state.javaScriptLineExcludesColon && stream.peek() === ':') {
                    state.javaScriptLine = false;
                    state.javaScriptLineExcludesColon = false;
                    return;
                  }
                  var tok = jsMode.token(stream, state.jsState);
                  if (stream.eol()) state.javaScriptLine = false;
                  return tok || true;
                }
              }
              function javaScriptArguments(stream, state) {
                if (state.javaScriptArguments) {
                  if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') {
                    state.javaScriptArguments = false;
                    return;
                  }
                  if (stream.peek() === '(') {
                    state.javaScriptArgumentsDepth++;
                  } else if (stream.peek() === ')') {
                    state.javaScriptArgumentsDepth--;
                  }
                  if (state.javaScriptArgumentsDepth === 0) {
                    state.javaScriptArguments = false;
                    return;
                  }
            
                  var tok = jsMode.token(stream, state.jsState);
                  return tok || true;
                }
              }
            
              function yieldStatement(stream) {
                if (stream.match(/^yield\b/)) {
                    return 'keyword';
                }
              }
            
              function doctype(stream) {
                if (stream.match(/^(?:doctype) *([^\n]+)?/)) {
                    return DOCTYPE;
                }
              }
            
              function interpolation(stream, state) {
                if (stream.match('#{')) {
                  state.isInterpolating = true;
                  state.interpolationNesting = 0;
                  return 'punctuation';
                }
              }
            
              function interpolationContinued(stream, state) {
                if (state.isInterpolating) {
                  if (stream.peek() === '}') {
                    state.interpolationNesting--;
                    if (state.interpolationNesting < 0) {
                      stream.next();
                      state.isInterpolating = false;
                      return 'puncutation';
                    }
                  } else if (stream.peek() === '{') {
                    state.interpolationNesting++;
                  }
                  return jsMode.token(stream, state.jsState) || true;
                }
              }
            
              function caseStatement(stream, state) {
                if (stream.match(/^case\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function when(stream, state) {
                if (stream.match(/^when\b/)) {
                  state.javaScriptLine = true;
                  state.javaScriptLineExcludesColon = true;
                  return KEYWORD;
                }
              }
            
              function defaultStatement(stream) {
                if (stream.match(/^default\b/)) {
                  return KEYWORD;
                }
              }
            
              function extendsStatement(stream, state) {
                if (stream.match(/^extends?\b/)) {
                  state.restOfLine = 'string';
                  return KEYWORD;
                }
              }
            
              function append(stream, state) {
                if (stream.match(/^append\b/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
              function prepend(stream, state) {
                if (stream.match(/^prepend\b/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
              function block(stream, state) {
                if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
            
              function include(stream, state) {
                if (stream.match(/^include\b/)) {
                  state.restOfLine = 'string';
                  return KEYWORD;
                }
              }
            
              function includeFiltered(stream, state) {
                if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) {
                  state.isIncludeFiltered = true;
                  return KEYWORD;
                }
              }
            
              function includeFilteredContinued(stream, state) {
                if (state.isIncludeFiltered) {
                  var tok = filter(stream, state);
                  state.isIncludeFiltered = false;
                  state.restOfLine = 'string';
                  return tok;
                }
              }
            
              function mixin(stream, state) {
                if (stream.match(/^mixin\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function call(stream, state) {
                if (stream.match(/^\+([-\w]+)/)) {
                  if (!stream.match(/^\( *[-\w]+ *=/, false)) {
                    state.javaScriptArguments = true;
                    state.javaScriptArgumentsDepth = 0;
                  }
                  return 'variable';
                }
                if (stream.match(/^\+#{/, false)) {
                  stream.next();
                  state.mixinCallAfter = true;
                  return interpolation(stream, state);
                }
              }
              function callArguments(stream, state) {
                if (state.mixinCallAfter) {
                  state.mixinCallAfter = false;
                  if (!stream.match(/^\( *[-\w]+ *=/, false)) {
                    state.javaScriptArguments = true;
                    state.javaScriptArgumentsDepth = 0;
                  }
                  return true;
                }
              }
            
              function conditional(stream, state) {
                if (stream.match(/^(if|unless|else if|else)\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function each(stream, state) {
                if (stream.match(/^(- *)?(each|for)\b/)) {
                  state.isEach = true;
                  return KEYWORD;
                }
              }
              function eachContinued(stream, state) {
                if (state.isEach) {
                  if (stream.match(/^ in\b/)) {
                    state.javaScriptLine = true;
                    state.isEach = false;
                    return KEYWORD;
                  } else if (stream.sol() || stream.eol()) {
                    state.isEach = false;
                  } else if (stream.next()) {
                    while (!stream.match(/^ in\b/, false) && stream.next());
                    return 'variable';
                  }
                }
              }
            
              function whileStatement(stream, state) {
                if (stream.match(/^while\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function tag(stream, state) {
                var captures;
                if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) {
                  state.lastTag = captures[1].toLowerCase();
                  if (state.lastTag === 'script') {
                    state.scriptType = 'application/javascript';
                  }
                  return 'tag';
                }
              }
            
              function filter(stream, state) {
                if (stream.match(/^:([\w\-]+)/)) {
                  var innerMode;
                  if (config && config.innerModes) {
                    innerMode = config.innerModes(stream.current().substring(1));
                  }
                  if (!innerMode) {
                    innerMode = stream.current().substring(1);
                  }
                  if (typeof innerMode === 'string') {
                    innerMode = CodeMirror.getMode(config, innerMode);
                  }
                  setInnerMode(stream, state, innerMode);
                  return 'atom';
                }
              }
            
              function code(stream, state) {
                if (stream.match(/^(!?=|-)/)) {
                  state.javaScriptLine = true;
                  return 'punctuation';
                }
              }
            
              function id(stream) {
                if (stream.match(/^#([\w-]+)/)) {
                  return ID;
                }
              }
            
              function className(stream) {
                if (stream.match(/^\.([\w-]+)/)) {
                  return CLASS;
                }
              }
            
              function attrs(stream, state) {
                if (stream.peek() == '(') {
                  stream.next();
                  state.isAttrs = true;
                  state.attrsNest = [];
                  state.inAttributeName = true;
                  state.attrValue = '';
                  state.attributeIsType = false;
                  return 'punctuation';
                }
              }
            
              function attrsContinued(stream, state) {
                if (state.isAttrs) {
                  if (ATTRS_NEST[stream.peek()]) {
                    state.attrsNest.push(ATTRS_NEST[stream.peek()]);
                  }
                  if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {
                    state.attrsNest.pop();
                  } else  if (stream.eat(')')) {
                    state.isAttrs = false;
                    return 'punctuation';
                  }
                  if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) {
                    if (stream.peek() === '=' || stream.peek() === '!') {
                      state.inAttributeName = false;
                      state.jsState = jsMode.startState();
                      if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {
                        state.attributeIsType = true;
                      } else {
                        state.attributeIsType = false;
                      }
                    }
                    return 'attribute';
                  }
            
                  var tok = jsMode.token(stream, state.jsState);
                  if (state.attributeIsType && tok === 'string') {
                    state.scriptType = stream.current().toString();
                  }
                  if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) {
                    try {
                      Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, ''));
                      state.inAttributeName = true;
                      state.attrValue = '';
                      stream.backUp(stream.current().length);
                      return attrsContinued(stream, state);
                    } catch (ex) {
                      //not the end of an attribute
                    }
                  }
                  state.attrValue += stream.current();
                  return tok || true;
                }
              }
            
              function attributesBlock(stream, state) {
                if (stream.match(/^&attributes\b/)) {
                  state.javaScriptArguments = true;
                  state.javaScriptArgumentsDepth = 0;
                  return 'keyword';
                }
              }
            
              function indent(stream) {
                if (stream.sol() && stream.eatSpace()) {
                  return 'indent';
                }
              }
            
              function comment(stream, state) {
                if (stream.match(/^ *\/\/(-)?([^\n]*)/)) {
                  state.indentOf = stream.indentation();
                  state.indentToken = 'comment';
                  return 'comment';
                }
              }
            
              function colon(stream) {
                if (stream.match(/^: */)) {
                  return 'colon';
                }
              }
            
              function text(stream, state) {
                if (stream.match(/^(?:\| ?| )([^\n]+)/)) {
                  return 'string';
                }
                if (stream.match(/^(<[^\n]*)/, false)) {
                  // html string
                  setInnerMode(stream, state, 'htmlmixed');
                  state.innerModeForLine = true;
                  return innerMode(stream, state, true);
                }
              }
            
              function dot(stream, state) {
                if (stream.eat('.')) {
                  var innerMode = null;
                  if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) {
                    innerMode = state.scriptType.toLowerCase().replace(/"|'/g, '');
                  } else if (state.lastTag === 'style') {
                    innerMode = 'css';
                  }
                  setInnerMode(stream, state, innerMode);
                  return 'dot';
                }
              }
            
              function fail(stream) {
                stream.next();
                return null;
              }
            
            
              function setInnerMode(stream, state, mode) {
                mode = CodeMirror.mimeModes[mode] || mode;
                mode = config.innerModes ? config.innerModes(mode) || mode : mode;
                mode = CodeMirror.mimeModes[mode] || mode;
                mode = CodeMirror.getMode(config, mode);
                state.indentOf = stream.indentation();
            
                if (mode && mode.name !== 'null') {
                  state.innerMode = mode;
                } else {
                  state.indentToken = 'string';
                }
              }
              function innerMode(stream, state, force) {
                if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {
                  if (state.innerMode) {
                    if (!state.innerState) {
                      state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {};
                    }
                    return stream.hideFirstChars(state.indentOf + 2, function () {
                      return state.innerMode.token(stream, state.innerState) || true;
                    });
                  } else {
                    stream.skipToEnd();
                    return state.indentToken;
                  }
                } else if (stream.sol()) {
                  state.indentOf = Infinity;
                  state.indentToken = null;
                  state.innerMode = null;
                  state.innerState = null;
                }
              }
              function restOfLine(stream, state) {
                if (stream.sol()) {
                  // if restOfLine was set at end of line, ignore it
                  state.restOfLine = '';
                }
                if (state.restOfLine) {
                  stream.skipToEnd();
                  var tok = state.restOfLine;
                  state.restOfLine = '';
                  return tok;
                }
              }
            
            
              function startState() {
                return new State();
              }
              function copyState(state) {
                return state.copy();
              }
              /**
               * Get the next token in the stream
               *
               * @param {Stream} stream
               * @param {State} state
               */
              function nextToken(stream, state) {
                var tok = innerMode(stream, state)
                  || restOfLine(stream, state)
                  || interpolationContinued(stream, state)
                  || includeFilteredContinued(stream, state)
                  || eachContinued(stream, state)
                  || attrsContinued(stream, state)
                  || javaScript(stream, state)
                  || javaScriptArguments(stream, state)
                  || callArguments(stream, state)
            
                  || yieldStatement(stream, state)
                  || doctype(stream, state)
                  || interpolation(stream, state)
                  || caseStatement(stream, state)
                  || when(stream, state)
                  || defaultStatement(stream, state)
                  || extendsStatement(stream, state)
                  || append(stream, state)
                  || prepend(stream, state)
                  || block(stream, state)
                  || include(stream, state)
                  || includeFiltered(stream, state)
                  || mixin(stream, state)
                  || call(stream, state)
                  || conditional(stream, state)
                  || each(stream, state)
                  || whileStatement(stream, state)
                  || tag(stream, state)
                  || filter(stream, state)
                  || code(stream, state)
                  || id(stream, state)
                  || className(stream, state)
                  || attrs(stream, state)
                  || attributesBlock(stream, state)
                  || indent(stream, state)
                  || text(stream, state)
                  || comment(stream, state)
                  || colon(stream, state)
                  || dot(stream, state)
                  || fail(stream, state);
            
                return tok === true ? null : tok;
              }
              return {
                startState: startState,
                copyState: copyState,
                token: nextToken
              };
            });
            
            CodeMirror.defineMIME('text/x-jade', 'jade');
            
            });
            
        • javascript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: JavaScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">JavaScript</a>
              </ul>
            </div>
            
            <article>
            <h2>JavaScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            // Demo code (the actual new parser character stream implementation)
            
            function StringStream(string) {
              this.pos = 0;
              this.string = string;
            }
            
            StringStream.prototype = {
              done: function() {return this.pos >= this.string.length;},
              peek: function() {return this.string.charAt(this.pos);},
              next: function() {
                if (this.pos &lt; this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch &amp;&amp; match.test ? match.test(ch) : match(ch);
                if (ok) {this.pos++; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match));
                if (this.pos > start) return this.string.slice(start, this.pos);
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.pos;},
              eatSpace: function() {
                var start = this.pos;
                while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
                return this.pos - start;
              },
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
                  if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
                    if (consume !== false) this.pos += str.length;
                    return true;
                  }
                }
                else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match &amp;&amp; consume !== false) this.pos += match[0].length;
                  return match;
                }
              }
            };
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    continueComments: "Enter",
                    extraKeys: {"Ctrl-Q": "toggleComment"}
                  });
                </script>
            
                <p>
                  JavaScript mode supports several configuration options:
                  <ul>
                    <li><code>json</code> which will set the mode to expect JSON
                    data rather than a JavaScript program.</li>
                    <li><code>jsonld</code> which will set the mode to expect
                    <a href="http://json-ld.org">JSON-LD</a> linked data rather
                    than a JavaScript program (<a href="json-ld.html">demo</a>).</li>
                    <li><code>typescript</code> which will activate additional
                    syntax highlighting and some other things for TypeScript code
                    (<a href="typescript.html">demo</a>).</li>
                    <li><code>statementIndent</code> which (given a number) will
                    determine the amount of indentation to use for statements
                    continued on a new line.</li>
                    <li><code>wordCharacters</code>, a regexp that indicates which
                    characters should be considered part of an identifier.
                    Defaults to <code>/[\w$]/</code>, which does not handle
                    non-ASCII identifiers. Can be set to something more elaborate
                    to improve Unicode support.</li>
                  </ul>
                </p>
            
                <p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>, <code>application/ld+json</code>, <code>text/typescript</code>, <code>application/typescript</code>.</p>
              </article>
            
          • javascript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // TODO actually recognize syntax of TypeScript constructs
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("javascript", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
              var statementIndent = parserConfig.statementIndent;
              var jsonldMode = parserConfig.jsonld;
              var jsonMode = parserConfig.json || jsonldMode;
              var isTS = parserConfig.typescript;
              var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
            
              // Tokenizer
            
              var keywords = function(){
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
                var operator = kw("operator"), atom = {type: "atom", style: "atom"};
            
                var jsKeywords = {
                  "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
                  "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
                  "var": kw("var"), "const": kw("var"), "let": kw("var"),
                  "function": kw("function"), "catch": kw("catch"),
                  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
                  "in": operator, "typeof": operator, "instanceof": operator,
                  "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
                  "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
                  "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
                };
            
                // Extend the 'normal' keywords with the TypeScript language extensions
                if (isTS) {
                  var type = {type: "variable", style: "variable-3"};
                  var tsKeywords = {
                    // object-like things
                    "interface": kw("interface"),
                    "extends": kw("extends"),
                    "constructor": kw("constructor"),
            
                    // scope modifiers
                    "public": kw("public"),
                    "private": kw("private"),
                    "protected": kw("protected"),
                    "static": kw("static"),
            
                    // types
                    "string": type, "number": type, "bool": type, "any": type
                  };
            
                  for (var attr in tsKeywords) {
                    jsKeywords[attr] = tsKeywords[attr];
                  }
                }
            
                return jsKeywords;
              }();
            
              var isOperatorChar = /[+\-*&%=<>!?|~^]/;
              var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
            
              function readRegexp(stream) {
                var escaped = false, next, inSet = false;
                while ((next = stream.next()) != null) {
                  if (!escaped) {
                    if (next == "/" && !inSet) return;
                    if (next == "[") inSet = true;
                    else if (inSet && next == "]") inSet = false;
                  }
                  escaped = !escaped && next == "\\";
                }
              }
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
              function ret(tp, style, cont) {
                type = tp; content = cont;
                return style;
              }
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
                  return ret("number", "number");
                } else if (ch == "." && stream.match("..")) {
                  return ret("spread", "meta");
                } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  return ret(ch);
                } else if (ch == "=" && stream.eat(">")) {
                  return ret("=>", "operator");
                } else if (ch == "0" && stream.eat(/x/i)) {
                  stream.eatWhile(/[\da-f]/i);
                  return ret("number", "number");
                } else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
                  return ret("number", "number");
                } else if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  } else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
                           state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
                    readRegexp(stream);
                    stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
                    return ret("regexp", "string-2");
                  } else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", "operator", stream.current());
                  }
                } else if (ch == "`") {
                  state.tokenize = tokenQuasi;
                  return tokenQuasi(stream, state);
                } else if (ch == "#") {
                  stream.skipToEnd();
                  return ret("error", "error");
                } else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return ret("operator", "operator", stream.current());
                } else if (wordRE.test(ch)) {
                  stream.eatWhile(wordRE);
                  var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
                  return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
                                 ret("variable", "variable", word);
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next;
                  if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
                    state.tokenize = tokenBase;
                    return ret("jsonld-keyword", "meta");
                  }
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) break;
                    escaped = !escaped && next == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return ret("string", "string");
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenQuasi(stream, state) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  escaped = !escaped && next == "\\";
                }
                return ret("quasi", "string-2", stream.current());
              }
            
              var brackets = "([{}])";
              // This is a crude lookahead trick to try and notice that we're
              // parsing the argument patterns for a fat-arrow function before we
              // actually hit the arrow token. It only works if the arrow is on
              // the same line as the arguments and there's no strange noise
              // (comments) in between. Fallback is to only notice when we hit the
              // arrow, and not declare the arguments as locals for the arrow
              // body.
              function findFatArrow(stream, state) {
                if (state.fatArrowAt) state.fatArrowAt = null;
                var arrow = stream.string.indexOf("=>", stream.start);
                if (arrow < 0) return;
            
                var depth = 0, sawSomething = false;
                for (var pos = arrow - 1; pos >= 0; --pos) {
                  var ch = stream.string.charAt(pos);
                  var bracket = brackets.indexOf(ch);
                  if (bracket >= 0 && bracket < 3) {
                    if (!depth) { ++pos; break; }
                    if (--depth == 0) break;
                  } else if (bracket >= 3 && bracket < 6) {
                    ++depth;
                  } else if (wordRE.test(ch)) {
                    sawSomething = true;
                  } else if (/["'\/]/.test(ch)) {
                    return;
                  } else if (sawSomething && !depth) {
                    ++pos;
                    break;
                  }
                }
                if (sawSomething && !depth) state.fatArrowAt = pos;
              }
            
              // Parser
            
              var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
            
              function JSLexical(indented, column, type, align, prev, info) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.prev = prev;
                this.info = info;
                if (align != null) this.align = align;
              }
            
              function inScope(state, varname) {
                for (var v = state.localVars; v; v = v.next)
                  if (v.name == varname) return true;
                for (var cx = state.context; cx; cx = cx.prev) {
                  for (var v = cx.vars; v; v = v.next)
                    if (v.name == varname) return true;
                }
              }
            
              function parseJS(state, style, type, content, stream) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
            
                if (!state.lexical.hasOwnProperty("align"))
                  state.lexical.align = true;
            
                while(true) {
                  var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
                  if (combinator(type, content)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    if (cx.marked) return cx.marked;
                    if (type == "variable" && inScope(state, content)) return "variable-2";
                    return style;
                  }
                }
              }
            
              // Combinator utils
            
              var cx = {state: null, column: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
              function register(varname) {
                function inList(list) {
                  for (var v = list; v; v = v.next)
                    if (v.name == varname) return true;
                  return false;
                }
                var state = cx.state;
                if (state.context) {
                  cx.marked = "def";
                  if (inList(state.localVars)) return;
                  state.localVars = {name: varname, next: state.localVars};
                } else {
                  if (inList(state.globalVars)) return;
                  if (parserConfig.globalVars)
                    state.globalVars = {name: varname, next: state.globalVars};
                }
              }
            
              // Combinators
            
              var defaultVars = {name: "this", next: {name: "arguments"}};
              function pushcontext() {
                cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
                cx.state.localVars = defaultVars;
              }
              function popcontext() {
                cx.state.localVars = cx.state.context.vars;
                cx.state.context = cx.state.context.prev;
              }
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state, indent = state.indented;
                  if (state.lexical.type == "stat") indent = state.lexical.indented;
                  else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
                    indent = outer.indented;
                  state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              poplex.lex = true;
            
              function expect(wanted) {
                function exp(type) {
                  if (type == wanted) return cont();
                  else if (wanted == ";") return pass();
                  else return cont(exp);
                };
                return exp;
              }
            
              function statement(type, value) {
                if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
                if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
                if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
                if (type == "{") return cont(pushlex("}"), block, poplex);
                if (type == ";") return cont();
                if (type == "if") {
                  if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
                    cx.state.cc.pop()();
                  return cont(pushlex("form"), expression, statement, poplex, maybeelse);
                }
                if (type == "function") return cont(functiondef);
                if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
                if (type == "variable") return cont(pushlex("stat"), maybelabel);
                if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
                                                  block, poplex, poplex);
                if (type == "case") return cont(expression, expect(":"));
                if (type == "default") return cont(expect(":"));
                if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
                                                 statement, poplex, popcontext);
                if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
                if (type == "class") return cont(pushlex("form"), className, poplex);
                if (type == "export") return cont(pushlex("form"), afterExport, poplex);
                if (type == "import") return cont(pushlex("form"), afterImport, poplex);
                return pass(pushlex("stat"), expression, expect(";"), poplex);
              }
              function expression(type) {
                return expressionInner(type, false);
              }
              function expressionNoComma(type) {
                return expressionInner(type, true);
              }
              function expressionInner(type, noComma) {
                if (cx.state.fatArrowAt == cx.stream.start) {
                  var body = noComma ? arrowBodyNoComma : arrowBody;
                  if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
                  else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
                }
            
                var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
                if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
                if (type == "function") return cont(functiondef, maybeop);
                if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
                if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
                if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
                if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
                if (type == "{") return contCommasep(objprop, "}", null, maybeop);
                if (type == "quasi") { return pass(quasi, maybeop); }
                return cont();
              }
              function maybeexpression(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expression);
              }
              function maybeexpressionNoComma(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expressionNoComma);
              }
            
              function maybeoperatorComma(type, value) {
                if (type == ",") return cont(expression);
                return maybeoperatorNoComma(type, value, false);
              }
              function maybeoperatorNoComma(type, value, noComma) {
                var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
                var expr = noComma == false ? expression : expressionNoComma;
                if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
                if (type == "operator") {
                  if (/\+\+|--/.test(value)) return cont(me);
                  if (value == "?") return cont(expression, expect(":"), expr);
                  return cont(expr);
                }
                if (type == "quasi") { return pass(quasi, me); }
                if (type == ";") return;
                if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
                if (type == ".") return cont(property, me);
                if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
              }
              function quasi(type, value) {
                if (type != "quasi") return pass();
                if (value.slice(value.length - 2) != "${") return cont(quasi);
                return cont(expression, continueQuasi);
              }
              function continueQuasi(type) {
                if (type == "}") {
                  cx.marked = "string-2";
                  cx.state.tokenize = tokenQuasi;
                  return cont(quasi);
                }
              }
              function arrowBody(type) {
                findFatArrow(cx.stream, cx.state);
                return pass(type == "{" ? statement : expression);
              }
              function arrowBodyNoComma(type) {
                findFatArrow(cx.stream, cx.state);
                return pass(type == "{" ? statement : expressionNoComma);
              }
              function maybelabel(type) {
                if (type == ":") return cont(poplex, statement);
                return pass(maybeoperatorComma, expect(";"), poplex);
              }
              function property(type) {
                if (type == "variable") {cx.marked = "property"; return cont();}
              }
              function objprop(type, value) {
                if (type == "variable" || cx.style == "keyword") {
                  cx.marked = "property";
                  if (value == "get" || value == "set") return cont(getterSetter);
                  return cont(afterprop);
                } else if (type == "number" || type == "string") {
                  cx.marked = jsonldMode ? "property" : (cx.style + " property");
                  return cont(afterprop);
                } else if (type == "jsonld-keyword") {
                  return cont(afterprop);
                } else if (type == "[") {
                  return cont(expression, expect("]"), afterprop);
                }
              }
              function getterSetter(type) {
                if (type != "variable") return pass(afterprop);
                cx.marked = "property";
                return cont(functiondef);
              }
              function afterprop(type) {
                if (type == ":") return cont(expressionNoComma);
                if (type == "(") return pass(functiondef);
              }
              function commasep(what, end) {
                function proceed(type) {
                  if (type == ",") {
                    var lex = cx.state.lexical;
                    if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
                    return cont(what, proceed);
                  }
                  if (type == end) return cont();
                  return cont(expect(end));
                }
                return function(type) {
                  if (type == end) return cont();
                  return pass(what, proceed);
                };
              }
              function contCommasep(what, end, info) {
                for (var i = 3; i < arguments.length; i++)
                  cx.cc.push(arguments[i]);
                return cont(pushlex(end, info), commasep(what, end), poplex);
              }
              function block(type) {
                if (type == "}") return cont();
                return pass(statement, block);
              }
              function maybetype(type) {
                if (isTS && type == ":") return cont(typedef);
              }
              function typedef(type) {
                if (type == "variable"){cx.marked = "variable-3"; return cont();}
              }
              function vardef() {
                return pass(pattern, maybetype, maybeAssign, vardefCont);
              }
              function pattern(type, value) {
                if (type == "variable") { register(value); return cont(); }
                if (type == "[") return contCommasep(pattern, "]");
                if (type == "{") return contCommasep(proppattern, "}");
              }
              function proppattern(type, value) {
                if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
                  register(value);
                  return cont(maybeAssign);
                }
                if (type == "variable") cx.marked = "property";
                return cont(expect(":"), pattern, maybeAssign);
              }
              function maybeAssign(_type, value) {
                if (value == "=") return cont(expressionNoComma);
              }
              function vardefCont(type) {
                if (type == ",") return cont(vardef);
              }
              function maybeelse(type, value) {
                if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
              }
              function forspec(type) {
                if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
              }
              function forspec1(type) {
                if (type == "var") return cont(vardef, expect(";"), forspec2);
                if (type == ";") return cont(forspec2);
                if (type == "variable") return cont(formaybeinof);
                return pass(expression, expect(";"), forspec2);
              }
              function formaybeinof(_type, value) {
                if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
                return cont(maybeoperatorComma, forspec2);
              }
              function forspec2(type, value) {
                if (type == ";") return cont(forspec3);
                if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
                return pass(expression, expect(";"), forspec3);
              }
              function forspec3(type) {
                if (type != ")") cont(expression);
              }
              function functiondef(type, value) {
                if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
                if (type == "variable") {register(value); return cont(functiondef);}
                if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
              }
              function funarg(type) {
                if (type == "spread") return cont(funarg);
                return pass(pattern, maybetype);
              }
              function className(type, value) {
                if (type == "variable") {register(value); return cont(classNameAfter);}
              }
              function classNameAfter(type, value) {
                if (value == "extends") return cont(expression, classNameAfter);
                if (type == "{") return cont(pushlex("}"), classBody, poplex);
              }
              function classBody(type, value) {
                if (type == "variable" || cx.style == "keyword") {
                  cx.marked = "property";
                  if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
                  return cont(functiondef, classBody);
                }
                if (value == "*") {
                  cx.marked = "keyword";
                  return cont(classBody);
                }
                if (type == ";") return cont(classBody);
                if (type == "}") return cont();
              }
              function classGetterSetter(type) {
                if (type != "variable") return pass();
                cx.marked = "property";
                return cont();
              }
              function afterModule(type, value) {
                if (type == "string") return cont(statement);
                if (type == "variable") { register(value); return cont(maybeFrom); }
              }
              function afterExport(_type, value) {
                if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
                if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
                return pass(statement);
              }
              function afterImport(type) {
                if (type == "string") return cont();
                return pass(importSpec, maybeFrom);
              }
              function importSpec(type, value) {
                if (type == "{") return contCommasep(importSpec, "}");
                if (type == "variable") register(value);
                return cont();
              }
              function maybeFrom(_type, value) {
                if (value == "from") { cx.marked = "keyword"; return cont(expression); }
              }
              function arrayLiteral(type) {
                if (type == "]") return cont();
                return pass(expressionNoComma, maybeArrayComprehension);
              }
              function maybeArrayComprehension(type) {
                if (type == "for") return pass(comprehension, expect("]"));
                if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
                return pass(commasep(expressionNoComma, "]"));
              }
              function comprehension(type) {
                if (type == "for") return cont(forspec, comprehension);
                if (type == "if") return cont(expression, comprehension);
              }
            
              function isContinuedStatement(state, textAfter) {
                return state.lastType == "operator" || state.lastType == "," ||
                  isOperatorChar.test(textAfter.charAt(0)) ||
                  /[,.]/.test(textAfter.charAt(0));
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  var state = {
                    tokenize: tokenBase,
                    lastType: "sof",
                    cc: [],
                    lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
                    localVars: parserConfig.localVars,
                    context: parserConfig.localVars && {vars: parserConfig.localVars},
                    indented: 0
                  };
                  if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
                    state.globalVars = parserConfig.globalVars;
                  return state;
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                    findFatArrow(stream, state);
                  }
                  if (state.tokenize != tokenComment && stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (type == "comment") return style;
                  state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
                  return parseJS(state, style, type, content, stream);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize == tokenComment) return CodeMirror.Pass;
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
                  // Kludge to prevent 'maybelse' from blocking lexical scope pops
                  if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
                    var c = state.cc[i];
                    if (c == poplex) lexical = lexical.prev;
                    else if (c != maybeelse) break;
                  }
                  if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
                  if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
                    lexical = lexical.prev;
                  var type = lexical.type, closing = firstChar == type;
            
                  if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
                  else if (type == "form" && firstChar == "{") return lexical.indented;
                  else if (type == "form") return lexical.indented + indentUnit;
                  else if (type == "stat")
                    return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
                  else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
                    return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
                  else if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  else return lexical.indented + (closing ? 0 : indentUnit);
                },
            
                electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
                blockCommentStart: jsonMode ? null : "/*",
                blockCommentEnd: jsonMode ? null : "*/",
                lineComment: jsonMode ? null : "//",
                fold: "brace",
            
                helperType: jsonMode ? "json" : "javascript",
                jsonldMode: jsonldMode,
                jsonMode: jsonMode
              };
            });
            
            CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
            
            CodeMirror.defineMIME("text/javascript", "javascript");
            CodeMirror.defineMIME("text/ecmascript", "javascript");
            CodeMirror.defineMIME("application/javascript", "javascript");
            CodeMirror.defineMIME("application/x-javascript", "javascript");
            CodeMirror.defineMIME("application/ecmascript", "javascript");
            CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
            CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
            CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
            CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
            CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
            
            });
            
          • json-ld.html
            <!doctype html>
            
            <title>CodeMirror: JSON-LD mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id="nav">
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"/></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">JSON-LD</a>
              </ul>
            </div>
            
            <article>
            <h2>JSON-LD mode</h2>
            
            
            <div><textarea id="code" name="code">
            {
              "@context": {
                "name": "http://schema.org/name",
                "description": "http://schema.org/description",
                "image": {
                  "@id": "http://schema.org/image",
                  "@type": "@id"
                },
                "geo": "http://schema.org/geo",
                "latitude": {
                  "@id": "http://schema.org/latitude",
                  "@type": "xsd:float"
                },
                "longitude": {
                  "@id": "http://schema.org/longitude",
                  "@type": "xsd:float"
                },
                "xsd": "http://www.w3.org/2001/XMLSchema#"
              },
              "name": "The Empire State Building",
              "description": "The Empire State Building is a 102-story landmark in New York City.",
              "image": "http://www.civil.usherbrooke.ca/cours/gci215a/empire-state-building.jpg",
              "geo": {
                "latitude": "40.75",
                "longitude": "73.98"
              }
            }
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    matchBrackets: true,
                    autoCloseBrackets: true,
                    mode: "application/ld+json",
                    lineWrapping: true
                  });
                </script>
                
                <p>This is a specialization of the <a href="index.html">JavaScript mode</a>.</p>
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("locals",
                 "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");
            
              MT("comma-and-binop",
                 "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");
            
              MT("destructuring",
                 "([keyword function]([def a], [[[def b], [def c] ]]) {",
                 "  [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",
                 "  [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
                 "})();");
            
              MT("class_body",
                 "[keyword class] [variable Foo] {",
                 "  [property constructor]() {}",
                 "  [property sayName]() {",
                 "    [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
                 "  }",
                 "}");
            
              MT("class",
                 "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
                 "  [property get] [property prop]() { [keyword return] [number 24]; }",
                 "  [property constructor]([def x], [def y]) {",
                 "    [keyword super]([string 'something']);",
                 "    [keyword this].[property x] [operator =] [variable-2 x];",
                 "  }",
                 "}");
            
              MT("module",
                 "[keyword module] [string 'foo'] {",
                 "  [keyword export] [keyword let] [def x] [operator =] [number 42];",
                 "  [keyword export] [keyword *] [keyword from] [string 'somewhere'];",
                 "}");
            
              MT("import",
                 "[keyword function] [variable foo]() {",
                 "  [keyword import] [def $] [keyword from] [string 'jquery'];",
                 "  [keyword module] [def crypto] [keyword from] [string 'crypto'];",
                 "  [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
                 "}");
            
              MT("const",
                 "[keyword function] [variable f]() {",
                 "  [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
                 "}");
            
              MT("for/of",
                 "[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}");
            
              MT("generator",
                 "[keyword function*] [variable repeat]([def n]) {",
                 "  [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
                 "    [keyword yield] [variable-2 i];",
                 "}");
            
              MT("quotedStringAddition",
                 "[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
            
              MT("quotedFatArrow",
                 "[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
            
              MT("fatArrow",
                 "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
                 "[variable a];", // No longer in scope
                 "[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
                 "[variable c];");
            
              MT("spread",
                 "[keyword function] [variable f]([def a], [meta ...][def b]) {",
                 "  [variable something]([variable-2 a], [meta ...][variable-2 b]);",
                 "}");
            
              MT("comprehension",
                 "[keyword function] [variable f]() {",
                 "  [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
                 "  ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));",
                 "}");
            
              MT("quasi",
                 "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
            
              MT("quasi_no_function",
                 "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
            
              MT("indent_statement",
                 "[keyword var] [variable x] [operator =] [number 10]",
                 "[variable x] [operator +=] [variable y] [operator +]",
                 "  [atom Infinity]",
                 "[keyword debugger];");
            
              MT("indent_if",
                 "[keyword if] ([number 1])",
                 "  [keyword break];",
                 "[keyword else] [keyword if] ([number 2])",
                 "  [keyword continue];",
                 "[keyword else]",
                 "  [number 10];",
                 "[keyword if] ([number 1]) {",
                 "  [keyword break];",
                 "} [keyword else] [keyword if] ([number 2]) {",
                 "  [keyword continue];",
                 "} [keyword else] {",
                 "  [number 10];",
                 "}");
            
              MT("indent_for",
                 "[keyword for] ([keyword var] [variable i] [operator =] [number 0];",
                 "     [variable i] [operator <] [number 100];",
                 "     [variable i][operator ++])",
                 "  [variable doSomething]([variable i]);",
                 "[keyword debugger];");
            
              MT("indent_c_style",
                 "[keyword function] [variable foo]()",
                 "{",
                 "  [keyword debugger];",
                 "}");
            
              MT("indent_else",
                 "[keyword for] (;;)",
                 "  [keyword if] ([variable foo])",
                 "    [keyword if] ([variable bar])",
                 "      [number 1];",
                 "    [keyword else]",
                 "      [number 2];",
                 "  [keyword else]",
                 "    [number 3];");
            
              MT("indent_funarg",
                 "[variable foo]([number 10000],",
                 "    [keyword function]([def a]) {",
                 "  [keyword debugger];",
                 "};");
            
              MT("indent_below_if",
                 "[keyword for] (;;)",
                 "  [keyword if] ([variable foo])",
                 "    [number 1];",
                 "[number 2];");
            
              MT("multilinestring",
                 "[keyword var] [variable x] [operator =] [string 'foo\\]",
                 "[string bar'];");
            
              MT("scary_regexp",
                 "[string-2 /foo[[/]]bar/];");
            
              MT("indent_strange_array",
                 "[keyword var] [variable x] [operator =] [[",
                 "  [number 1],,",
                 "  [number 2],",
                 "]];",
                 "[number 10];");
            
              var jsonld_mode = CodeMirror.getMode(
                {indentUnit: 2},
                {name: "javascript", jsonld: true}
              );
              function LD(name) {
                test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1));
              }
            
              LD("json_ld_keywords",
                '{',
                '  [meta "@context"]: {',
                '    [meta "@base"]: [string "http://example.com"],',
                '    [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],',
                '    [property "likesFlavor"]: {',
                '      [meta "@container"]: [meta "@list"]',
                '      [meta "@reverse"]: [string "@beFavoriteOf"]',
                '    },',
                '    [property "nick"]: { [meta "@container"]: [meta "@set"] },',
                '    [property "nick"]: { [meta "@container"]: [meta "@index"] }',
                '  },',
                '  [meta "@graph"]: [[ {',
                '    [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],',
                '    [property "name"]: [string "John Lennon"],',
                '    [property "modified"]: {',
                '      [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],',
                '      [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]',
                '    }',
                '  } ]]',
                '}');
            
              LD("json_ld_fake",
                '{',
                '  [property "@fake"]: [string "@fake"],',
                '  [property "@contextual"]: [string "@identifier"],',
                '  [property "user@domain.com"]: [string "@graphical"],',
                '  [property "@ID"]: [string "@@ID"]',
                '}');
            })();
            
          • typescript.html
            <!doctype html>
            
            <title>CodeMirror: TypeScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TypeScript</a>
              </ul>
            </div>
            
            <article>
            <h2>TypeScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            class Greeter {
            	greeting: string;
            	constructor (message: string) {
            		this.greeting = message;
            	}
            	greet() {
            		return "Hello, " + this.greeting;
            	}
            }   
            
            var greeter = new Greeter("world");
            
            var button = document.createElement('button')
            button.innerText = "Say Hello"
            button.onclick = function() {
            	alert(greeter.greet())
            }
            
            document.body.appendChild(button)
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/typescript"
                  });
                </script>
            
                <p>This is a specialization of the <a href="index.html">JavaScript mode</a>.</p>
              </article>
            
        • jinja2
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Jinja2 mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="jinja2.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Jinja2</a>
              </ul>
            </div>
            
            <article>
            <h2>Jinja2 mode</h2>
            <form><textarea id="code" name="code">
            {# this is a comment #}
            {%- for item in li -%}
              &lt;li&gt;{{ item.label }}&lt;/li&gt;
            {% endfor -%}
            {{ item.sand == true and item.keyword == false ? 1 : 0 }}
            {{ app.get(55, 1.2, true) }}
            {% if app.get(&#39;_route&#39;) == (&#39;_home&#39;) %}home{% endif %}
            {% if app.session.flashbag.has(&#39;message&#39;) %}
              {% for message in app.session.flashbag.get(&#39;message&#39;) %}
                {{ message.content }}
              {% endfor %}
            {% endif %}
            {{ path(&#39;_home&#39;, {&#39;section&#39;: app.request.get(&#39;section&#39;)}) }}
            {{ path(&#39;_home&#39;, {
                &#39;section&#39;: app.request.get(&#39;section&#39;),
                &#39;boolean&#39;: true,
                &#39;number&#39;: 55.33
              })
            }}
            {% include (&#39;test.incl.html.twig&#39;) %}
            </textarea></form>
                <script>
                  var editor =
                  CodeMirror.fromTextArea(document.getElementById("code"), {mode:
                    {name: "jinja2", htmlMode: true}});
                </script>
              </article>
            
          • jinja2.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("jinja2", function() {
                var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",
                  "extends", "filter", "endfilter", "firstof", "for",
                  "endfor", "if", "endif", "ifchanged", "endifchanged",
                  "ifequal", "endifequal", "ifnotequal",
                  "endifnotequal", "in", "include", "load", "not", "now", "or",
                  "parsed", "regroup", "reversed", "spaceless",
                  "endspaceless", "ssi", "templatetag", "openblock",
                  "closeblock", "openvariable", "closevariable",
                  "openbrace", "closebrace", "opencomment",
                  "closecomment", "widthratio", "url", "with", "endwith",
                  "get_current_language", "trans", "endtrans", "noop", "blocktrans",
                  "endblocktrans", "get_available_languages",
                  "get_current_language_bidi", "plural"],
                operator = /^[+\-*&%=<>!?|~^]/,
                sign = /^[:\[\(\{]/,
                atom = ["true", "false"],
                number = /^(\d[+\-\*\/])?\d+(\.\d+)?/;
            
                keywords = new RegExp("((" + keywords.join(")|(") + "))\\b");
                atom = new RegExp("((" + atom.join(")|(") + "))\\b");
            
                function tokenBase (stream, state) {
                  var ch = stream.peek();
            
                  //Comment
                  if (state.incomment) {
                    if(!stream.skipTo("#}")) {
                      stream.skipToEnd();
                    } else {
                      stream.eatWhile(/\#|}/);
                      state.incomment = false;
                    }
                    return "comment";
                  //Tag
                  } else if (state.intag) {
                    //After operator
                    if(state.operator) {
                      state.operator = false;
                      if(stream.match(atom)) {
                        return "atom";
                      }
                      if(stream.match(number)) {
                        return "number";
                      }
                    }
                    //After sign
                    if(state.sign) {
                      state.sign = false;
                      if(stream.match(atom)) {
                        return "atom";
                      }
                      if(stream.match(number)) {
                        return "number";
                      }
                    }
            
                    if(state.instring) {
                      if(ch == state.instring) {
                        state.instring = false;
                      }
                      stream.next();
                      return "string";
                    } else if(ch == "'" || ch == '"') {
                      state.instring = ch;
                      stream.next();
                      return "string";
                    } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) {
                      state.intag = false;
                      return "tag";
                    } else if(stream.match(operator)) {
                      state.operator = true;
                      return "operator";
                    } else if(stream.match(sign)) {
                      state.sign = true;
                    } else {
                      if(stream.eat(" ") || stream.sol()) {
                        if(stream.match(keywords)) {
                          return "keyword";
                        }
                        if(stream.match(atom)) {
                          return "atom";
                        }
                        if(stream.match(number)) {
                          return "number";
                        }
                        if(stream.sol()) {
                          stream.next();
                        }
                      } else {
                        stream.next();
                      }
            
                    }
                    return "variable";
                  } else if (stream.eat("{")) {
                    if (ch = stream.eat("#")) {
                      state.incomment = true;
                      if(!stream.skipTo("#}")) {
                        stream.skipToEnd();
                      } else {
                        stream.eatWhile(/\#|}/);
                        state.incomment = false;
                      }
                      return "comment";
                    //Open tag
                    } else if (ch = stream.eat(/\{|%/)) {
                      //Cache close tag
                      state.intag = ch;
                      if(ch == "{") {
                        state.intag = "}";
                      }
                      stream.eat("-");
                      return "tag";
                    }
                  }
                  stream.next();
                };
            
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  }
                };
              });
            });
            
        • julia
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Julia mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="julia.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Julia</a>
              </ul>
            </div>
            
            <article>
            <h2>Julia mode</h2>
            
                <div><textarea id="code" name="code">
            #numbers
            1234
            1234im
            .234
            .234im
            2.23im
            2.3f3
            23e2
            0x234
            
            #strings
            'a'
            "asdf"
            r"regex"
            b"bytestring"
            
            """
            multiline string
            """
            
            #identifiers
            a
            as123
            function_name!
            
            #unicode identifiers
            # a = x\ddot
            a⃗ = ẍ
            # a = v\dot
            a⃗ = v̇
            #F\vec = m \cdotp a\vec
            F⃗ = m·a⃗
            
            #literal identifier multiples
            3x
            4[1, 2, 3]
            
            #dicts and indexing
            x=[1, 2, 3]
            x[end-1]
            x={"julia"=>"language of technical computing"}
            
            
            #exception handling
            try
              f()
            catch
              @printf "Error"
            finally
              g()
            end
            
            #types
            immutable Color{T<:Number}
              r::T
              g::T
              b::T
            end
            
            #functions
            function change!(x::Vector{Float64})
              for i = 1:length(x)
                x[i] *= 2
              end
            end
            
            #function invocation
            f('b', (2, 3)...)
            
            #operators
            |=
            &=
            ^=
            \-
            %=
            *=
            +=
            -=
            <=
            >=
            !=
            ==
            %
            *
            +
            -
            <
            >
            !
            =
            |
            &
            ^
            \
            ?
            ~
            :
            $
            <:
            .<
            .>
            <<
            <<=
            >>
            >>>>
            >>=
            >>>=
            <<=
            <<<=
            .<=
            .>=
            .==
            ->
            //
            in
            ...
            //
            :=
            .//=
            .*=
            ./=
            .^=
            .%=
            .+=
            .-=
            \=
            \\=
            ||
            ===
            &&
            |=
            .|=
            <:
            >:
            |>
            <|
            ::
            x ? y : z
            
            #macros
            @spawnat 2 1+1
            @eval(:x)
            
            #keywords and operators
            if else elseif while for
             begin let end do
            try catch finally return break continue
            global local const 
            export import importall using
            function macro module baremodule 
            type immutable quote
            true false enumerate
            
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "julia",
                           },
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-julia</code>.</p>
            </article>
            
          • julia.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("julia", function(_conf, parserConf) {
              var ERRORCLASS = 'error';
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b/;
              var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
              var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
              var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"];
              var blockClosers = ["end", "else", "elseif", "catch", "finally"];
              var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall'];
              var builtinList = ['true', 'false', 'enumerate', 'open', 'close', 'nothing', 'NaN', 'Inf', 'print', 'println', 'Int', 'Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Int64', 'Uint64', 'Int128', 'Uint128', 'Bool', 'Char', 'Float16', 'Float32', 'Float64', 'Array', 'Vector', 'Matrix', 'String', 'UTF8String', 'ASCIIString', 'error', 'warn', 'info', '@printf'];
            
              //var stringPrefixes = new RegExp("^[br]?('|\")")
              var stringPrefixes = /^(`|'|"{3}|([br]?"))/;
              var keywords = wordRegexp(keywordList);
              var builtins = wordRegexp(builtinList);
              var openers = wordRegexp(blockOpeners);
              var closers = wordRegexp(blockClosers);
              var macro = /^@[_A-Za-z][_A-Za-z0-9]*/;
              var symbol = /^:[_A-Za-z][_A-Za-z0-9]*/;
              var indentInfo = null;
            
              function in_array(state) {
                var ch = cur_scope(state);
                if(ch=="[" || ch=="{") {
                  return true;
                }
                else {
                  return false;
                }
              }
            
              function cur_scope(state) {
                if(state.scopes.length==0) {
                  return null;
                }
                return state.scopes[state.scopes.length - 1];
              }
            
              // tokenizers
              function tokenBase(stream, state) {
                // Handle scope changes
                var leaving_expr = state.leaving_expr;
                if(stream.sol()) {
                  leaving_expr = false;
                }
                state.leaving_expr = false;
                if(leaving_expr) {
                  if(stream.match(/^'+/)) {
                    return 'operator';
                  }
            
                }
            
                if(stream.match(/^\.{2,3}/)) {
                  return 'operator';
                }
            
                if (stream.eatSpace()) {
                  return null;
                }
            
                var ch = stream.peek();
                // Handle Comments
                if (ch === '#') {
                    stream.skipToEnd();
                    return 'comment';
                }
                if(ch==='[') {
                  state.scopes.push("[");
                }
            
                if(ch==='{') {
                  state.scopes.push("{");
                }
            
                var scope=cur_scope(state);
            
                if(scope==='[' && ch===']') {
                  state.scopes.pop();
                  state.leaving_expr=true;
                }
            
                if(scope==='{' && ch==='}') {
                  state.scopes.pop();
                  state.leaving_expr=true;
                }
            
                if(ch===')') {
                  state.leaving_expr = true;
                }
            
                var match;
                if(!in_array(state) && (match=stream.match(openers, false))) {
                  state.scopes.push(match);
                }
            
                if(!in_array(state) && stream.match(closers, false)) {
                  state.scopes.pop();
                }
            
                if(in_array(state)) {
                  if(stream.match(/^end/)) {
                    return 'number';
                  }
            
                }
            
                if(stream.match(/^=>/)) {
                  return 'operator';
                }
            
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.]/, false)) {
                  var imMatcher = RegExp(/^im\b/);
                  var floatLiteral = false;
                  // Floats
                  if (stream.match(/^\d*\.(?!\.)\d+([ef][\+\-]?\d+)?/i)) { floatLiteral = true; }
                  if (stream.match(/^\d+\.(?!\.)\d*/)) { floatLiteral = true; }
                  if (stream.match(/^\.\d+/)) { floatLiteral = true; }
                  if (floatLiteral) {
                      // Float literals may be "imaginary"
                      stream.match(imMatcher);
                      state.leaving_expr = true;
                      return 'number';
                  }
                  // Integers
                  var intLiteral = false;
                  // Hex
                  if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }
                  // Binary
                  if (stream.match(/^0b[01]+/i)) { intLiteral = true; }
                  // Octal
                  if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }
                  // Decimal
                  if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                      intLiteral = true;
                  }
                  // Zero by itself with no other piece of number.
                  if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                  if (intLiteral) {
                      // Integer literals may be "long"
                      stream.match(imMatcher);
                      state.leaving_expr = true;
                      return 'number';
                  }
                }
            
                if(stream.match(/^(::)|(<:)/)) {
                  return 'operator';
                }
            
                // Handle symbols
                if(!leaving_expr && stream.match(symbol)) {
                  return 'string';
                }
            
                // Handle operators and Delimiters
                if (stream.match(operators)) {
                  return 'operator';
                }
            
            
                // Handle Strings
                if (stream.match(stringPrefixes)) {
                  state.tokenize = tokenStringFactory(stream.current());
                  return state.tokenize(stream, state);
                }
            
                if (stream.match(macro)) {
                  return 'meta';
                }
            
            
                if (stream.match(delimiters)) {
                  return null;
                }
            
                if (stream.match(keywords)) {
                  return 'keyword';
                }
            
                if (stream.match(builtins)) {
                  return 'builtin';
                }
            
            
                if (stream.match(identifiers)) {
                  state.leaving_expr=true;
                  return 'variable';
                }
                // Handle non-detected items
                stream.next();
                return ERRORCLASS;
              }
            
              function tokenStringFactory(delimiter) {
                while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
                  delimiter = delimiter.substr(1);
                }
                var singleline = delimiter.length == 1;
                var OUTCLASS = 'string';
            
                function tokenString(stream, state) {
                  while (!stream.eol()) {
                    stream.eatWhile(/[^'"\\]/);
                    if (stream.eat('\\')) {
                        stream.next();
                        if (singleline && stream.eol()) {
                          return OUTCLASS;
                        }
                    } else if (stream.match(delimiter)) {
                        state.tokenize = tokenBase;
                        return OUTCLASS;
                    } else {
                        stream.eat(/['"]/);
                    }
                  }
                  if (singleline) {
                    if (parserConf.singleLineStringErrors) {
                        return ERRORCLASS;
                    } else {
                        state.tokenize = tokenBase;
                    }
                  }
                  return OUTCLASS;
                }
                tokenString.isString = true;
                return tokenString;
              }
            
              function tokenLexer(stream, state) {
                indentInfo = null;
                var style = state.tokenize(stream, state);
                var current = stream.current();
            
                // Handle '.' connected identifiers
                if (current === '.') {
                  style = stream.match(identifiers, false) ? null : ERRORCLASS;
                  if (style === null && state.lastStyle === 'meta') {
                      // Apply 'meta' style to '.' connected identifiers when
                      // appropriate.
                    style = 'meta';
                  }
                  return style;
                }
            
                return style;
              }
            
              var external = {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    scopes: [],
                    leaving_expr: false
                  };
                },
            
                token: function(stream, state) {
                  var style = tokenLexer(stream, state);
                  state.lastStyle = style;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var delta = 0;
                  if(textAfter=="end" || textAfter=="]" || textAfter=="}" || textAfter=="else" || textAfter=="elseif" || textAfter=="catch" || textAfter=="finally") {
                    delta = -1;
                  }
                  return (state.scopes.length + delta) * 4;
                },
            
                lineComment: "#",
                fold: "indent",
                electricChars: "edlsifyh]}"
              };
              return external;
            });
            
            
            CodeMirror.defineMIME("text/x-julia", "julia");
            
            });
            
        • kotlin
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Kotlin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="kotlin.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Kotlin</a>
              </ul>
            </div>
            
            <article>
            <h2>Kotlin mode</h2>
            
            
            <div><textarea id="code" name="code">
            package org.wasabi.http
            
            import java.util.concurrent.Executors
            import java.net.InetSocketAddress
            import org.wasabi.app.AppConfiguration
            import io.netty.bootstrap.ServerBootstrap
            import io.netty.channel.nio.NioEventLoopGroup
            import io.netty.channel.socket.nio.NioServerSocketChannel
            import org.wasabi.app.AppServer
            
            public class HttpServer(private val appServer: AppServer) {
            
                val bootstrap: ServerBootstrap
                val primaryGroup: NioEventLoopGroup
                val workerGroup:  NioEventLoopGroup
            
                {
                    // Define worker groups
                    primaryGroup = NioEventLoopGroup()
                    workerGroup = NioEventLoopGroup()
            
                    // Initialize bootstrap of server
                    bootstrap = ServerBootstrap()
            
                    bootstrap.group(primaryGroup, workerGroup)
                    bootstrap.channel(javaClass<NioServerSocketChannel>())
                    bootstrap.childHandler(NettyPipelineInitializer(appServer))
                }
            
                public fun start(wait: Boolean = true) {
                    val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()
            
                    if (wait) {
                        channel?.closeFuture()?.sync()
                    }
                }
            
                public fun stop() {
                    // Shutdown all event loops
                    primaryGroup.shutdownGracefully()
                    workerGroup.shutdownGracefully()
            
                    // Wait till all threads are terminated
                    primaryGroup.terminationFuture().sync()
                    workerGroup.terminationFuture().sync()
                }
            }
            </textarea></div>
            
                <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                        mode: {name: "kotlin"},
                        lineNumbers: true,
                        indentUnit: 4
                    });
                </script>
                <h3>Mode for Kotlin (http://kotlin.jetbrains.org/)</h3>
                <p>Developed by Hadi Hariri (https://github.com/hhariri).</p>
                <p><strong>MIME type defined:</strong> <code>text/x-kotlin</code>.</p>
            </article>
            
          • kotlin.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("kotlin", function (config, parserConfig) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var multiLineStrings = parserConfig.multiLineStrings;
            
              var keywords = words(
                      "package continue return object while break class data trait throw super" +
                      " when type this else This try val var fun for is in if do as true false null get set");
              var softKeywords = words("import" +
                  " where by get set abstract enum open annotation override private public internal" +
                  " protected catch out vararg inline finally final ref");
              var blockKeywords = words("catch class do else finally for if where try while enum");
              var atoms = words("null true false this");
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  return startString(ch, stream, state);
                }
                // Wildcard import w/o trailing semicolon (import smth.*)
                if (ch == "." && stream.eat("*")) {
                  return "word";
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  if (stream.eat(/eE/)) {
                    stream.eat(/\+\-/);
                    stream.eatWhile(/\d/);
                  }
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize.push(tokenComment);
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (expectExpression(state.lastToken)) {
                    return startString(ch, stream, state);
                  }
                }
                // Commented
                if (ch == "-" && stream.eat(">")) {
                  curPunc = "->";
                  return null;
                }
                if (/[\-+*&%=<>!?|\/~]/.test(ch)) {
                  stream.eatWhile(/[\-+*&%=<>|~]/);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
            
                var cur = stream.current();
                if (atoms.propertyIsEnumerable(cur)) {
                  return "atom";
                }
                if (softKeywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "softKeyword";
                }
            
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                return "word";
              }
            
              tokenBase.isBase = true;
            
              function startString(quote, stream, state) {
                var tripleQuoted = false;
                if (quote != "/" && stream.eat(quote)) {
                  if (stream.eat(quote)) tripleQuoted = true;
                  else return "string";
                }
                function t(stream, state) {
                  var escaped = false, next, end = !tripleQuoted;
            
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      if (!tripleQuoted) {
                        break;
                      }
                      if (stream.match(quote + quote)) {
                        end = true;
                        break;
                      }
                    }
            
                    if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
                      state.tokenize.push(tokenBaseUntilBrace());
                      return "string";
                    }
            
                    if (next == "$" && !escaped && !stream.eat(" ")) {
                      state.tokenize.push(tokenBaseUntilSpace());
                      return "string";
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (multiLineStrings)
                    state.tokenize.push(t);
                  if (end) state.tokenize.pop();
                  return "string";
                }
            
                state.tokenize.push(t);
                return t(stream, state);
              }
            
              function tokenBaseUntilBrace() {
                var depth = 1;
            
                function t(stream, state) {
                  if (stream.peek() == "}") {
                    depth--;
                    if (depth == 0) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length - 1](stream, state);
                    }
                  } else if (stream.peek() == "{") {
                    depth++;
                  }
                  return tokenBase(stream, state);
                }
            
                t.isBase = true;
                return t;
              }
            
              function tokenBaseUntilSpace() {
                function t(stream, state) {
                  if (stream.eat(/[\w]/)) {
                    var isWord = stream.eatWhile(/[\w]/);
                    if (isWord) {
                      state.tokenize.pop();
                      return "word";
                    }
                  }
                  state.tokenize.pop();
                  return "string";
                }
            
                t.isBase = true;
                return t;
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize.pop();
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function expectExpression(last) {
                return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
                    last == "newstatement" || last == "keyword" || last == "proplabel";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
            
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
            
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function (basecolumn) {
                  return {
                    tokenize: [tokenBase],
                    context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true,
                    lastToken: null
                  };
                },
            
                token: function (stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    // Automatic semicolon insertion
                    if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
                      popContext(state);
                      ctx = state.context;
                    }
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = state.tokenize[state.tokenize.length - 1](stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  // Handle indentation for {x -> \n ... }
                  else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
                    popContext(state);
                    state.context.align = false;
                  }
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  state.lastToken = curPunc || style;
                  return style;
                },
            
                indent: function (state, textAfter) {
                  if (!state.tokenize[state.tokenize.length - 1].isBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
                  if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") {
                    return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
                  }
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : config.indentUnit);
                },
            
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-kotlin", "kotlin");
            
            });
            
        • livescript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: LiveScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/solarized.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="livescript.js"></script>
            <style>.CodeMirror {font-size: 80%;border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">LiveScript</a>
              </ul>
            </div>
            
            <article>
            <h2>LiveScript mode</h2>
            <form><textarea id="code" name="code">
            # LiveScript mode for CodeMirror
            # The following script, prelude.ls, is used to
            # demonstrate LiveScript mode for CodeMirror.
            #   https://github.com/gkz/prelude-ls
            
            export objToFunc = objToFunc = (obj) ->
              (key) -> obj[key]
            
            export each = (f, xs) -->
              if typeof! xs is \Object
                for , x of xs then f x
              else
                for x in xs then f x
              xs
            
            export map = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, f x] for key, x of xs}
              else
                result = [f x for x in xs]
                if type is \String then result * '' else result
            
            export filter = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, x] for key, x of xs when f x}
              else
                result = [x for x in xs when f x]
                if type is \String then result * '' else result
            
            export reject = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, x] for key, x of xs when not f x}
              else
                result = [x for x in xs when not f x]
                if type is \String then result * '' else result
            
            export partition = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                passed = {}
                failed = {}
                for key, x of xs
                  (if f x then passed else failed)[key] = x
              else
                passed = []
                failed = []
                for x in xs
                  (if f x then passed else failed)push x
                if type is \String
                  passed *= ''
                  failed *= ''
              [passed, failed]
            
            export find = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              if typeof! xs is \Object
                for , x of xs when f x then return x
              else
                for x in xs when f x then return x
              void
            
            export head = export first = (xs) ->
              return void if not xs.length
              xs.0
            
            export tail = (xs) ->
              return void if not xs.length
              xs.slice 1
            
            export last = (xs) ->
              return void if not xs.length
              xs[*-1]
            
            export initial = (xs) ->
              return void if not xs.length
              xs.slice 0 xs.length - 1
            
            export empty = (xs) ->
              if typeof! xs is \Object
                for x of xs then return false
                return yes
              not xs.length
            
            export values = (obj) ->
              [x for , x of obj]
            
            export keys = (obj) ->
              [x for x of obj]
            
            export len = (xs) ->
              xs = values xs if typeof! xs is \Object
              xs.length
            
            export cons = (x, xs) -->
              if typeof! xs is \String then x + xs else [x] ++ xs
            
            export append = (xs, ys) -->
              if typeof! ys is \String then xs + ys else xs ++ ys
            
            export join = (sep, xs) -->
              xs = values xs if typeof! xs is \Object
              xs.join sep
            
            export reverse = (xs) ->
              if typeof! xs is \String
              then (xs / '')reverse! * ''
              else xs.slice!reverse!
            
            export fold = export foldl = (f, memo, xs) -->
              if typeof! xs is \Object
                for , x of xs then memo = f memo, x
              else
                for x in xs then memo = f memo, x
              memo
            
            export fold1 = export foldl1 = (f, xs) --> fold f, xs.0, xs.slice 1
            
            export foldr = (f, memo, xs) --> fold f, memo, xs.slice!reverse!
            
            export foldr1 = (f, xs) -->
              xs.=slice!reverse!
              fold f, xs.0, xs.slice 1
            
            export unfoldr = export unfold = (f, b) -->
              if (f b)?
                [that.0] ++ unfoldr f, that.1
              else
                []
            
            export andList = (xs) ->
              for x in xs when not x
                return false
              true
            
            export orList = (xs) ->
              for x in xs when x
                return true
              false
            
            export any = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              for x in xs when f x
                return yes
              no
            
            export all = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              for x in xs when not f x
                return no
              yes
            
            export unique = (xs) ->
              result = []
              if typeof! xs is \Object
                for , x of xs when x not in result then result.push x
              else
                for x   in xs when x not in result then result.push x
              if typeof! xs is \String then result * '' else result
            
            export sort = (xs) ->
              xs.concat!sort (x, y) ->
                | x > y =>  1
                | x < y => -1
                | _     =>  0
            
            export sortBy = (f, xs) -->
              return [] unless xs.length
              xs.concat!sort f
            
            export compare = (f, x, y) -->
              | (f x) > (f y) =>  1
              | (f x) < (f y) => -1
              | otherwise     =>  0
            
            export sum = (xs) ->
              result = 0
              if typeof! xs is \Object
                for , x of xs then result += x
              else
                for x   in xs then result += x
              result
            
            export product = (xs) ->
              result = 1
              if typeof! xs is \Object
                for , x of xs then result *= x
              else
                for x   in xs then result *= x
              result
            
            export mean = export average = (xs) -> (sum xs) / len xs
            
            export concat = (xss) -> fold append, [], xss
            
            export concatMap = (f, xs) --> fold ((memo, x) -> append memo, f x), [], xs
            
            export listToObj = (xs) ->
              {[x.0, x.1] for x in xs}
            
            export maximum = (xs) -> fold1 (>?), xs
            
            export minimum = (xs) -> fold1 (<?), xs
            
            export scan = export scanl = (f, memo, xs) -->
              last = memo
              if typeof! xs is \Object
              then [memo] ++ [last = f last, x for , x of xs]
              else [memo] ++ [last = f last, x for x in xs]
            
            export scan1 = export scanl1 = (f, xs) --> scan f, xs.0, xs.slice 1
            
            export scanr = (f, memo, xs) -->
              xs.=slice!reverse!
              scan f, memo, xs .reverse!
            
            export scanr1 = (f, xs) -->
              xs.=slice!reverse!
              scan f, xs.0, xs.slice 1 .reverse!
            
            export replicate = (n, x) -->
              result = []
              i = 0
              while i < n, ++i then result.push x
              result
            
            export take = (n, xs) -->
              | n <= 0
                if typeof! xs is \String then '' else []
              | not xs.length => xs
              | otherwise     => xs.slice 0, n
            
            export drop = (n, xs) -->
              | n <= 0        => xs
              | not xs.length => xs
              | otherwise     => xs.slice n
            
            export splitAt = (n, xs) --> [(take n, xs), (drop n, xs)]
            
            export takeWhile = (p, xs) -->
              return xs if not xs.length
              p = objToFunc p if typeof! p isnt \Function
              result = []
              for x in xs
                break if not p x
                result.push x
              if typeof! xs is \String then result * '' else result
            
            export dropWhile = (p, xs) -->
              return xs if not xs.length
              p = objToFunc p if typeof! p isnt \Function
              i = 0
              for x in xs
                break if not p x
                ++i
              drop i, xs
            
            export span = (p, xs) --> [(takeWhile p, xs), (dropWhile p, xs)]
            
            export breakIt = (p, xs) --> span (not) << p, xs
            
            export zip = (xs, ys) -->
              result = []
              for zs, i in [xs, ys]
                for z, j in zs
                  result.push [] if i is 0
                  result[j]?push z
              result
            
            export zipWith = (f,xs, ys) -->
              f = objToFunc f if typeof! f isnt \Function
              if not xs.length or not ys.length
                []
              else
                [f.apply this, zs for zs in zip.call this, xs, ys]
            
            export zipAll = (...xss) ->
              result = []
              for xs, i in xss
                for x, j in xs
                  result.push [] if i is 0
                  result[j]?push x
              result
            
            export zipAllWith = (f, ...xss) ->
              f = objToFunc f if typeof! f isnt \Function
              if not xss.0.length or not xss.1.length
                []
              else
                [f.apply this, xs for xs in zipAll.apply this, xss]
            
            export compose = (...funcs) ->
              ->
                args = arguments
                for f in funcs
                  args = [f.apply this, args]
                args.0
            
            export curry = (f) ->
              curry$ f # using util method curry$ from livescript
            
            export id = (x) -> x
            
            export flip = (f, x, y) --> f y, x
            
            export fix = (f) ->
              ( (g, x) -> -> f(g g) ...arguments ) do
                (g, x) -> -> f(g g) ...arguments
            
            export lines = (str) ->
              return [] if not str.length
              str / \\n
            
            export unlines = (strs) -> strs * \\n
            
            export words = (str) ->
              return [] if not str.length
              str / /[ ]+/
            
            export unwords = (strs) -> strs * ' '
            
            export max = (>?)
            
            export min = (<?)
            
            export negate = (x) -> -x
            
            export abs = Math.abs
            
            export signum = (x) ->
              | x < 0     => -1
              | x > 0     =>  1
              | otherwise =>  0
            
            export quot = (x, y) --> ~~(x / y)
            
            export rem = (%)
            
            export div = (x, y) --> Math.floor x / y
            
            export mod = (%%)
            
            export recip = (1 /)
            
            export pi = Math.PI
            
            export tau = pi * 2
            
            export exp = Math.exp
            
            export sqrt = Math.sqrt
            
            # changed from log as log is a
            # common function for logging things
            export ln = Math.log
            
            export pow = (^)
            
            export sin = Math.sin
            
            export tan = Math.tan
            
            export cos = Math.cos
            
            export asin = Math.asin
            
            export acos = Math.acos
            
            export atan = Math.atan
            
            export atan2 = (x, y) --> Math.atan2 x, y
            
            # sinh
            # tanh
            # cosh
            # asinh
            # atanh
            # acosh
            
            export truncate = (x) -> ~~x
            
            export round = Math.round
            
            export ceiling = Math.ceil
            
            export floor = Math.floor
            
            export isItNaN = (x) -> x isnt x
            
            export even = (x) -> x % 2 == 0
            
            export odd = (x) -> x % 2 != 0
            
            export gcd = (x, y) -->
              x = Math.abs x
              y = Math.abs y
              until y is 0
                z = x % y
                x = y
                y = z
              x
            
            export lcm = (x, y) -->
              Math.abs Math.floor (x / (gcd x, y) * y)
            
            # meta
            export installPrelude = !(target) ->
              unless target.prelude?isInstalled
                target <<< out$ # using out$ generated by livescript
                target <<< target.prelude.isInstalled = true
            
            export prelude = out$
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "solarized light",
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-livescript</code>.</p>
            
                <p>The LiveScript mode was written by Kenneth Bentley.</p>
            
              </article>
            
          • livescript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Link to the project's GitHub page:
             * https://github.com/duralog/CodeMirror
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode('livescript', function(){
                var tokenBase = function(stream, state) {
                  var next_rule = state.next || "start";
                  if (next_rule) {
                    state.next = state.next;
                    var nr = Rules[next_rule];
                    if (nr.splice) {
                      for (var i$ = 0; i$ < nr.length; ++i$) {
                        var r = nr[i$], m;
                        if (r.regex && (m = stream.match(r.regex))) {
                          state.next = r.next || state.next;
                          return r.token;
                        }
                      }
                      stream.next();
                      return 'error';
                    }
                    if (stream.match(r = Rules[next_rule])) {
                      if (r.regex && stream.match(r.regex)) {
                        state.next = r.next;
                        return r.token;
                      } else {
                        stream.next();
                        return 'error';
                      }
                    }
                  }
                  stream.next();
                  return 'error';
                };
                var external = {
                  startState: function(){
                    return {
                      next: 'start',
                      lastToken: null
                    };
                  },
                  token: function(stream, state){
                    while (stream.pos == stream.start)
                      var style = tokenBase(stream, state);
                    state.lastToken = {
                      style: style,
                      indent: stream.indentation(),
                      content: stream.current()
                    };
                    return style.replace(/\./g, ' ');
                  },
                  indent: function(state){
                    var indentation = state.lastToken.indent;
                    if (state.lastToken.content.match(indenter)) {
                      indentation += 2;
                    }
                    return indentation;
                  }
                };
                return external;
              });
            
              var identifier = '(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*';
              var indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$');
              var keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))';
              var stringfill = {
                token: 'string',
                regex: '.+'
              };
              var Rules = {
                start: [
                  {
                    token: 'comment.doc',
                    regex: '/\\*',
                    next: 'comment'
                  }, {
                    token: 'comment',
                    regex: '#.*'
                  }, {
                    token: 'keyword',
                    regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend
                  }, {
                    token: 'constant.language',
                    regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend
                  }, {
                    token: 'invalid.illegal',
                    regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend
                  }, {
                    token: 'language.support.class',
                    regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend
                  }, {
                    token: 'language.support.function',
                    regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend
                  }, {
                    token: 'variable.language',
                    regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend
                  }, {
                    token: 'identifier',
                    regex: identifier + '\\s*:(?![:=])'
                  }, {
                    token: 'variable',
                    regex: identifier
                  }, {
                    token: 'keyword.operator',
                    regex: '(?:\\.{3}|\\s+\\?)'
                  }, {
                    token: 'keyword.variable',
                    regex: '(?:@+|::|\\.\\.)',
                    next: 'key'
                  }, {
                    token: 'keyword.operator',
                    regex: '\\.\\s*',
                    next: 'key'
                  }, {
                    token: 'string',
                    regex: '\\\\\\S[^\\s,;)}\\]]*'
                  }, {
                    token: 'string.doc',
                    regex: '\'\'\'',
                    next: 'qdoc'
                  }, {
                    token: 'string.doc',
                    regex: '"""',
                    next: 'qqdoc'
                  }, {
                    token: 'string',
                    regex: '\'',
                    next: 'qstring'
                  }, {
                    token: 'string',
                    regex: '"',
                    next: 'qqstring'
                  }, {
                    token: 'string',
                    regex: '`',
                    next: 'js'
                  }, {
                    token: 'string',
                    regex: '<\\[',
                    next: 'words'
                  }, {
                    token: 'string.regex',
                    regex: '//',
                    next: 'heregex'
                  }, {
                    token: 'string.regex',
                    regex: '\\/(?:[^[\\/\\n\\\\]*(?:(?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[\\/\\n\\\\]*)*)\\/[gimy$]{0,4}',
                    next: 'key'
                  }, {
                    token: 'constant.numeric',
                    regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*|(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*|(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[\\w$]*)'
                  }, {
                    token: 'lparen',
                    regex: '[({[]'
                  }, {
                    token: 'rparen',
                    regex: '[)}\\]]',
                    next: 'key'
                  }, {
                    token: 'keyword.operator',
                    regex: '\\S+'
                  }, {
                    token: 'text',
                    regex: '\\s+'
                  }
                ],
                heregex: [
                  {
                    token: 'string.regex',
                    regex: '.*?//[gimy$?]{0,4}',
                    next: 'start'
                  }, {
                    token: 'string.regex',
                    regex: '\\s*#{'
                  }, {
                    token: 'comment.regex',
                    regex: '\\s+(?:#.*)?'
                  }, {
                    token: 'string.regex',
                    regex: '\\S+'
                  }
                ],
                key: [
                  {
                    token: 'keyword.operator',
                    regex: '[.?@!]+'
                  }, {
                    token: 'identifier',
                    regex: identifier,
                    next: 'start'
                  }, {
                    token: 'text',
                    regex: '',
                    next: 'start'
                  }
                ],
                comment: [
                  {
                    token: 'comment.doc',
                    regex: '.*?\\*/',
                    next: 'start'
                  }, {
                    token: 'comment.doc',
                    regex: '.+'
                  }
                ],
                qdoc: [
                  {
                    token: 'string',
                    regex: ".*?'''",
                    next: 'key'
                  }, stringfill
                ],
                qqdoc: [
                  {
                    token: 'string',
                    regex: '.*?"""',
                    next: 'key'
                  }, stringfill
                ],
                qstring: [
                  {
                    token: 'string',
                    regex: '[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'',
                    next: 'key'
                  }, stringfill
                ],
                qqstring: [
                  {
                    token: 'string',
                    regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',
                    next: 'key'
                  }, stringfill
                ],
                js: [
                  {
                    token: 'string',
                    regex: '[^\\\\`]*(?:\\\\.[^\\\\`]*)*`',
                    next: 'key'
                  }, stringfill
                ],
                words: [
                  {
                    token: 'string',
                    regex: '.*?\\]>',
                    next: 'key'
                  }, stringfill
                ]
              };
              for (var idx in Rules) {
                var r = Rules[idx];
                if (r.splice) {
                  for (var i = 0, len = r.length; i < len; ++i) {
                    var rr = r[i];
                    if (typeof rr.regex === 'string') {
                      Rules[idx][i].regex = new RegExp('^' + rr.regex);
                    }
                  }
                } else if (typeof rr.regex === 'string') {
                  Rules[idx].regex = new RegExp('^' + r.regex);
                }
              }
            
              CodeMirror.defineMIME('text/x-livescript', 'livescript');
            
            });
            
        • lua
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Lua mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../lib/codemirror.js"></script>
            <script src="lua.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Lua</a>
              </ul>
            </div>
            
            <article>
            <h2>Lua mode</h2>
            <form><textarea id="code" name="code">
            --[[
            example useless code to show lua syntax highlighting
            this is multiline comment
            ]]
            
            function blahblahblah(x)
            
              local table = {
                "asd" = 123,
                "x" = 0.34,  
              }
              if x ~= 3 then
                print( x )
              elseif x == "string"
                my_custom_function( 0x34 )
              else
                unknown_function( "some string" )
              end
            
              --single line comment
              
            end
            
            function blablabla3()
            
              for k,v in ipairs( table ) do
                --abcde..
                y=[=[
              x=[[
                  x is a multi line string
               ]]
              but its definition is iside a highest level string!
              ]=]
                print(" \"\" ")
            
                s = math.sin( x )
              end
            
            end
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    matchBrackets: true,
                    theme: "neat"
                  });
                </script>
            
                <p>Loosely based on Franciszek
                Wawrzak's <a href="http://codemirror.net/1/contrib/lua">CodeMirror
                1 mode</a>. One configuration parameter is
                supported, <code>specials</code>, to which you can provide an
                array of strings to have those identifiers highlighted with
                the <code>lua-special</code> style.</p>
                <p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>
            
              </article>
            
          • lua.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
            // CodeMirror 1 mode.
            // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("lua", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
            
              function prefixRE(words) {
                return new RegExp("^(?:" + words.join("|") + ")", "i");
              }
              function wordRE(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var specials = wordRE(parserConfig.specials || []);
            
              // long list of standard functions from lua manual
              var builtins = wordRE([
                "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load",
                "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require",
                "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
            
                "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
            
                "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable",
                "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable",
                "debug.setupvalue","debug.traceback",
            
                "close","flush","lines","read","seek","setvbuf","write",
            
                "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin",
                "io.stdout","io.tmpfile","io.type","io.write",
            
                "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg",
                "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max",
                "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh",
                "math.sqrt","math.tan","math.tanh",
            
                "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale",
                "os.time","os.tmpname",
            
                "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload",
                "package.seeall",
            
                "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub",
                "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
            
                "table.concat","table.insert","table.maxn","table.remove","table.sort"
              ]);
              var keywords = wordRE(["and","break","elseif","false","nil","not","or","return",
                                     "true","function", "end", "if", "then", "else", "do",
                                     "while", "repeat", "until", "for", "in", "local" ]);
            
              var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]);
              var dedentTokens = wordRE(["end", "until", "\\)", "}"]);
              var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]);
            
              function readBracket(stream) {
                var level = 0;
                while (stream.eat("=")) ++level;
                stream.eat("[");
                return level;
              }
            
              function normal(stream, state) {
                var ch = stream.next();
                if (ch == "-" && stream.eat("-")) {
                  if (stream.eat("[") && stream.eat("["))
                    return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
                  stream.skipToEnd();
                  return "comment";
                }
                if (ch == "\"" || ch == "'")
                  return (state.cur = string(ch))(stream, state);
                if (ch == "[" && /[\[=]/.test(stream.peek()))
                  return (state.cur = bracketed(readBracket(stream), "string"))(stream, state);
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w.%]/);
                  return "number";
                }
                if (/[\w_]/.test(ch)) {
                  stream.eatWhile(/[\w\\\-_.]/);
                  return "variable";
                }
                return null;
              }
            
              function bracketed(level, style) {
                return function(stream, state) {
                  var curlev = null, ch;
                  while ((ch = stream.next()) != null) {
                    if (curlev == null) {if (ch == "]") curlev = 0;}
                    else if (ch == "=") ++curlev;
                    else if (ch == "]" && curlev == level) { state.cur = normal; break; }
                    else curlev = null;
                  }
                  return style;
                };
              }
            
              function string(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.cur = normal;
                  return "string";
                };
              }
            
              return {
                startState: function(basecol) {
                  return {basecol: basecol || 0, indentDepth: 0, cur: normal};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.cur(stream, state);
                  var word = stream.current();
                  if (style == "variable") {
                    if (keywords.test(word)) style = "keyword";
                    else if (builtins.test(word)) style = "builtin";
                    else if (specials.test(word)) style = "variable-2";
                  }
                  if ((style != "comment") && (style != "string")){
                    if (indentTokens.test(word)) ++state.indentDepth;
                    else if (dedentTokens.test(word)) --state.indentDepth;
                  }
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var closing = dedentPartial.test(textAfter);
                  return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));
                },
            
                lineComment: "--",
                blockCommentStart: "--[[",
                blockCommentEnd: "]]"
              };
            });
            
            CodeMirror.defineMIME("text/x-lua", "lua");
            
            });
            
        • markdown
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Markdown mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/continuelist.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="markdown.js"></script>
            <style type="text/css">
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default .cm-trailing-space-a:before,
                  .cm-s-default .cm-trailing-space-b:before {position: absolute; content: "\00B7"; color: #777;}
                  .cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Markdown</a>
              </ul>
            </div>
            
            <article>
            <h2>Markdown mode</h2>
            <form><textarea id="code" name="code">
            Markdown: Basics
            ================
            
            &lt;ul id="ProjectSubmenu"&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/" title="Markdown Project Page"&gt;Main&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a class="selected" title="Markdown Basics"&gt;Basics&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/syntax" title="Markdown Syntax Documentation"&gt;Syntax&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/license" title="Pricing and License Information"&gt;License&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/dingus" title="Online Markdown Web Form"&gt;Dingus&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
            
            
            Getting the Gist of Markdown's Formatting Syntax
            ------------------------------------------------
            
            This page offers a brief overview of what it's like to use Markdown.
            The [syntax page] [s] provides complete, detailed documentation for
            every feature, but Markdown should be very easy to pick up simply by
            looking at a few examples of it in action. The examples on this page
            are written in a before/after style, showing example syntax and the
            HTML output produced by Markdown.
            
            It's also helpful to simply try Markdown out; the [Dingus] [d] is a
            web application that allows you type your own Markdown-formatted text
            and translate it to XHTML.
            
            **Note:** This document is itself written using Markdown; you
            can [see the source for it by adding '.text' to the URL] [src].
            
              [s]: /projects/markdown/syntax  "Markdown Syntax"
              [d]: /projects/markdown/dingus  "Markdown Dingus"
              [src]: /projects/markdown/basics.text
            
            
            ## Paragraphs, Headers, Blockquotes ##
            
            A paragraph is simply one or more consecutive lines of text, separated
            by one or more blank lines. (A blank line is any line that looks like
            a blank line -- a line containing nothing but spaces or tabs is
            considered blank.) Normal paragraphs should not be indented with
            spaces or tabs.
            
            Markdown offers two styles of headers: *Setext* and *atx*.
            Setext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by
            "underlining" with equal signs (`=`) and hyphens (`-`), respectively.
            To create an atx-style header, you put 1-6 hash marks (`#`) at the
            beginning of the line -- the number of hashes equals the resulting
            HTML header level.
            
            Blockquotes are indicated using email-style '`&gt;`' angle brackets.
            
            Markdown:
            
                A First Level Header
                ====================
                
                A Second Level Header
                ---------------------
            
                Now is the time for all good men to come to
                the aid of their country. This is just a
                regular paragraph.
            
                The quick brown fox jumped over the lazy
                dog's back.
                
                ### Header 3
            
                &gt; This is a blockquote.
                &gt; 
                &gt; This is the second paragraph in the blockquote.
                &gt;
                &gt; ## This is an H2 in a blockquote
            
            
            Output:
            
                &lt;h1&gt;A First Level Header&lt;/h1&gt;
                
                &lt;h2&gt;A Second Level Header&lt;/h2&gt;
                
                &lt;p&gt;Now is the time for all good men to come to
                the aid of their country. This is just a
                regular paragraph.&lt;/p&gt;
                
                &lt;p&gt;The quick brown fox jumped over the lazy
                dog's back.&lt;/p&gt;
                
                &lt;h3&gt;Header 3&lt;/h3&gt;
                
                &lt;blockquote&gt;
                    &lt;p&gt;This is a blockquote.&lt;/p&gt;
                    
                    &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
                    
                    &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
                &lt;/blockquote&gt;
            
            
            
            ### Phrase Emphasis ###
            
            Markdown uses asterisks and underscores to indicate spans of emphasis.
            
            Markdown:
            
                Some of these words *are emphasized*.
                Some of these words _are emphasized also_.
                
                Use two asterisks for **strong emphasis**.
                Or, if you prefer, __use two underscores instead__.
            
            Output:
            
                &lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
                Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
                
                &lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
                Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
               
            
            
            ## Lists ##
            
            Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
            `+`, and `-`) as list markers. These three markers are
            interchangable; this:
            
                *   Candy.
                *   Gum.
                *   Booze.
            
            this:
            
                +   Candy.
                +   Gum.
                +   Booze.
            
            and this:
            
                -   Candy.
                -   Gum.
                -   Booze.
            
            all produce the same output:
            
                &lt;ul&gt;
                &lt;li&gt;Candy.&lt;/li&gt;
                &lt;li&gt;Gum.&lt;/li&gt;
                &lt;li&gt;Booze.&lt;/li&gt;
                &lt;/ul&gt;
            
            Ordered (numbered) lists use regular numbers, followed by periods, as
            list markers:
            
                1.  Red
                2.  Green
                3.  Blue
            
            Output:
            
                &lt;ol&gt;
                &lt;li&gt;Red&lt;/li&gt;
                &lt;li&gt;Green&lt;/li&gt;
                &lt;li&gt;Blue&lt;/li&gt;
                &lt;/ol&gt;
            
            If you put blank lines between items, you'll get `&lt;p&gt;` tags for the
            list item text. You can create multi-paragraph list items by indenting
            the paragraphs by 4 spaces or 1 tab:
            
                *   A list item.
                
                    With multiple paragraphs.
            
                *   Another item in the list.
            
            Output:
            
                &lt;ul&gt;
                &lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
                &lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
                &lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
                &lt;/ul&gt;
                
            
            
            ### Links ###
            
            Markdown supports two styles for creating links: *inline* and
            *reference*. With both styles, you use square brackets to delimit the
            text you want to turn into a link.
            
            Inline-style links use parentheses immediately after the link text.
            For example:
            
                This is an [example link](http://example.com/).
            
            Output:
            
                &lt;p&gt;This is an &lt;a href="http://example.com/"&gt;
                example link&lt;/a&gt;.&lt;/p&gt;
            
            Optionally, you may include a title attribute in the parentheses:
            
                This is an [example link](http://example.com/ "With a Title").
            
            Output:
            
                &lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;
                example link&lt;/a&gt;.&lt;/p&gt;
            
            Reference-style links allow you to refer to your links by names, which
            you define elsewhere in your document:
            
                I get 10 times more traffic from [Google][1] than from
                [Yahoo][2] or [MSN][3].
            
                [1]: http://google.com/        "Google"
                [2]: http://search.yahoo.com/  "Yahoo Search"
                [3]: http://search.msn.com/    "MSN Search"
            
            Output:
            
                &lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
                title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"
                title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"
                title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
            
            The title attribute is optional. Link names may contain letters,
            numbers and spaces, but are *not* case sensitive:
            
                I start my morning with a cup of coffee and
                [The New York Times][NY Times].
            
                [ny times]: http://www.nytimes.com/
            
            Output:
            
                &lt;p&gt;I start my morning with a cup of coffee and
                &lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
            
            
            ### Images ###
            
            Image syntax is very much like link syntax.
            
            Inline (titles are optional):
            
                ![alt text](/path/to/img.jpg "Title")
            
            Reference-style:
            
                ![alt text][id]
            
                [id]: /path/to/img.jpg "Title"
            
            Both of the above examples produce the same output:
            
                &lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;
            
            
            
            ### Code ###
            
            In a regular paragraph, you can create code span by wrapping text in
            backtick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or
            `&gt;`) will automatically be translated into HTML entities. This makes
            it easy to use Markdown to write about HTML example code:
            
                I strongly recommend against using any `&lt;blink&gt;` tags.
            
                I wish SmartyPants used named entities like `&amp;mdash;`
                instead of decimal-encoded entites like `&amp;#8212;`.
            
            Output:
            
                &lt;p&gt;I strongly recommend against using any
                &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
                
                &lt;p&gt;I wish SmartyPants used named entities like
                &lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
                entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
            
            
            To specify an entire block of pre-formatted code, indent every line of
            the block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,
            and `&gt;` characters will be escaped automatically.
            
            Markdown:
            
                If you want your page to validate under XHTML 1.0 Strict,
                you've got to put paragraph tags in your blockquotes:
            
                    &lt;blockquote&gt;
                        &lt;p&gt;For example.&lt;/p&gt;
                    &lt;/blockquote&gt;
            
            Output:
            
                &lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
                you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
                
                &lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
                    &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
                &amp;lt;/blockquote&amp;gt;
                &lt;/code&gt;&lt;/pre&gt;
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'markdown',
                    lineNumbers: true,
                    theme: "default",
                    extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"}
                  });
                </script>
            
                <p>Optionally depends on the XML mode for properly highlighted inline XML blocks.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#markdown_*">normal</a>,  <a href="../../test/index.html#verbose,markdown_*">verbose</a>.</p>
            
              </article>
            
          • markdown.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
            
              var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
              var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
            
              function getMode(name) {
                if (CodeMirror.findModeByName) {
                  var found = CodeMirror.findModeByName(name);
                  if (found) name = found.mime || found.mimes[0];
                }
                var mode = CodeMirror.getMode(cmCfg, name);
                return mode.name == "null" ? null : mode;
              }
            
              // Should characters that affect highlighting be highlighted separate?
              // Does not include characters that will be output (such as `1.` and `-` for lists)
              if (modeCfg.highlightFormatting === undefined)
                modeCfg.highlightFormatting = false;
            
              // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
              // Excess `>` will emit `error` token.
              if (modeCfg.maxBlockquoteDepth === undefined)
                modeCfg.maxBlockquoteDepth = 0;
            
              // Should underscores in words open/close em/strong?
              if (modeCfg.underscoresBreakWords === undefined)
                modeCfg.underscoresBreakWords = true;
            
              // Turn on fenced code blocks? ("```" to start/end)
              if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
            
              // Turn on task lists? ("- [ ] " and "- [x] ")
              if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
            
              // Turn on strikethrough syntax
              if (modeCfg.strikethrough === undefined)
                modeCfg.strikethrough = false;
            
              var codeDepth = 0;
            
              var header   = 'header'
              ,   code     = 'comment'
              ,   quote    = 'quote'
              ,   list1    = 'variable-2'
              ,   list2    = 'variable-3'
              ,   list3    = 'keyword'
              ,   hr       = 'hr'
              ,   image    = 'tag'
              ,   formatting = 'formatting'
              ,   linkinline = 'link'
              ,   linkemail = 'link'
              ,   linktext = 'link'
              ,   linkhref = 'string'
              ,   em       = 'em'
              ,   strong   = 'strong'
              ,   strikethrough = 'strikethrough';
            
              var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
              ,   ulRE = /^[*\-+]\s+/
              ,   olRE = /^[0-9]+\.\s+/
              ,   taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
              ,   atxHeaderRE = /^#+/
              ,   setextHeaderRE = /^(?:\={1,}|-{1,})$/
              ,   textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
            
              function switchInline(stream, state, f) {
                state.f = state.inline = f;
                return f(stream, state);
              }
            
              function switchBlock(stream, state, f) {
                state.f = state.block = f;
                return f(stream, state);
              }
            
            
              // Blocks
            
              function blankLine(state) {
                // Reset linkTitle state
                state.linkTitle = false;
                // Reset EM state
                state.em = false;
                // Reset STRONG state
                state.strong = false;
                // Reset strikethrough state
                state.strikethrough = false;
                // Reset state.quote
                state.quote = 0;
                if (!htmlFound && state.f == htmlBlock) {
                  state.f = inlineNormal;
                  state.block = blockNormal;
                }
                // Reset state.trailingSpace
                state.trailingSpace = 0;
                state.trailingSpaceNewLine = false;
                // Mark this line as blank
                state.thisLineHasContent = false;
                return null;
              }
            
              function blockNormal(stream, state) {
            
                var sol = stream.sol();
            
                var prevLineIsList = (state.list !== false);
                if (state.list !== false && state.indentationDiff >= 0) { // Continued list
                  if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
                    state.indentation -= state.indentationDiff;
                  }
                  state.list = null;
                } else if (state.list !== false && state.indentation > 0) {
                  state.list = null;
                  state.listDepth = Math.floor(state.indentation / 4);
                } else if (state.list !== false) { // No longer a list
                  state.list = false;
                  state.listDepth = 0;
                }
            
                var match = null;
                if (state.indentationDiff >= 4) {
                  state.indentation -= 4;
                  stream.skipToEnd();
                  return code;
                } else if (stream.eatSpace()) {
                  return null;
                } else if (match = stream.match(atxHeaderRE)) {
                  state.header = match[0].length <= 6 ? match[0].length : 6;
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  state.f = state.inline;
                  return getType(state);
                } else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {
                  state.header = match[0].charAt(0) == '=' ? 1 : 2;
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  state.f = state.inline;
                  return getType(state);
                } else if (stream.eat('>')) {
                  state.indentation++;
                  state.quote = sol ? 1 : state.quote + 1;
                  if (modeCfg.highlightFormatting) state.formatting = "quote";
                  stream.eatSpace();
                  return getType(state);
                } else if (stream.peek() === '[') {
                  return switchInline(stream, state, footnoteLink);
                } else if (stream.match(hrRE, true)) {
                  return hr;
                } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
                  var listType = null;
                  if (stream.match(ulRE, true)) {
                    listType = 'ul';
                  } else {
                    stream.match(olRE, true);
                    listType = 'ol';
                  }
                  state.indentation += 4;
                  state.list = true;
                  state.listDepth++;
                  if (modeCfg.taskLists && stream.match(taskListRE, false)) {
                    state.taskList = true;
                  }
                  state.f = state.inline;
                  if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
                  return getType(state);
                } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
                  // try switching mode
                  state.localMode = getMode(RegExp.$1);
                  if (state.localMode) state.localState = state.localMode.startState();
                  state.f = state.block = local;
                  if (modeCfg.highlightFormatting) state.formatting = "code-block";
                  state.code = true;
                  return getType(state);
                }
            
                return switchInline(stream, state, state.inline);
              }
            
              function htmlBlock(stream, state) {
                var style = htmlMode.token(stream, state.htmlState);
                if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
                    (state.md_inside && stream.current().indexOf(">") > -1)) {
                  state.f = inlineNormal;
                  state.block = blockNormal;
                  state.htmlState = null;
                }
                return style;
              }
            
              function local(stream, state) {
                if (stream.sol() && stream.match("```", false)) {
                  state.localMode = state.localState = null;
                  state.f = state.block = leavingLocal;
                  return null;
                } else if (state.localMode) {
                  return state.localMode.token(stream, state.localState);
                } else {
                  stream.skipToEnd();
                  return code;
                }
              }
            
              function leavingLocal(stream, state) {
                stream.match("```");
                state.block = blockNormal;
                state.f = inlineNormal;
                if (modeCfg.highlightFormatting) state.formatting = "code-block";
                state.code = true;
                var returnType = getType(state);
                state.code = false;
                return returnType;
              }
            
              // Inline
              function getType(state) {
                var styles = [];
            
                if (state.formatting) {
                  styles.push(formatting);
            
                  if (typeof state.formatting === "string") state.formatting = [state.formatting];
            
                  for (var i = 0; i < state.formatting.length; i++) {
                    styles.push(formatting + "-" + state.formatting[i]);
            
                    if (state.formatting[i] === "header") {
                      styles.push(formatting + "-" + state.formatting[i] + "-" + state.header);
                    }
            
                    // Add `formatting-quote` and `formatting-quote-#` for blockquotes
                    // Add `error` instead if the maximum blockquote nesting depth is passed
                    if (state.formatting[i] === "quote") {
                      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
                        styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
                      } else {
                        styles.push("error");
                      }
                    }
                  }
                }
            
                if (state.taskOpen) {
                  styles.push("meta");
                  return styles.length ? styles.join(' ') : null;
                }
                if (state.taskClosed) {
                  styles.push("property");
                  return styles.length ? styles.join(' ') : null;
                }
            
                if (state.linkHref) {
                  styles.push(linkhref);
                  return styles.length ? styles.join(' ') : null;
                }
            
                if (state.strong) { styles.push(strong); }
                if (state.em) { styles.push(em); }
                if (state.strikethrough) { styles.push(strikethrough); }
            
                if (state.linkText) { styles.push(linktext); }
            
                if (state.code) { styles.push(code); }
            
                if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
            
                if (state.quote) {
                  styles.push(quote);
            
                  // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
                  if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
                    styles.push(quote + "-" + state.quote);
                  } else {
                    styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
                  }
                }
            
                if (state.list !== false) {
                  var listMod = (state.listDepth - 1) % 3;
                  if (!listMod) {
                    styles.push(list1);
                  } else if (listMod === 1) {
                    styles.push(list2);
                  } else {
                    styles.push(list3);
                  }
                }
            
                if (state.trailingSpaceNewLine) {
                  styles.push("trailing-space-new-line");
                } else if (state.trailingSpace) {
                  styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
                }
            
                return styles.length ? styles.join(' ') : null;
              }
            
              function handleText(stream, state) {
                if (stream.match(textRE, true)) {
                  return getType(state);
                }
                return undefined;
              }
            
              function inlineNormal(stream, state) {
                var style = state.text(stream, state);
                if (typeof style !== 'undefined')
                  return style;
            
                if (state.list) { // List marker (*, +, -, 1., etc)
                  state.list = null;
                  return getType(state);
                }
            
                if (state.taskList) {
                  var taskOpen = stream.match(taskListRE, true)[1] !== "x";
                  if (taskOpen) state.taskOpen = true;
                  else state.taskClosed = true;
                  if (modeCfg.highlightFormatting) state.formatting = "task";
                  state.taskList = false;
                  return getType(state);
                }
            
                state.taskOpen = false;
                state.taskClosed = false;
            
                if (state.header && stream.match(/^#+$/, true)) {
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  return getType(state);
                }
            
                // Get sol() value now, before character is consumed
                var sol = stream.sol();
            
                var ch = stream.next();
            
                if (ch === '\\') {
                  stream.next();
                  if (modeCfg.highlightFormatting) {
                    var type = getType(state);
                    return type ? type + " formatting-escape" : "formatting-escape";
                  }
                }
            
                // Matches link titles present on next line
                if (state.linkTitle) {
                  state.linkTitle = false;
                  var matchCh = ch;
                  if (ch === '(') {
                    matchCh = ')';
                  }
                  matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
                  var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
                  if (stream.match(new RegExp(regex), true)) {
                    return linkhref;
                  }
                }
            
                // If this block is changed, it may need to be updated in GFM mode
                if (ch === '`') {
                  var previousFormatting = state.formatting;
                  if (modeCfg.highlightFormatting) state.formatting = "code";
                  var t = getType(state);
                  var before = stream.pos;
                  stream.eatWhile('`');
                  var difference = 1 + stream.pos - before;
                  if (!state.code) {
                    codeDepth = difference;
                    state.code = true;
                    return getType(state);
                  } else {
                    if (difference === codeDepth) { // Must be exact
                      state.code = false;
                      return t;
                    }
                    state.formatting = previousFormatting;
                    return getType(state);
                  }
                } else if (state.code) {
                  return getType(state);
                }
            
                if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
                  stream.match(/\[[^\]]*\]/);
                  state.inline = state.f = linkHref;
                  return image;
                }
            
                if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
                  state.linkText = true;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  return getType(state);
                }
            
                if (ch === ']' && state.linkText && stream.match(/\(.*\)| ?\[.*\]/, false)) {
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  state.linkText = false;
                  state.inline = state.f = linkHref;
                  return type;
                }
            
                if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
                  state.f = state.inline = linkInline;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkinline;
                }
            
                if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
                  state.f = state.inline = linkInline;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkemail;
                }
            
                if (ch === '<' && stream.match(/^\w/, false)) {
                  if (stream.string.indexOf(">") != -1) {
                    var atts = stream.string.substring(1,stream.string.indexOf(">"));
                    if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
                      state.md_inside = true;
                    }
                  }
                  stream.backUp(1);
                  state.htmlState = CodeMirror.startState(htmlMode);
                  return switchBlock(stream, state, htmlBlock);
                }
            
                if (ch === '<' && stream.match(/^\/\w*?>/)) {
                  state.md_inside = false;
                  return "tag";
                }
            
                var ignoreUnderscore = false;
                if (!modeCfg.underscoresBreakWords) {
                  if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
                    var prevPos = stream.pos - 2;
                    if (prevPos >= 0) {
                      var prevCh = stream.string.charAt(prevPos);
                      if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
                        ignoreUnderscore = true;
                      }
                    }
                  }
                }
                if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
                  if (sol && stream.peek() === ' ') {
                    // Do nothing, surrounded by newline and space
                  } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
                    if (modeCfg.highlightFormatting) state.formatting = "strong";
                    var t = getType(state);
                    state.strong = false;
                    return t;
                  } else if (!state.strong && stream.eat(ch)) { // Add STRONG
                    state.strong = ch;
                    if (modeCfg.highlightFormatting) state.formatting = "strong";
                    return getType(state);
                  } else if (state.em === ch) { // Remove EM
                    if (modeCfg.highlightFormatting) state.formatting = "em";
                    var t = getType(state);
                    state.em = false;
                    return t;
                  } else if (!state.em) { // Add EM
                    state.em = ch;
                    if (modeCfg.highlightFormatting) state.formatting = "em";
                    return getType(state);
                  }
                } else if (ch === ' ') {
                  if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
                    if (stream.peek() === ' ') { // Surrounded by spaces, ignore
                      return getType(state);
                    } else { // Not surrounded by spaces, back up pointer
                      stream.backUp(1);
                    }
                  }
                }
            
                if (modeCfg.strikethrough) {
                  if (ch === '~' && stream.eatWhile(ch)) {
                    if (state.strikethrough) {// Remove strikethrough
                      if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
                      var t = getType(state);
                      state.strikethrough = false;
                      return t;
                    } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
                      state.strikethrough = true;
                      if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
                      return getType(state);
                    }
                  } else if (ch === ' ') {
                    if (stream.match(/^~~/, true)) { // Probably surrounded by space
                      if (stream.peek() === ' ') { // Surrounded by spaces, ignore
                        return getType(state);
                      } else { // Not surrounded by spaces, back up pointer
                        stream.backUp(2);
                      }
                    }
                  }
                }
            
                if (ch === ' ') {
                  if (stream.match(/ +$/, false)) {
                    state.trailingSpace++;
                  } else if (state.trailingSpace) {
                    state.trailingSpaceNewLine = true;
                  }
                }
            
                return getType(state);
              }
            
              function linkInline(stream, state) {
                var ch = stream.next();
            
                if (ch === ">") {
                  state.f = state.inline = inlineNormal;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkinline;
                }
            
                stream.match(/^[^>]+/, true);
            
                return linkinline;
              }
            
              function linkHref(stream, state) {
                // Check if space, and return NULL if so (to avoid marking the space)
                if(stream.eatSpace()){
                  return null;
                }
                var ch = stream.next();
                if (ch === '(' || ch === '[') {
                  state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
                  if (modeCfg.highlightFormatting) state.formatting = "link-string";
                  state.linkHref = true;
                  return getType(state);
                }
                return 'error';
              }
            
              function getLinkHrefInside(endChar) {
                return function(stream, state) {
                  var ch = stream.next();
            
                  if (ch === endChar) {
                    state.f = state.inline = inlineNormal;
                    if (modeCfg.highlightFormatting) state.formatting = "link-string";
                    var returnState = getType(state);
                    state.linkHref = false;
                    return returnState;
                  }
            
                  if (stream.match(inlineRE(endChar), true)) {
                    stream.backUp(1);
                  }
            
                  state.linkHref = true;
                  return getType(state);
                };
              }
            
              function footnoteLink(stream, state) {
                if (stream.match(/^[^\]]*\]:/, false)) {
                  state.f = footnoteLinkInside;
                  stream.next(); // Consume [
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  state.linkText = true;
                  return getType(state);
                }
                return switchInline(stream, state, inlineNormal);
              }
            
              function footnoteLinkInside(stream, state) {
                if (stream.match(/^\]:/, true)) {
                  state.f = state.inline = footnoteUrl;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var returnType = getType(state);
                  state.linkText = false;
                  return returnType;
                }
            
                stream.match(/^[^\]]+/, true);
            
                return linktext;
              }
            
              function footnoteUrl(stream, state) {
                // Check if space, and return NULL if so (to avoid marking the space)
                if(stream.eatSpace()){
                  return null;
                }
                // Match URL
                stream.match(/^[^\s]+/, true);
                // Check for link title
                if (stream.peek() === undefined) { // End of line, set flag to check next line
                  state.linkTitle = true;
                } else { // More content on line, check if link title
                  stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
                }
                state.f = state.inline = inlineNormal;
                return linkhref;
              }
            
              var savedInlineRE = [];
              function inlineRE(endChar) {
                if (!savedInlineRE[endChar]) {
                  // Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
                  endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
                  // Match any non-endChar, escaped character, as well as the closing
                  // endChar.
                  savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
                }
                return savedInlineRE[endChar];
              }
            
              var mode = {
                startState: function() {
                  return {
                    f: blockNormal,
            
                    prevLineHasContent: false,
                    thisLineHasContent: false,
            
                    block: blockNormal,
                    htmlState: null,
                    indentation: 0,
            
                    inline: inlineNormal,
                    text: handleText,
            
                    formatting: false,
                    linkText: false,
                    linkHref: false,
                    linkTitle: false,
                    em: false,
                    strong: false,
                    header: 0,
                    taskList: false,
                    list: false,
                    listDepth: 0,
                    quote: 0,
                    trailingSpace: 0,
                    trailingSpaceNewLine: false,
                    strikethrough: false
                  };
                },
            
                copyState: function(s) {
                  return {
                    f: s.f,
            
                    prevLineHasContent: s.prevLineHasContent,
                    thisLineHasContent: s.thisLineHasContent,
            
                    block: s.block,
                    htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
                    indentation: s.indentation,
            
                    localMode: s.localMode,
                    localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
            
                    inline: s.inline,
                    text: s.text,
                    formatting: false,
                    linkTitle: s.linkTitle,
                    em: s.em,
                    strong: s.strong,
                    strikethrough: s.strikethrough,
                    header: s.header,
                    taskList: s.taskList,
                    list: s.list,
                    listDepth: s.listDepth,
                    quote: s.quote,
                    trailingSpace: s.trailingSpace,
                    trailingSpaceNewLine: s.trailingSpaceNewLine,
                    md_inside: s.md_inside
                  };
                },
            
                token: function(stream, state) {
            
                  // Reset state.formatting
                  state.formatting = false;
            
                  if (stream.sol()) {
                    var forceBlankLine = !!state.header;
            
                    // Reset state.header
                    state.header = 0;
            
                    if (stream.match(/^\s*$/, true) || forceBlankLine) {
                      state.prevLineHasContent = false;
                      blankLine(state);
                      return forceBlankLine ? this.token(stream, state) : null;
                    } else {
                      state.prevLineHasContent = state.thisLineHasContent;
                      state.thisLineHasContent = true;
                    }
            
                    // Reset state.taskList
                    state.taskList = false;
            
                    // Reset state.code
                    state.code = false;
            
                    // Reset state.trailingSpace
                    state.trailingSpace = 0;
                    state.trailingSpaceNewLine = false;
            
                    state.f = state.block;
                    var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length;
                    var difference = Math.floor((indentation - state.indentation) / 4) * 4;
                    if (difference > 4) difference = 4;
                    var adjustedIndentation = state.indentation + difference;
                    state.indentationDiff = adjustedIndentation - state.indentation;
                    state.indentation = adjustedIndentation;
                    if (indentation > 0) return null;
                  }
                  return state.f(stream, state);
                },
            
                innerMode: function(state) {
                  if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
                  if (state.localState) return {state: state.localState, mode: state.localMode};
                  return {state: state, mode: mode};
                },
            
                blankLine: blankLine,
            
                getType: getType,
            
                fold: "markdown"
              };
              return mode;
            }, "xml");
            
            CodeMirror.defineMIME("text/x-markdown", "markdown");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
              var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true});
              function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
            
              FT("formatting_emAsterisk",
                 "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
            
              FT("formatting_emUnderscore",
                 "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");
            
              FT("formatting_strongAsterisk",
                 "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");
            
              FT("formatting_strongUnderscore",
                 "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");
            
              FT("formatting_codeBackticks",
                 "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
            
              FT("formatting_doubleBackticks",
                 "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
            
              FT("formatting_atxHeader",
                 "[header&header-1&formatting&formatting-header&formatting-header-1 #][header&header-1  foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");
            
              FT("formatting_setextHeader",
                 "foo",
                 "[header&header-1&formatting&formatting-header&formatting-header-1 =]");
            
              FT("formatting_blockquote",
                 "[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]");
            
              FT("formatting_list",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
              FT("formatting_list",
                 "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");
            
              FT("formatting_link",
                 "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]");
            
              FT("formatting_linkReference",
                 "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]",
                 "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]");
            
              FT("formatting_linkWeb",
                 "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");
            
              FT("formatting_linkEmail",
                 "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");
            
              FT("formatting_escape",
                 "[formatting-escape \\*]");
            
              MT("plainText",
                 "foo");
            
              // Don't style single trailing space
              MT("trailingSpace1",
                 "foo ");
            
              // Two or more trailing spaces should be styled with line break character
              MT("trailingSpace2",
                 "foo[trailing-space-a  ][trailing-space-new-line  ]");
            
              MT("trailingSpace3",
                 "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-new-line  ]");
            
              MT("trailingSpace4",
                 "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-a  ][trailing-space-new-line  ]");
            
              // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
              MT("codeBlocksUsing4Spaces",
                 "    [comment foo]");
            
              // Code blocks using 4 spaces with internal indentation
              MT("codeBlocksUsing4SpacesIndentation",
                 "    [comment bar]",
                 "        [comment hello]",
                 "            [comment world]",
                 "    [comment foo]",
                 "bar");
            
              // Code blocks using 4 spaces with internal indentation
              MT("codeBlocksUsing4SpacesIndentation",
                 " foo",
                 "    [comment bar]",
                 "        [comment hello]",
                 "    [comment world]");
            
              // Code blocks should end even after extra indented lines
              MT("codeBlocksWithTrailingIndentedLine",
                 "    [comment foo]",
                 "        [comment bar]",
                 "    [comment baz]",
                 "    ",
                 "hello");
            
              // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
              MT("codeBlocksUsing1Tab",
                 "\t[comment foo]");
            
              // Inline code using backticks
              MT("inlineCodeUsingBackticks",
                 "foo [comment `bar`]");
            
              // Block code using single backtick (shouldn't work)
              MT("blockCodeSingleBacktick",
                 "[comment `]",
                 "foo",
                 "[comment `]");
            
              // Unclosed backticks
              // Instead of simply marking as CODE, it would be nice to have an
              // incomplete flag for CODE, that is styled slightly different.
              MT("unclosedBackticks",
                 "foo [comment `bar]");
            
              // Per documentation: "To include a literal backtick character within a
              // code span, you can use multiple backticks as the opening and closing
              // delimiters"
              MT("doubleBackticks",
                 "[comment ``foo ` bar``]");
            
              // Tests based on Dingus
              // http://daringfireball.net/projects/markdown/dingus
              //
              // Multiple backticks within an inline code block
              MT("consecutiveBackticks",
                 "[comment `foo```bar`]");
            
              // Multiple backticks within an inline code block with a second code block
              MT("consecutiveBackticks",
                 "[comment `foo```bar`] hello [comment `world`]");
            
              // Unclosed with several different groups of backticks
              MT("unclosedBackticks",
                 "[comment ``foo ``` bar` hello]");
            
              // Closed with several different groups of backticks
              MT("closedBackticks",
                 "[comment ``foo ``` bar` hello``] world");
            
              // atx headers
              // http://daringfireball.net/projects/markdown/syntax#header
            
              MT("atxH1",
                 "[header&header-1 # foo]");
            
              MT("atxH2",
                 "[header&header-2 ## foo]");
            
              MT("atxH3",
                 "[header&header-3 ### foo]");
            
              MT("atxH4",
                 "[header&header-4 #### foo]");
            
              MT("atxH5",
                 "[header&header-5 ##### foo]");
            
              MT("atxH6",
                 "[header&header-6 ###### foo]");
            
              // H6 - 7x '#' should still be H6, per Dingus
              // http://daringfireball.net/projects/markdown/dingus
              MT("atxH6NotH7",
                 "[header&header-6 ####### foo]");
            
              // Inline styles should be parsed inside headers
              MT("atxH1inline",
                 "[header&header-1 # foo ][header&header-1&em *bar*]");
            
              // Setext headers - H1, H2
              // Per documentation, "Any number of underlining =’s or -’s will work."
              // http://daringfireball.net/projects/markdown/syntax#header
              // Ideally, the text would be marked as `header` as well, but this is
              // not really feasible at the moment. So, instead, we're testing against
              // what works today, to avoid any regressions.
              //
              // Check if single underlining = works
              MT("setextH1",
                 "foo",
                 "[header&header-1 =]");
            
              // Check if 3+ ='s work
              MT("setextH1",
                 "foo",
                 "[header&header-1 ===]");
            
              // Check if single underlining - works
              MT("setextH2",
                 "foo",
                 "[header&header-2 -]");
            
              // Check if 3+ -'s work
              MT("setextH2",
                 "foo",
                 "[header&header-2 ---]");
            
              // Single-line blockquote with trailing space
              MT("blockquoteSpace",
                 "[quote&quote-1 > foo]");
            
              // Single-line blockquote
              MT("blockquoteNoSpace",
                 "[quote&quote-1 >foo]");
            
              // No blank line before blockquote
              MT("blockquoteNoBlankLine",
                 "foo",
                 "[quote&quote-1 > bar]");
            
              // Nested blockquote
              MT("blockquoteSpace",
                 "[quote&quote-1 > foo]",
                 "[quote&quote-1 >][quote&quote-2 > foo]",
                 "[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
            
              // Single-line blockquote followed by normal paragraph
              MT("blockquoteThenParagraph",
                 "[quote&quote-1 >foo]",
                 "",
                 "bar");
            
              // Multi-line blockquote (lazy mode)
              MT("multiBlockquoteLazy",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 bar]");
            
              // Multi-line blockquote followed by normal paragraph (lazy mode)
              MT("multiBlockquoteLazyThenParagraph",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 bar]",
                 "",
                 "hello");
            
              // Multi-line blockquote (non-lazy mode)
              MT("multiBlockquote",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 >bar]");
            
              // Multi-line blockquote followed by normal paragraph (non-lazy mode)
              MT("multiBlockquoteThenParagraph",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 >bar]",
                 "",
                 "hello");
            
              // Check list types
            
              MT("listAsterisk",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 * foo]",
                 "[variable-2 * bar]");
            
              MT("listPlus",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 + foo]",
                 "[variable-2 + bar]");
            
              MT("listDash",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 - foo]",
                 "[variable-2 - bar]");
            
              MT("listNumber",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 1. foo]",
                 "[variable-2 2. bar]");
            
              // Lists require a preceding blank line (per Dingus)
              MT("listBogus",
                 "foo",
                 "1. bar",
                 "2. hello");
            
              // List after header
              MT("listAfterHeader",
                 "[header&header-1 # foo]",
                 "[variable-2 - bar]");
            
              // Formatting in lists (*)
              MT("listAsteriskFormatting",
                 "[variable-2 * ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 * ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 * ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (+)
              MT("listPlusFormatting",
                 "[variable-2 + ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 + ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 + ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (-)
              MT("listDashFormatting",
                 "[variable-2 - ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 - ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 - ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (1.)
              MT("listNumberFormatting",
                 "[variable-2 1. ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 2. ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 4. ][variable-2&comment `foo`][variable-2  bar]");
            
              // Paragraph lists
              MT("listParagraph",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]");
            
              // Multi-paragraph lists
              //
              // 4 spaces
              MT("listMultiParagraph",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "    [variable-2 hello]");
            
              // 4 spaces, extra blank lines (should still be list, per Dingus)
              MT("listMultiParagraphExtra",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "",
                 "    [variable-2 hello]");
            
              // 4 spaces, plus 1 space (should still be list, per Dingus)
              MT("listMultiParagraphExtraSpace",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "     [variable-2 hello]",
                 "",
                 "    [variable-2 world]");
            
              // 1 tab
              MT("listTab",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "\t[variable-2 hello]");
            
              // No indent
              MT("listNoIndent",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "hello");
            
              // Blockquote
              MT("blockquote",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "    [variable-2&quote&quote-1 > hello]");
            
              // Code block
              MT("blockquoteCode",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "        [comment > hello]",
                 "",
                 "    [variable-2 world]");
            
              // Code block followed by text
              MT("blockquoteCodeText",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-2 bar]",
                 "",
                 "        [comment hello]",
                 "",
                 "    [variable-2 world]");
            
              // Nested list
            
              MT("listAsteriskNested",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 * bar]");
            
              MT("listPlusNested",
                 "[variable-2 + foo]",
                 "",
                 "    [variable-3 + bar]");
            
              MT("listDashNested",
                 "[variable-2 - foo]",
                 "",
                 "    [variable-3 - bar]");
            
              MT("listNumberNested",
                 "[variable-2 1. foo]",
                 "",
                 "    [variable-3 2. bar]");
            
              MT("listMixed",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "        [keyword - hello]",
                 "",
                 "            [variable-2 1. world]");
            
              MT("listBlockquote",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "        [quote&quote-1&variable-3 > hello]");
            
              MT("listCode",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "            [comment hello]");
            
              // Code with internal indentation
              MT("listCodeIndentation",
                 "[variable-2 * foo]",
                 "",
                 "        [comment bar]",
                 "            [comment hello]",
                 "                [comment world]",
                 "        [comment foo]",
                 "    [variable-2 bar]");
            
              // List nesting edge cases
              MT("listNested",
                "[variable-2 * foo]",
                "",
                "    [variable-3 * bar]",
                "",
                "       [variable-2 hello]"
              );
              MT("listNested",
                "[variable-2 * foo]",
                "",
                "    [variable-3 * bar]",
                "",
                "      [variable-3 * foo]"
              );
            
              // Code followed by text
              MT("listCodeText",
                 "[variable-2 * foo]",
                 "",
                 "        [comment bar]",
                 "",
                 "hello");
            
              // Following tests directly from official Markdown documentation
              // http://daringfireball.net/projects/markdown/syntax#hr
            
              MT("hrSpace",
                 "[hr * * *]");
            
              MT("hr",
                 "[hr ***]");
            
              MT("hrLong",
                 "[hr *****]");
            
              MT("hrSpaceDash",
                 "[hr - - -]");
            
              MT("hrDashLong",
                 "[hr ---------------------------------------]");
            
              // Inline link with title
              MT("linkTitle",
                 "[link [[foo]]][string (http://example.com/ \"bar\")] hello");
            
              // Inline link without title
              MT("linkNoTitle",
                 "[link [[foo]]][string (http://example.com/)] bar");
            
              // Inline link with image
              MT("linkImage",
                 "[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar");
            
              // Inline link with Em
              MT("linkEm",
                 "[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar");
            
              // Inline link with Strong
              MT("linkStrong",
                 "[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar");
            
              // Inline link with EmStrong
              MT("linkEmStrong",
                 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar");
            
              // Image with title
              MT("imageTitle",
                 "[tag ![[foo]]][string (http://example.com/ \"bar\")] hello");
            
              // Image without title
              MT("imageNoTitle",
                 "[tag ![[foo]]][string (http://example.com/)] bar");
            
              // Image with asterisks
              MT("imageAsterisks",
                 "[tag ![[*foo*]]][string (http://example.com/)] bar");
            
              // Not a link. Should be normal text due to square brackets being used
              // regularly in text, especially in quoted material, and no space is allowed
              // between square brackets and parentheses (per Dingus).
              MT("notALink",
                 "[[foo]] (bar)");
            
              // Reference-style links
              MT("linkReference",
                 "[link [[foo]]][string [[bar]]] hello");
            
              // Reference-style links with Em
              MT("linkReferenceEm",
                 "[link [[][link&em *foo*][link ]]][string [[bar]]] hello");
            
              // Reference-style links with Strong
              MT("linkReferenceStrong",
                 "[link [[][link&strong **foo**][link ]]][string [[bar]]] hello");
            
              // Reference-style links with EmStrong
              MT("linkReferenceEmStrong",
                 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello");
            
              // Reference-style links with optional space separator (per docuentation)
              // "You can optionally use a space to separate the sets of brackets"
              MT("linkReferenceSpace",
                 "[link [[foo]]] [string [[bar]]] hello");
            
              // Should only allow a single space ("...use *a* space...")
              MT("linkReferenceDoubleSpace",
                 "[[foo]]  [[bar]] hello");
            
              // Reference-style links with implicit link name
              MT("linkImplicit",
                 "[link [[foo]]][string [[]]] hello");
            
              // @todo It would be nice if, at some point, the document was actually
              // checked to see if the referenced link exists
            
              // Link label, for reference-style links (taken from documentation)
            
              MT("labelNoTitle",
                 "[link [[foo]]:] [string http://example.com/]");
            
              MT("labelIndented",
                 "   [link [[foo]]:] [string http://example.com/]");
            
              MT("labelSpaceTitle",
                 "[link [[foo bar]]:] [string http://example.com/ \"hello\"]");
            
              MT("labelDoubleTitle",
                 "[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\"");
            
              MT("labelTitleDoubleQuotes",
                 "[link [[foo]]:] [string http://example.com/  \"bar\"]");
            
              MT("labelTitleSingleQuotes",
                 "[link [[foo]]:] [string http://example.com/  'bar']");
            
              MT("labelTitleParenthese",
                 "[link [[foo]]:] [string http://example.com/  (bar)]");
            
              MT("labelTitleInvalid",
                 "[link [[foo]]:] [string http://example.com/] bar");
            
              MT("labelLinkAngleBrackets",
                 "[link [[foo]]:] [string <http://example.com/>  \"bar\"]");
            
              MT("labelTitleNextDoubleQuotes",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string \"bar\"] hello");
            
              MT("labelTitleNextSingleQuotes",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string 'bar'] hello");
            
              MT("labelTitleNextParenthese",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string (bar)] hello");
            
              MT("labelTitleNextMixed",
                 "[link [[foo]]:] [string http://example.com/]",
                 "(bar\" hello");
            
              MT("linkWeb",
                 "[link <http://example.com/>] foo");
            
              MT("linkWebDouble",
                 "[link <http://example.com/>] foo [link <http://example.com/>]");
            
              MT("linkEmail",
                 "[link <user@example.com>] foo");
            
              MT("linkEmailDouble",
                 "[link <user@example.com>] foo [link <user@example.com>]");
            
              MT("emAsterisk",
                 "[em *foo*] bar");
            
              MT("emUnderscore",
                 "[em _foo_] bar");
            
              MT("emInWordAsterisk",
                 "foo[em *bar*]hello");
            
              MT("emInWordUnderscore",
                 "foo[em _bar_]hello");
            
              // Per documentation: "...surround an * or _ with spaces, it’ll be
              // treated as a literal asterisk or underscore."
            
              MT("emEscapedBySpaceIn",
                 "foo [em _bar _ hello_] world");
            
              MT("emEscapedBySpaceOut",
                 "foo _ bar[em _hello_]world");
            
              MT("emEscapedByNewline",
                 "foo",
                 "_ bar[em _hello_]world");
            
              // Unclosed emphasis characters
              // Instead of simply marking as EM / STRONG, it would be nice to have an
              // incomplete flag for EM and STRONG, that is styled slightly different.
              MT("emIncompleteAsterisk",
                 "foo [em *bar]");
            
              MT("emIncompleteUnderscore",
                 "foo [em _bar]");
            
              MT("strongAsterisk",
                 "[strong **foo**] bar");
            
              MT("strongUnderscore",
                 "[strong __foo__] bar");
            
              MT("emStrongAsterisk",
                 "[em *foo][em&strong **bar*][strong hello**] world");
            
              MT("emStrongUnderscore",
                 "[em _foo][em&strong __bar_][strong hello__] world");
            
              // "...same character must be used to open and close an emphasis span.""
              MT("emStrongMixed",
                 "[em _foo][em&strong **bar*hello__ world]");
            
              MT("emStrongMixed",
                 "[em *foo][em&strong __bar_hello** world]");
            
              // These characters should be escaped:
              // \   backslash
              // `   backtick
              // *   asterisk
              // _   underscore
              // {}  curly braces
              // []  square brackets
              // ()  parentheses
              // #   hash mark
              // +   plus sign
              // -   minus sign (hyphen)
              // .   dot
              // !   exclamation mark
            
              MT("escapeBacktick",
                 "foo \\`bar\\`");
            
              MT("doubleEscapeBacktick",
                 "foo \\\\[comment `bar\\\\`]");
            
              MT("escapeAsterisk",
                 "foo \\*bar\\*");
            
              MT("doubleEscapeAsterisk",
                 "foo \\\\[em *bar\\\\*]");
            
              MT("escapeUnderscore",
                 "foo \\_bar\\_");
            
              MT("doubleEscapeUnderscore",
                 "foo \\\\[em _bar\\\\_]");
            
              MT("escapeHash",
                 "\\# foo");
            
              MT("doubleEscapeHash",
                 "\\\\# foo");
            
              MT("escapeNewline",
                 "\\",
                 "[em *foo*]");
            
            
              // Tests to make sure GFM-specific things aren't getting through
            
              MT("taskList",
                 "[variable-2 * [ ]] bar]");
            
              MT("fencedCodeBlocks",
                 "[comment ```]",
                 "foo",
                 "[comment ```]");
            
              // Tests that require XML mode
            
              MT("xmlMode",
                 "[tag&bracket <][tag div][tag&bracket >]",
                 "*foo*",
                 "[tag&bracket <][tag http://github.com][tag&bracket />]",
                 "[tag&bracket </][tag div][tag&bracket >]",
                 "[link <http://github.com/>]");
            
              MT("xmlModeWithMarkdownInside",
                 "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",
                 "[em *foo*]",
                 "[link <http://github.com/>]",
                 "[tag </div>]",
                 "[link <http://github.com/>]",
                 "[tag&bracket <][tag div][tag&bracket >]",
                 "[tag&bracket </][tag div][tag&bracket >]");
            
            })();
            
        • mirc
          • index.html
            <!doctype html>
            
            <title>CodeMirror: mIRC mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/twilight.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="mirc.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">mIRC</a>
              </ul>
            </div>
            
            <article>
            <h2>mIRC mode</h2>
            <form><textarea id="code" name="code">
            ;AKA Nick Tracker by Ford_Lawnmower irc.GeekShed.net #Script-Help
            ;*****************************************************************************;
            ;**Start Setup
            ;Change JoinDisplay, below, for On Join AKA Display. On = 1 - Off = 0
            alias -l JoinDisplay { return 1 }
            ;Change MaxNicks, below, to the number of nicknames you want to store for each hostmask. I wouldn't go over 400 with this ;/
            alias -l MaxNicks { return 20 }
            ;Change AKALogo, below, To the text you want displayed before each AKA result.
            alias -l AKALogo { return 06 05A06K07A 06 }
            ;**End Setup
            ;*****************************************************************************;
            On *:Join:#: {
              if ($nick == $me) { .timer 1 1 ialupdateCheck $chan }
              NickNamesAdd $nick $+($network,$wildsite)
              if ($JoinDisplay) { .timerNickNames $+ $nick 1 2 NickNames.display $nick $chan $network $wildsite }
            }
            on *:Nick: { NickNamesAdd $newnick $+($network,$wildsite) $nick }
            alias -l NickNames.display {
              if ($gettok($hget(NickNames,$+($3,$4)),0,126) > 1) {
                echo -g $2 $AKALogo $+(09,$1) $AKALogo 07 $mid($replace($hget(NickNames,$+($3,$4)),$chr(126),$chr(44)),2,-1)
              }
            }
            alias -l NickNamesAdd {
              if ($hget(NickNames,$2)) {
                if (!$regex($hget(NickNames,$2),/~\Q $+ $replacecs($1,\E,\E\\E\Q) $+ \E~/i)) {
                  if ($gettok($hget(NickNames,$2),0,126) <= $MaxNicks) {
                    hadd NickNames $2 $+($hget(NickNames,$2),$1,~)
                  }
                  else {
                    hadd NickNames $2 $+($mid($hget(NickNames,$2),$pos($hget(NickNames,$2),~,2)),$1,~)
                  }
                }
              }
              else {
                hadd -m NickNames $2 $+(~,$1,~,$iif($3,$+($3,~)))
              }
            }
            alias -l Fix.All.MindUser {
              var %Fix.Count = $hfind(NickNames,/[^~]+[0-9]{4}~/,0,r).data
              while (%Fix.Count) {
                if ($Fix.MindUser($hget(NickNames,$hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data))) {
                  echo -ag Record %Fix.Count - $v1 - Was Cleaned
                  hadd NickNames $hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data $v1
                }
                dec %Fix.Count
              }
            }
            alias -l Fix.MindUser { return $regsubex($1,/[^~]+[0-9]{4}~/g,$null) }
            menu nicklist,query {
              -
              .AKA
              ..Check $$1: {
                if ($gettok($hget(NickNames,$+($network,$address($1,2))),0,126) > 1) {
                  NickNames.display $1 $active $network $address($1,2)
                }
                else { echo -ag $AKALogo $+(09,$1) 07has not been known by any other nicknames while I have been watching. }
              }
              ..Cleanup $$1:hadd NickNames $+($network,$address($1,2)) $fix.minduser($hget(NickNames,$+($network,$address($1,2))))
              ..Clear $$1:hadd NickNames $+($network,$address($1,2)) $+(~,$1,~)
              ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
              -
            }
            menu status,channel {
              -
              .AKA
              ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
              ..Clean All Records:Fix.All.Minduser
              -
            }
            dialog AKA_Search {
              title "AKA Search Engine"
              size -1 -1 206 221
              option dbu
              edit "", 1, 8 5 149 10, autohs
              button "Search", 2, 163 4 32 12
              radio "Search HostMask", 4, 61 22 55 10
              radio "Search Nicknames", 5, 123 22 56 10
              list 6, 8 38 190 169, sort extsel vsbar
              button "Check Selected", 7, 67 206 40 12
              button "Close", 8, 160 206 38 12, cancel
              box "Search Type", 3, 11 17 183 18
              button "Copy to Clipboard", 9, 111 206 46 12
            }
            On *:Dialog:Aka_Search:init:*: { did -c $dname 5 }
            On *:Dialog:Aka_Search:Sclick:2,7,9: {
              if ($did == 2) && ($did($dname,1)) {
                did -r $dname 6
                var %search $+(*,$v1,*), %type $iif($did($dname,5).state,data,item), %matches = $hfind(NickNames,%search,0,w). [ $+ [ %type ] ]
                while (%matches) {
                  did -a $dname 6 $hfind(NickNames,%search,%matches,w). [ $+ [ %type ] ]
                  dec %matches
                }
                did -c $dname 6 1
              }
              elseif ($did == 7) && ($did($dname,6).seltext) { echo -ga $AKALogo 07 $mid($replace($hget(NickNames,$v1),$chr(126),$chr(44)),2,-1) }
              elseif ($did == 9) && ($did($dname,6).seltext) { clipboard $mid($v1,$pos($v1,*,1)) }
            }
            On *:Start:{
              if (!$hget(NickNames)) { hmake NickNames 10 }
              if ($isfile(NickNames.hsh)) { hload  NickNames NickNames.hsh }
            }
            On *:Exit: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
            On *:Disconnect: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
            On *:Unload: { hfree NickNames }
            alias -l ialupdateCheck {
              inc -z $+(%,ialupdateCheck,$network) $calc($nick($1,0) / 4)
              ;If your ial is already being updated on join .who $1 out.
              ;If you are using /names to update ial you will still need this line.
              .who $1
            }
            Raw 352:*: {
              if ($($+(%,ialupdateCheck,$network),2)) haltdef
              NickNamesAdd $6 $+($network,$address($6,2))
            }
            Raw 315:*: {
              if ($($+(%,ialupdateCheck,$network),2)) haltdef
            }
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "twilight",
                    lineNumbers: true,
                    matchBrackets: true,
                    indentUnit: 4,
                    mode: "text/mirc"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/mirc</code>.</p>
            
              </article>
            
          • mirc.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            //mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMIME("text/mirc", "mirc");
            CodeMirror.defineMode("mirc", function() {
              function parseWords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " +
                                        "$activewid $address $addtok $agent $agentname $agentstat $agentver " +
                                        "$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " +
                                        "$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " +
                                        "$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " +
                                        "$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " +
                                        "$com $comcall $comchan $comerr $compact $compress $comval $cos $count " +
                                        "$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " +
                                        "$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " +
                                        "$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " +
                                        "$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " +
                                        "$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " +
                                        "$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " +
                                        "$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " +
                                        "$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " +
                                        "$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " +
                                        "$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " +
                                        "$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " +
                                        "$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " +
                                        "$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " +
                                        "$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " +
                                        "$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " +
                                        "$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " +
                                        "$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " +
                                        "$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " +
                                        "$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " +
                                        "$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " +
                                        "$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " +
                                        "$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " +
                                        "$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " +
                                        "$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " +
                                        "$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " +
                                        "$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " +
                                        "$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " +
                                        "$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " +
                                        "$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor");
              var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " +
                                        "away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " +
                                        "channel clear clearall cline clipboard close cnick color comclose comopen " +
                                        "comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " +
                                        "debug dec describe dialog did didtok disable disconnect dlevel dline dll " +
                                        "dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " +
                                        "drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " +
                                        "events exit fclose filter findtext finger firewall flash flist flood flush " +
                                        "flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " +
                                        "gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " +
                                        "halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " +
                                        "ialmark identd if ignore iline inc invite iuser join kick linesep links list " +
                                        "load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " +
                                        "notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " +
                                        "qme qmsg query queryn quit raw reload remini remote remove rename renwin " +
                                        "reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " +
                                        "say scid scon server set showmirc signam sline sockaccept sockclose socklist " +
                                        "socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " +
                                        "sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " +
                                        "toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " +
                                        "var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " +
                                        "isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " +
                                        "isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " +
                                        "elseif else goto menu nicklist status title icon size option text edit " +
                                        "button check radio box scroll list combo link tab item");
              var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
              var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
              function tokenBase(stream, state) {
                var beforeParams = state.beforeParams;
                state.beforeParams = false;
                var ch = stream.next();
                if (/[\[\]{}\(\),\.]/.test(ch)) {
                  if (ch == "(" && beforeParams) state.inParams = true;
                  else if (ch == ")") state.inParams = false;
                  return null;
                }
                else if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                else if (ch == "\\") {
                  stream.eat("\\");
                  stream.eat(/./);
                  return "number";
                }
                else if (ch == "/" && stream.eat("*")) {
                  return chain(stream, state, tokenComment);
                }
                else if (ch == ";" && stream.match(/ *\( *\(/)) {
                  return chain(stream, state, tokenUnparsed);
                }
                else if (ch == ";" && !state.inParams) {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (ch == '"') {
                  stream.eat(/"/);
                  return "keyword";
                }
                else if (ch == "$") {
                  stream.eatWhile(/[$_a-z0-9A-Z\.:]/);
                  if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
                    return "keyword";
                  }
                  else {
                    state.beforeParams = true;
                    return "builtin";
                  }
                }
                else if (ch == "%") {
                  stream.eatWhile(/[^,^\s^\(^\)]/);
                  state.beforeParams = true;
                  return "string";
                }
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                else {
                  stream.eatWhile(/[\w\$_{}]/);
                  var word = stream.current().toLowerCase();
                  if (keywords && keywords.propertyIsEnumerable(word))
                    return "keyword";
                  if (functions && functions.propertyIsEnumerable(word)) {
                    state.beforeParams = true;
                    return "keyword";
                  }
                  return null;
                }
              }
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
              function tokenUnparsed(stream, state) {
                var maybeEnd = 0, ch;
                while (ch = stream.next()) {
                  if (ch == ";" && maybeEnd == 2) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  if (ch == ")")
                    maybeEnd++;
                  else if (ch != " ")
                    maybeEnd = 0;
                }
                return "meta";
              }
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    beforeParams: false,
                    inParams: false
                  };
                },
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                }
              };
            });
            
            });
            
        • mllike
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ML-like mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src=../../addon/edit/matchbrackets.js></script>
            <script src=mllike.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">ML-like</a>
              </ul>
            </div>
            
            <article>
            <h2>OCaml mode</h2>
            
            
            <textarea id="ocamlCode">
            (* Summing a list of integers *)
            let rec sum xs =
              match xs with
                | []       -&gt; 0
                | x :: xs' -&gt; x + sum xs'
            
            (* Quicksort *)
            let rec qsort = function
               | [] -&gt; []
               | pivot :: rest -&gt;
                   let is_less x = x &lt; pivot in
                   let left, right = List.partition is_less rest in
                   qsort left @ [pivot] @ qsort right
            
            (* Fibonacci Sequence *)
            let rec fib_aux n a b =
              match n with
              | 0 -&gt; a
              | _ -&gt; fib_aux (n - 1) (a + b) a
            let fib n = fib_aux n 0 1
            
            (* Birthday paradox *)
            let year_size = 365.
            
            let rec birthday_paradox prob people =
                let prob' = (year_size -. float people) /. year_size *. prob  in
                if prob' &lt; 0.5 then
                    Printf.printf "answer = %d\n" (people+1)
                else
                    birthday_paradox prob' (people+1) ;;
            
            birthday_paradox 1.0 1
            
            (* Church numerals *)
            let zero f x = x
            let succ n f x = f (n f x)
            let one = succ zero
            let two = succ (succ zero)
            let add n1 n2 f x = n1 f (n2 f x)
            let to_string n = n (fun k -&gt; "S" ^ k) "0"
            let _ = to_string (add (succ two) two)
            
            (* Elementary functions *)
            let square x = x * x;;
            let rec fact x =
              if x &lt;= 1 then 1 else x * fact (x - 1);;
            
            (* Automatic memory management *)
            let l = 1 :: 2 :: 3 :: [];;
            [1; 2; 3];;
            5 :: l;;
            
            (* Polymorphism: sorting lists *)
            let rec sort = function
              | [] -&gt; []
              | x :: l -&gt; insert x (sort l)
            
            and insert elem = function
              | [] -&gt; [elem]
              | x :: l -&gt;
                  if elem &lt; x then elem :: x :: l else x :: insert elem l;;
            
            (* Imperative features *)
            let add_polynom p1 p2 =
              let n1 = Array.length p1
              and n2 = Array.length p2 in
              let result = Array.create (max n1 n2) 0 in
              for i = 0 to n1 - 1 do result.(i) &lt;- p1.(i) done;
              for i = 0 to n2 - 1 do result.(i) &lt;- result.(i) + p2.(i) done;
              result;;
            add_polynom [| 1; 2 |] [| 1; 2; 3 |];;
            
            (* We may redefine fact using a reference cell and a for loop *)
            let fact n =
              let result = ref 1 in
              for i = 2 to n do
                result := i * !result
               done;
               !result;;
            fact 5;;
            
            (* Triangle (graphics) *)
            let () =
              ignore( Glut.init Sys.argv );
              Glut.initDisplayMode ~double_buffer:true ();
              ignore (Glut.createWindow ~title:"OpenGL Demo");
              let angle t = 10. *. t *. t in
              let render () =
                GlClear.clear [ `color ];
                GlMat.load_identity ();
                GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();
                GlDraw.begins `triangles;
                List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];
                GlDraw.ends ();
                Glut.swapBuffers () in
              GlMat.mode `modelview;
              Glut.displayFunc ~cb:render;
              Glut.idleFunc ~cb:(Some Glut.postRedisplay);
              Glut.mainLoop ()
            
            (* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *)
            (* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)
            </textarea>
            
            <h2>F# mode</h2>
            <textarea id="fsharpCode">
            module CodeMirror.FSharp
            
            let rec fib = function
                | 0 -> 0
                | 1 -> 1
                | n -> fib (n - 1) + fib (n - 2)
            
            type Point =
                {
                    x : int
                    y : int
                }
            
            type Color =
                | Red
                | Green
                | Blue
            
            [0 .. 10]
            |> List.map ((+) 2)
            |> List.fold (fun x y -> x + y) 0
            |> printf "%i"
            </textarea>
            
            
            <script>
              var ocamlEditor = CodeMirror.fromTextArea(document.getElementById('ocamlCode'), {
                mode: 'text/x-ocaml',
                lineNumbers: true,
                matchBrackets: true
              });
            
              var fsharpEditor = CodeMirror.fromTextArea(document.getElementById('fsharpCode'), {
                mode: 'text/x-fsharp',
                lineNumbers: true,
                matchBrackets: true
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-ocaml</code> (OCaml) and <code>text/x-fsharp</code> (F#).</p>
            </article>
            
          • mllike.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('mllike', function(_config, parserConfig) {
              var words = {
                'let': 'keyword',
                'rec': 'keyword',
                'in': 'keyword',
                'of': 'keyword',
                'and': 'keyword',
                'if': 'keyword',
                'then': 'keyword',
                'else': 'keyword',
                'for': 'keyword',
                'to': 'keyword',
                'while': 'keyword',
                'do': 'keyword',
                'done': 'keyword',
                'fun': 'keyword',
                'function': 'keyword',
                'val': 'keyword',
                'type': 'keyword',
                'mutable': 'keyword',
                'match': 'keyword',
                'with': 'keyword',
                'try': 'keyword',
                'open': 'builtin',
                'ignore': 'builtin',
                'begin': 'keyword',
                'end': 'keyword'
              };
            
              var extraWords = parserConfig.extraWords || {};
              for (var prop in extraWords) {
                if (extraWords.hasOwnProperty(prop)) {
                  words[prop] = parserConfig.extraWords[prop];
                }
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                if (ch === '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
                }
                if (ch === '(') {
                  if (stream.eat('*')) {
                    state.commentLevel++;
                    state.tokenize = tokenComment;
                    return state.tokenize(stream, state);
                  }
                }
                if (ch === '~') {
                  stream.eatWhile(/\w/);
                  return 'variable-2';
                }
                if (ch === '`') {
                  stream.eatWhile(/\w/);
                  return 'quote';
                }
                if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
                  stream.skipToEnd();
                  return 'comment';
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\d]/);
                  if (stream.eat('.')) {
                    stream.eatWhile(/[\d]/);
                  }
                  return 'number';
                }
                if ( /[+\-*&%=<>!?|]/.test(ch)) {
                  return 'operator';
                }
                stream.eatWhile(/\w/);
                var cur = stream.current();
                return words[cur] || 'variable';
              }
            
              function tokenString(stream, state) {
                var next, end = false, escaped = false;
                while ((next = stream.next()) != null) {
                  if (next === '"' && !escaped) {
                    end = true;
                    break;
                  }
                  escaped = !escaped && next === '\\';
                }
                if (end && !escaped) {
                  state.tokenize = tokenBase;
                }
                return 'string';
              };
            
              function tokenComment(stream, state) {
                var prev, next;
                while(state.commentLevel > 0 && (next = stream.next()) != null) {
                  if (prev === '(' && next === '*') state.commentLevel++;
                  if (prev === '*' && next === ')') state.commentLevel--;
                  prev = next;
                }
                if (state.commentLevel <= 0) {
                  state.tokenize = tokenBase;
                }
                return 'comment';
              }
            
              return {
                startState: function() {return {tokenize: tokenBase, commentLevel: 0};},
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                },
            
                blockCommentStart: "(*",
                blockCommentEnd: "*)",
                lineComment: parserConfig.slashComments ? "//" : null
              };
            });
            
            CodeMirror.defineMIME('text/x-ocaml', {
              name: 'mllike',
              extraWords: {
                'succ': 'keyword',
                'trace': 'builtin',
                'exit': 'builtin',
                'print_string': 'builtin',
                'print_endline': 'builtin',
                'true': 'atom',
                'false': 'atom',
                'raise': 'keyword'
              }
            });
            
            CodeMirror.defineMIME('text/x-fsharp', {
              name: 'mllike',
              extraWords: {
                'abstract': 'keyword',
                'as': 'keyword',
                'assert': 'keyword',
                'base': 'keyword',
                'class': 'keyword',
                'default': 'keyword',
                'delegate': 'keyword',
                'downcast': 'keyword',
                'downto': 'keyword',
                'elif': 'keyword',
                'exception': 'keyword',
                'extern': 'keyword',
                'finally': 'keyword',
                'global': 'keyword',
                'inherit': 'keyword',
                'inline': 'keyword',
                'interface': 'keyword',
                'internal': 'keyword',
                'lazy': 'keyword',
                'let!': 'keyword',
                'member' : 'keyword',
                'module': 'keyword',
                'namespace': 'keyword',
                'new': 'keyword',
                'null': 'keyword',
                'override': 'keyword',
                'private': 'keyword',
                'public': 'keyword',
                'return': 'keyword',
                'return!': 'keyword',
                'select': 'keyword',
                'static': 'keyword',
                'struct': 'keyword',
                'upcast': 'keyword',
                'use': 'keyword',
                'use!': 'keyword',
                'val': 'keyword',
                'when': 'keyword',
                'yield': 'keyword',
                'yield!': 'keyword',
            
                'List': 'builtin',
                'Seq': 'builtin',
                'Map': 'builtin',
                'Set': 'builtin',
                'int': 'builtin',
                'string': 'builtin',
                'raise': 'builtin',
                'failwith': 'builtin',
                'not': 'builtin',
                'true': 'builtin',
                'false': 'builtin'
              },
              slashComments: true
            });
            
            });
            
        • modelica
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Modelica mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="modelica.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Modelica</a>
              </ul>
            </div>
            
            <article>
            <h2>Modelica mode</h2>
            
            <div><textarea id="modelica">
            model BouncingBall
              parameter Real e = 0.7;
              parameter Real g = 9.81;
              Real h(start=1);
              Real v;
              Boolean flying(start=true);
              Boolean impact;
              Real v_new;
            equation
              impact = h <= 0.0;
              der(v) = if flying then -g else 0;
              der(h) = v;
              when {h <= 0.0 and v <= 0.0, impact} then
                v_new = if edge(impact) then -e*pre(v) else 0;
                flying = v_new > 0;
                reinit(v, v_new);
              end when;
              annotation (uses(Modelica(version="3.2")));
            end BouncingBall;
            </textarea></div>
            
                <script>
                  var modelicaEditor = CodeMirror.fromTextArea(document.getElementById("modelica"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-modelica"
                  });
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
            
                <p>Simple mode that tries to handle Modelica as well as it can.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-modelica</code>
                (Modlica code).</p>
            </article>
            
          • modelica.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Modelica support for CodeMirror, copyright (c) by Lennart Ochel
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })
            
            (function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("modelica", function(config, parserConfig) {
            
                var indentUnit = config.indentUnit;
                var keywords = parserConfig.keywords || {};
                var builtin = parserConfig.builtin || {};
                var atoms = parserConfig.atoms || {};
            
                var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/;
                var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/;
                var isDigit = /[0-9]/;
                var isNonDigit = /[_a-zA-Z]/;
            
                function tokenLineComment(stream, state) {
                  stream.skipToEnd();
                  state.tokenize = null;
                  return "comment";
                }
            
                function tokenBlockComment(stream, state) {
                  var maybeEnd = false, ch;
                  while (ch = stream.next()) {
                    if (maybeEnd && ch == "/") {
                      state.tokenize = null;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return "comment";
                }
            
                function tokenString(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == '"' && !escaped) {
                      state.tokenize = null;
                      state.sol = false;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
            
                  return "string";
                }
            
                function tokenIdent(stream, state) {
                  stream.eatWhile(isDigit);
                  while (stream.eat(isDigit) || stream.eat(isNonDigit)) { }
            
            
                  var cur = stream.current();
            
                  if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++;
                  else if(state.sol && cur == "end" && state.level > 0) state.level--;
            
                  state.tokenize = null;
                  state.sol = false;
            
                  if (keywords.propertyIsEnumerable(cur)) return "keyword";
                  else if (builtin.propertyIsEnumerable(cur)) return "builtin";
                  else if (atoms.propertyIsEnumerable(cur)) return "atom";
                  else return "variable";
                }
            
                function tokenQIdent(stream, state) {
                  while (stream.eat(/[^']/)) { }
            
                  state.tokenize = null;
                  state.sol = false;
            
                  if(stream.eat("'"))
                    return "variable";
                  else
                    return "error";
                }
            
                function tokenUnsignedNuber(stream, state) {
                  stream.eatWhile(isDigit);
                  if (stream.eat('.')) {
                    stream.eatWhile(isDigit);
                  }
                  if (stream.eat('e') || stream.eat('E')) {
                    if (!stream.eat('-'))
                      stream.eat('+');
                    stream.eatWhile(isDigit);
                  }
            
                  state.tokenize = null;
                  state.sol = false;
                  return "number";
                }
            
                // Interface
                return {
                  startState: function() {
                    return {
                      tokenize: null,
                      level: 0,
                      sol: true
                    };
                  },
            
                  token: function(stream, state) {
                    if(state.tokenize != null) {
                      return state.tokenize(stream, state);
                    }
            
                    if(stream.sol()) {
                      state.sol = true;
                    }
            
                    // WHITESPACE
                    if(stream.eatSpace()) {
                      state.tokenize = null;
                      return null;
                    }
            
                    var ch = stream.next();
            
                    // LINECOMMENT
                    if(ch == '/' && stream.eat('/')) {
                      state.tokenize = tokenLineComment;
                    }
                    // BLOCKCOMMENT
                    else if(ch == '/' && stream.eat('*')) {
                      state.tokenize = tokenBlockComment;
                    }
                    // TWO SYMBOL TOKENS
                    else if(isDoubleOperatorChar.test(ch+stream.peek())) {
                      stream.next();
                      state.tokenize = null;
                      return "operator";
                    }
                    // SINGLE SYMBOL TOKENS
                    else if(isSingleOperatorChar.test(ch)) {
                      state.tokenize = null;
                      return "operator";
                    }
                    // IDENT
                    else if(isNonDigit.test(ch)) {
                      state.tokenize = tokenIdent;
                    }
                    // Q-IDENT
                    else if(ch == "'" && stream.peek() && stream.peek() != "'") {
                      state.tokenize = tokenQIdent;
                    }
                    // STRING
                    else if(ch == '"') {
                      state.tokenize = tokenString;
                    }
                    // UNSIGNED_NUBER
                    else if(isDigit.test(ch)) {
                      state.tokenize = tokenUnsignedNuber;
                    }
                    // ERROR
                    else {
                      state.tokenize = null;
                      return "error";
                    }
            
                    return state.tokenize(stream, state);
                  },
            
                  indent: function(state, textAfter) {
                    if (state.tokenize != null) return CodeMirror.Pass;
            
                    var level = state.level;
                    if(/(algorithm)/.test(textAfter)) level--;
                    if(/(equation)/.test(textAfter)) level--;
                    if(/(initial algorithm)/.test(textAfter)) level--;
                    if(/(initial equation)/.test(textAfter)) level--;
                    if(/(end)/.test(textAfter)) level--;
            
                    if(level > 0)
                      return indentUnit*level;
                    else
                      return 0;
                  },
            
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  lineComment: "//"
                };
              });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i=0; i<words.length; ++i)
                  obj[words[i]] = true;
                return obj;
              }
            
              var modelicaKeywords = "algorithm and annotation assert block break class connect connector constant constrainedby der discrete each else elseif elsewhen encapsulated end enumeration equation expandable extends external false final flow for function if import impure in initial inner input loop model not operator or outer output package parameter partial protected public pure record redeclare replaceable return stream then true type when while within";
              var modelicaBuiltin = "abs acos actualStream asin atan atan2 cardinality ceil cos cosh delay div edge exp floor getInstanceName homotopy inStream integer log log10 mod pre reinit rem semiLinear sign sin sinh spatialDistribution sqrt tan tanh";
              var modelicaAtoms = "Real Boolean Integer String";
            
              function def(mimes, mode) {
                if (typeof mimes == "string")
                  mimes = [mimes];
            
                var words = [];
            
                function add(obj) {
                  if (obj)
                    for (var prop in obj)
                      if (obj.hasOwnProperty(prop))
                        words.push(prop);
                }
            
                add(mode.keywords);
                add(mode.builtin);
                add(mode.atoms);
            
                if (words.length) {
                  mode.helperType = mimes[0];
                  CodeMirror.registerHelper("hintWords", mimes[0], words);
                }
            
                for (var i=0; i<mimes.length; ++i)
                  CodeMirror.defineMIME(mimes[i], mode);
              }
            
              def(["text/x-modelica"], {
                name: "modelica",
                keywords: words(modelicaKeywords),
                builtin: words(modelicaBuiltin),
                atoms: words(modelicaAtoms)
              });
            });
            
        • nginx
          • index.html
            <!doctype html>
            
            <title>CodeMirror: NGINX mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="nginx.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
                <link rel="stylesheet" href="../../doc/docs.css">
              </head>
            
              <style>
                body {
                  margin: 0em auto;
                }
            
                .CodeMirror, .CodeMirror-scroll {
                  height: 600px;
                }
              </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">NGINX</a>
              </ul>
            </div>
            
            <article>
            <h2>NGINX mode</h2>
            <form><textarea id="code" name="code" style="height: 800px;">
            server {
              listen 173.255.219.235:80;
              server_name website.com.au;
              rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
            }
            
            server {
              listen 173.255.219.235:443;
              server_name website.com.au;
              rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
            }
            
            server {
            
              listen      173.255.219.235:80;
              server_name www.website.com.au;
            
            
            
              root        /data/www;
              index       index.html index.php;
            
              location / {
                index index.html index.php;     ## Allow a static html file to be shown first
                try_files $uri $uri/ @handler;  ## If missing pass the URI to Magento's front handler
                expires 30d;                    ## Assume all files are cachable
              }
            
              ## These locations would be hidden by .htaccess normally
              location /app/                { deny all; }
              location /includes/           { deny all; }
              location /lib/                { deny all; }
              location /media/downloadable/ { deny all; }
              location /pkginfo/            { deny all; }
              location /report/config.xml   { deny all; }
              location /var/                { deny all; }
            
              location /var/export/ { ## Allow admins only to view export folder
                auth_basic           "Restricted"; ## Message shown in login window
                auth_basic_user_file /rs/passwords/testfile; ## See /etc/nginx/htpassword
                autoindex            on;
              }
            
              location  /. { ## Disable .htaccess and other hidden files
                return 404;
              }
            
              location @handler { ## Magento uses a common front handler
                rewrite / /index.php;
              }
            
              location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
                rewrite ^/(.*.php)/ /$1 last;
              }
            
              location ~ \.php$ {
                if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
            
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        /rs/confs/nginx/fastcgi_params;
              }
            
            }
            
            
            server {
            
              listen              173.255.219.235:443;
              server_name         website.com.au www.website.com.au;
            
              root   /data/www;
              index index.html index.php;
            
              ssl                 on;
              ssl_certificate     /rs/ssl/ssl.crt;
              ssl_certificate_key /rs/ssl/ssl.key;
            
              ssl_session_timeout  5m;
            
              ssl_protocols  SSLv2 SSLv3 TLSv1;
              ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
              ssl_prefer_server_ciphers   on;
            
            
            
              location / {
                index index.html index.php; ## Allow a static html file to be shown first
                try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler
                expires 30d; ## Assume all files are cachable
              }
            
              ## These locations would be hidden by .htaccess normally
              location /app/                { deny all; }
              location /includes/           { deny all; }
              location /lib/                { deny all; }
              location /media/downloadable/ { deny all; }
              location /pkginfo/            { deny all; }
              location /report/config.xml   { deny all; }
              location /var/                { deny all; }
            
              location /var/export/ { ## Allow admins only to view export folder
                auth_basic           "Restricted"; ## Message shown in login window
                auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
                autoindex            on;
              }
            
              location  /. { ## Disable .htaccess and other hidden files
                return 404;
              }
            
              location @handler { ## Magento uses a common front handler
                rewrite / /index.php;
              }
            
              location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
                rewrite ^/(.*.php)/ /$1 last;
              }
            
              location ~ .php$ { ## Execute PHP scripts
                if (!-e $request_filename) { rewrite  /index.php last; } ## Catch 404s that try_files miss
            
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        /rs/confs/nginx/fastcgi_params;
            
                fastcgi_param HTTPS on;
              }
            
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/nginx</code>.</p>
            
              </article>
            
          • nginx.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("nginx", function(config) {
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var keywords = words(
                /* ngxDirectiveControl */ "break return rewrite set" +
                /* ngxDirective */ " accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23"
                );
            
              var keywords_block = words(
                /* ngxDirectiveBlock */ "http mail events server types location upstream charset_map limit_except if geo map"
                );
            
              var keywords_important = words(
                /* ngxDirectiveImportant */ "include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files"
                );
            
              var indentUnit = config.indentUnit, type;
              function ret(style, tp) {type = tp; return style;}
            
              function tokenBase(stream, state) {
            
            
                stream.eatWhile(/[\w\$_]/);
            
                var cur = stream.current();
            
            
                if (keywords.propertyIsEnumerable(cur)) {
                  return "keyword";
                }
                else if (keywords_block.propertyIsEnumerable(cur)) {
                  return "variable-2";
                }
                else if (keywords_important.propertyIsEnumerable(cur)) {
                  return "string-2";
                }
                /**/
            
                var ch = stream.next();
                if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
                else if (ch == "/" && stream.eat("*")) {
                  state.tokenize = tokenCComment;
                  return tokenCComment(stream, state);
                }
                else if (ch == "<" && stream.eat("!")) {
                  state.tokenize = tokenSGMLComment;
                  return tokenSGMLComment(stream, state);
                }
                else if (ch == "=") ret(null, "compare");
                else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return ret("comment", "comment");
                }
                else if (ch == "!") {
                  stream.match(/^\s*\w*/);
                  return ret("keyword", "important");
                }
                else if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w.%]/);
                  return ret("number", "unit");
                }
                else if (/[,.+>*\/]/.test(ch)) {
                  return ret(null, "select-op");
                }
                else if (/[;{}:\[\]]/.test(ch)) {
                  return ret(null, ch);
                }
                else {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("variable", "variable");
                }
              }
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenSGMLComment(stream, state) {
                var dashes = 0, ch;
                while ((ch = stream.next()) != null) {
                  if (dashes >= 2 && ch == ">") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  dashes = (ch == "-") ? dashes + 1 : 0;
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped)
                      break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return ret("string", "string");
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          stack: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  type = null;
                  var style = state.tokenize(stream, state);
            
                  var context = state.stack[state.stack.length-1];
                  if (type == "hash" && context == "rule") style = "atom";
                  else if (style == "variable") {
                    if (context == "rule") style = "number";
                    else if (!context || context == "@media{") style = "tag";
                  }
            
                  if (context == "rule" && /^[\{\};]$/.test(type))
                    state.stack.pop();
                  if (type == "{") {
                    if (context == "@media") state.stack[state.stack.length-1] = "@media{";
                    else state.stack.push("{");
                  }
                  else if (type == "}") state.stack.pop();
                  else if (type == "@media") state.stack.push("@media");
                  else if (context == "{" && type != "comment") state.stack.push("rule");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var n = state.stack.length;
                  if (/^\}/.test(textAfter))
                    n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
                  return state.baseIndent + n * indentUnit;
                },
            
                electricChars: "}"
              };
            });
            
            CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");
            
            });
            
        • ntriples
          • index.html
            <!doctype html>
            
            <title>CodeMirror: NTriples mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ntriples.js"></script>
            <style type="text/css">
                  .CodeMirror {
                    border: 1px solid #eee;
                  }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">NTriples</a>
              </ul>
            </div>
            
            <article>
            <h2>NTriples mode</h2>
            <form>
            <textarea id="ntriples" name="ntriples">    
            <http://Sub1>     <http://pred1>     <http://obj> .
            <http://Sub2>     <http://pred2#an2> "literal 1" .
            <http://Sub3#an3> <http://pred3>     _:bnode3 .
            _:bnode4          <http://pred4>     "literal 2"@lang .
            _:bnode5          <http://pred5>     "literal 3"^^<http://type> .
            </textarea>
            </form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("ntriples"), {});
                </script>
                <p><strong>MIME types defined:</strong> <code>text/n-triples</code>.</p>
              </article>
            
          • ntriples.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**********************************************************
            * This script provides syntax highlighting support for
            * the Ntriples format.
            * Ntriples format specification:
            *     http://www.w3.org/TR/rdf-testcases/#ntriples
            ***********************************************************/
            
            /*
                The following expression defines the defined ASF grammar transitions.
            
                pre_subject ->
                    {
                    ( writing_subject_uri | writing_bnode_uri )
                        -> pre_predicate
                            -> writing_predicate_uri
                                -> pre_object
                                    -> writing_object_uri | writing_object_bnode |
                                      (
                                        writing_object_literal
                                            -> writing_literal_lang | writing_literal_type
                                      )
                                        -> post_object
                                            -> BEGIN
                     } otherwise {
                         -> ERROR
                     }
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ntriples", function() {
            
              var Location = {
                PRE_SUBJECT         : 0,
                WRITING_SUB_URI     : 1,
                WRITING_BNODE_URI   : 2,
                PRE_PRED            : 3,
                WRITING_PRED_URI    : 4,
                PRE_OBJ             : 5,
                WRITING_OBJ_URI     : 6,
                WRITING_OBJ_BNODE   : 7,
                WRITING_OBJ_LITERAL : 8,
                WRITING_LIT_LANG    : 9,
                WRITING_LIT_TYPE    : 10,
                POST_OBJ            : 11,
                ERROR               : 12
              };
              function transitState(currState, c) {
                var currLocation = currState.location;
                var ret;
            
                // Opening.
                if     (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;
                else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;
                else if(currLocation == Location.PRE_PRED    && c == '<') ret = Location.WRITING_PRED_URI;
                else if(currLocation == Location.PRE_OBJ     && c == '<') ret = Location.WRITING_OBJ_URI;
                else if(currLocation == Location.PRE_OBJ     && c == '_') ret = Location.WRITING_OBJ_BNODE;
                else if(currLocation == Location.PRE_OBJ     && c == '"') ret = Location.WRITING_OBJ_LITERAL;
            
                // Closing.
                else if(currLocation == Location.WRITING_SUB_URI     && c == '>') ret = Location.PRE_PRED;
                else if(currLocation == Location.WRITING_BNODE_URI   && c == ' ') ret = Location.PRE_PRED;
                else if(currLocation == Location.WRITING_PRED_URI    && c == '>') ret = Location.PRE_OBJ;
                else if(currLocation == Location.WRITING_OBJ_URI     && c == '>') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_OBJ_BNODE   && c == ' ') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;
            
                // Closing typed and language literal.
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;
            
                // Spaces.
                else if( c == ' ' &&
                         (
                           currLocation == Location.PRE_SUBJECT ||
                           currLocation == Location.PRE_PRED    ||
                           currLocation == Location.PRE_OBJ     ||
                           currLocation == Location.POST_OBJ
                         )
                       ) ret = currLocation;
            
                // Reset.
                else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;
            
                // Error
                else ret = Location.ERROR;
            
                currState.location=ret;
              }
            
              return {
                startState: function() {
                   return {
                       location : Location.PRE_SUBJECT,
                       uris     : [],
                       anchors  : [],
                       bnodes   : [],
                       langs    : [],
                       types    : []
                   };
                },
                token: function(stream, state) {
                  var ch = stream.next();
                  if(ch == '<') {
                     transitState(state, ch);
                     var parsedURI = '';
                     stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );
                     state.uris.push(parsedURI);
                     if( stream.match('#', false) ) return 'variable';
                     stream.next();
                     transitState(state, '>');
                     return 'variable';
                  }
                  if(ch == '#') {
                    var parsedAnchor = '';
                    stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;});
                    state.anchors.push(parsedAnchor);
                    return 'variable-2';
                  }
                  if(ch == '>') {
                      transitState(state, '>');
                      return 'variable';
                  }
                  if(ch == '_') {
                      transitState(state, ch);
                      var parsedBNode = '';
                      stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});
                      state.bnodes.push(parsedBNode);
                      stream.next();
                      transitState(state, ' ');
                      return 'builtin';
                  }
                  if(ch == '"') {
                      transitState(state, ch);
                      stream.eatWhile( function(c) { return c != '"'; } );
                      stream.next();
                      if( stream.peek() != '@' && stream.peek() != '^' ) {
                          transitState(state, '"');
                      }
                      return 'string';
                  }
                  if( ch == '@' ) {
                      transitState(state, '@');
                      var parsedLang = '';
                      stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});
                      state.langs.push(parsedLang);
                      stream.next();
                      transitState(state, ' ');
                      return 'string-2';
                  }
                  if( ch == '^' ) {
                      stream.next();
                      transitState(state, '^');
                      var parsedType = '';
                      stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );
                      state.types.push(parsedType);
                      stream.next();
                      transitState(state, '>');
                      return 'variable';
                  }
                  if( ch == ' ' ) {
                      transitState(state, ch);
                  }
                  if( ch == '.' ) {
                      transitState(state, ch);
                  }
                }
              };
            });
            
            CodeMirror.defineMIME("text/n-triples", "ntriples");
            
            });
            
        • octave
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Octave mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="octave.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Octave</a>
              </ul>
            </div>
            
            <article>
            <h2>Octave mode</h2>
            
                <div><textarea id="code" name="code">
            %numbers
            [1234 1234i 1234j]
            [.234 .234j 2.23i]
            [23e2 12E1j 123D-4 0x234]
            
            %strings
            'asda''a'
            "asda""a"
            
            %identifiers
            a + as123 - __asd__
            
            %operators
            -
            +
            =
            ==
            >
            <
            >=
            <=
            &
            ~
            ...
            break zeros default margin round ones rand
            ceil floor size clear zeros eye mean std cov
            error eval function
            abs acos atan asin cos cosh exp log prod sum
            log10 max min sign sin sinh sqrt tan reshape
            return
            case switch
            else elseif end if otherwise
            do for while
            try catch
            classdef properties events methods
            global persistent
            
            %one line comment
            %{ multi 
            line commment %}
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "octave",
                           version: 2,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-octave</code>.</p>
            </article>
            
          • octave.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("octave", function() {
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]");
              var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;]');
              var doubleOperators = new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))");
              var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))");
              var tripleDelimiters = new RegExp("^((>>=)|(<<=))");
              var expressionEnd = new RegExp("^[\\]\\)]");
              var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*");
            
              var builtins = wordRegexp([
                'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos',
                'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh',
                'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones',
                'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov',
                'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot',
                'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str',
                'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember'
              ]);
            
              var keywords = wordRegexp([
                'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction',
                'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events',
                'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until',
                'continue', 'pkg'
              ]);
            
            
              // tokenizers
              function tokenTranspose(stream, state) {
                if (!stream.sol() && stream.peek() === '\'') {
                  stream.next();
                  state.tokenize = tokenBase;
                  return 'operator';
                }
                state.tokenize = tokenBase;
                return tokenBase(stream, state);
              }
            
            
              function tokenComment(stream, state) {
                if (stream.match(/^.*%}/)) {
                  state.tokenize = tokenBase;
                  return 'comment';
                };
                stream.skipToEnd();
                return 'comment';
              }
            
              function tokenBase(stream, state) {
                // whitespaces
                if (stream.eatSpace()) return null;
            
                // Handle one line Comments
                if (stream.match('%{')){
                  state.tokenize = tokenComment;
                  stream.skipToEnd();
                  return 'comment';
                }
            
                if (stream.match(/^[%#]/)){
                  stream.skipToEnd();
                  return 'comment';
                }
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.+-]/, false)) {
                  if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) {
                    stream.tokenize = tokenBase;
                    return 'number'; };
                  if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; };
                  if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; };
                }
                if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; };
            
                // Handle Strings
                if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } ;
                if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ;
            
                // Handle words
                if (stream.match(keywords)) { return 'keyword'; } ;
                if (stream.match(builtins)) { return 'builtin'; } ;
                if (stream.match(identifiers)) { return 'variable'; } ;
            
                if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; };
                if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; };
            
                if (stream.match(expressionEnd)) {
                  state.tokenize = tokenTranspose;
                  return null;
                };
            
            
                // Handle non-detected items
                stream.next();
                return 'error';
              };
            
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase
                  };
                },
            
                token: function(stream, state) {
                  var style = state.tokenize(stream, state);
                  if (style === 'number' || style === 'variable'){
                    state.tokenize = tokenTranspose;
                  }
                  return style;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-octave", "octave");
            
            });
            
        • pascal
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Pascal mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="pascal.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Pascal</a>
              </ul>
            </div>
            
            <article>
            <h2>Pascal mode</h2>
            
            
            <div><textarea id="code" name="code">
            (* Example Pascal code *)
            
            while a <> b do writeln('Waiting');
             
            if a > b then 
              writeln('Condition met')
            else 
              writeln('Condition not met');
             
            for i := 1 to 10 do 
              writeln('Iteration: ', i:1);
             
            repeat
              a := a + 1
            until a = 10;
             
            case i of
              0: write('zero');
              1: write('one');
              2: write('two')
            end;
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-pascal"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-pascal</code>.</p>
              </article>
            
          • pascal.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pascal", function() {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = words("and array begin case const div do downto else end file for forward integer " +
                                   "boolean char function goto if in label mod nil not of or packed procedure " +
                                   "program record repeat set string then to type until var while with");
              var atoms = {"null": true};
            
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == "#" && state.startOfLine) {
                  stream.skipToEnd();
                  return "meta";
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (ch == "(" && stream.eat("*")) {
                  state.tokenize = tokenComment;
                  return tokenComment(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) return "keyword";
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !escaped) state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == ")" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              // Interface
            
              return {
                startState: function() {
                  return {tokenize: null};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  return style;
                },
            
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-pascal", "pascal");
            
            });
            
        • pegjs
          • index.html
            <!doctype html>
            <html>
              <head>
                <title>CodeMirror: PEG.js Mode</title>
                <meta charset="utf-8"/>
                <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="../javascript/javascript.js"></script>
                <script src="pegjs.js"></script>
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              </head>
              <body>
                <div id=nav>
                  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
                  <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                  </ul>
                  <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="#">PEG.js Mode</a>
                  </ul>
                </div>
            
                <article>
                  <h2>PEG.js Mode</h2>
                  <form><textarea id="code" name="code">
            /*
             * Classic example grammar, which recognizes simple arithmetic expressions like
             * "2*(3+4)". The parser generated from this grammar then computes their value.
             */
            
            start
              = additive
            
            additive
              = left:multiplicative "+" right:additive { return left + right; }
              / multiplicative
            
            multiplicative
              = left:primary "*" right:multiplicative { return left * right; }
              / primary
            
            primary
              = integer
              / "(" additive:additive ")" { return additive; }
            
            integer "integer"
              = digits:[0-9]+ { return parseInt(digits.join(""), 10); }
            
            letter = [a-z]+</textarea></form>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "pegjs"},
                      lineNumbers: true
                    });
                  </script>
                  <h3>The PEG.js Mode</h3>
                  <p> Created by Forbes Lindesay.</p>
                </article>
              </body>
            </html>
            
          • pegjs.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../javascript/javascript"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../javascript/javascript"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pegjs", function (config) {
              var jsMode = CodeMirror.getMode(config, "javascript");
            
              function identifier(stream) {
                return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
              }
            
              return {
                startState: function () {
                  return {
                    inString: false,
                    stringType: null,
                    inComment: false,
                    inChracterClass: false,
                    braced: 0,
                    lhs: true,
                    localState: null
                  };
                },
                token: function (stream, state) {
                  if (stream)
            
                  //check for state changes
                  if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
                    state.stringType = stream.peek();
                    stream.next(); // Skip quote
                    state.inString = true; // Update state
                  }
                  if (!state.inString && !state.inComment && stream.match(/^\/\*/)) {
                    state.inComment = true;
                  }
            
                  //return state
                  if (state.inString) {
                    while (state.inString && !stream.eol()) {
                      if (stream.peek() === state.stringType) {
                        stream.next(); // Skip quote
                        state.inString = false; // Clear flag
                      } else if (stream.peek() === '\\') {
                        stream.next();
                        stream.next();
                      } else {
                        stream.match(/^.[^\\\"\']*/);
                      }
                    }
                    return state.lhs ? "property string" : "string"; // Token style
                  } else if (state.inComment) {
                    while (state.inComment && !stream.eol()) {
                      if (stream.match(/\*\//)) {
                        state.inComment = false; // Clear flag
                      } else {
                        stream.match(/^.[^\*]*/);
                      }
                    }
                    return "comment";
                  } else if (state.inChracterClass) {
                      while (state.inChracterClass && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
                          state.inChracterClass = false;
                        }
                      }
                  } else if (stream.peek() === '[') {
                    stream.next();
                    state.inChracterClass = true;
                    return 'bracket';
                  } else if (stream.match(/^\/\//)) {
                    stream.skipToEnd();
                    return "comment";
                  } else if (state.braced || stream.peek() === '{') {
                    if (state.localState === null) {
                      state.localState = jsMode.startState();
                    }
                    var token = jsMode.token(stream, state.localState);
                    var text = stream.current();
                    if (!token) {
                      for (var i = 0; i < text.length; i++) {
                        if (text[i] === '{') {
                          state.braced++;
                        } else if (text[i] === '}') {
                          state.braced--;
                        }
                      };
                    }
                    return token;
                  } else if (identifier(stream)) {
                    if (stream.peek() === ':') {
                      return 'variable';
                    }
                    return 'variable-2';
                  } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) {
                    stream.next();
                    return 'bracket';
                  } else if (!stream.eatSpace()) {
                    stream.next();
                  }
                  return null;
                }
              };
            }, "javascript");
            
            });
            
        • perl
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Perl mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="perl.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Perl</a>
              </ul>
            </div>
            
            <article>
            <h2>Perl mode</h2>
            
            
            <div><textarea id="code" name="code">
            #!/usr/bin/perl
            
            use Something qw(func1 func2);
            
            # strings
            my $s1 = qq'single line';
            our $s2 = q(multi-
                          line);
            
            =item Something
            	Example.
            =cut
            
            my $html=<<'HTML'
            <html>
            <title>hi!</title>
            </html>
            HTML
            
            print "first,".join(',', 'second', qq~third~);
            
            if($s1 =~ m[(?<!\s)(l.ne)\z]o) {
            	$h->{$1}=$$.' predefined variables';
            	$s2 =~ s/\-line//ox;
            	$s1 =~ s[
            		  line ]
            		[
            		  block
            		]ox;
            }
            
            1; # numbers and comments
            
            __END__
            something...
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-perl</code>.</p>
              </article>
            
          • perl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
            // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("perl",function(){
                    // http://perldoc.perl.org
                    var PERL={                                      //   null - magic touch
                                                                    //   1 - keyword
                                                                    //   2 - def
                                                                    //   3 - atom
                                                                    //   4 - operator
                                                                    //   5 - variable-2 (predefined)
                                                                    //   [x,y] - x=1,2,3; y=must be defined if x{...}
                                                            //      PERL operators
                            '->'                            :   4,
                            '++'                            :   4,
                            '--'                            :   4,
                            '**'                            :   4,
                                                                    //   ! ~ \ and unary + and -
                            '=~'                            :   4,
                            '!~'                            :   4,
                            '*'                             :   4,
                            '/'                             :   4,
                            '%'                             :   4,
                            'x'                             :   4,
                            '+'                             :   4,
                            '-'                             :   4,
                            '.'                             :   4,
                            '<<'                            :   4,
                            '>>'                            :   4,
                                                                    //   named unary operators
                            '<'                             :   4,
                            '>'                             :   4,
                            '<='                            :   4,
                            '>='                            :   4,
                            'lt'                            :   4,
                            'gt'                            :   4,
                            'le'                            :   4,
                            'ge'                            :   4,
                            '=='                            :   4,
                            '!='                            :   4,
                            '<=>'                           :   4,
                            'eq'                            :   4,
                            'ne'                            :   4,
                            'cmp'                           :   4,
                            '~~'                            :   4,
                            '&'                             :   4,
                            '|'                             :   4,
                            '^'                             :   4,
                            '&&'                            :   4,
                            '||'                            :   4,
                            '//'                            :   4,
                            '..'                            :   4,
                            '...'                           :   4,
                            '?'                             :   4,
                            ':'                             :   4,
                            '='                             :   4,
                            '+='                            :   4,
                            '-='                            :   4,
                            '*='                            :   4,  //   etc. ???
                            ','                             :   4,
                            '=>'                            :   4,
                            '::'                            :   4,
                                                                    //   list operators (rightward)
                            'not'                           :   4,
                            'and'                           :   4,
                            'or'                            :   4,
                            'xor'                           :   4,
                                                            //      PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
                            'BEGIN'                         :   [5,1],
                            'END'                           :   [5,1],
                            'PRINT'                         :   [5,1],
                            'PRINTF'                        :   [5,1],
                            'GETC'                          :   [5,1],
                            'READ'                          :   [5,1],
                            'READLINE'                      :   [5,1],
                            'DESTROY'                       :   [5,1],
                            'TIE'                           :   [5,1],
                            'TIEHANDLE'                     :   [5,1],
                            'UNTIE'                         :   [5,1],
                            'STDIN'                         :    5,
                            'STDIN_TOP'                     :    5,
                            'STDOUT'                        :    5,
                            'STDOUT_TOP'                    :    5,
                            'STDERR'                        :    5,
                            'STDERR_TOP'                    :    5,
                            '$ARG'                          :    5,
                            '$_'                            :    5,
                            '@ARG'                          :    5,
                            '@_'                            :    5,
                            '$LIST_SEPARATOR'               :    5,
                            '$"'                            :    5,
                            '$PROCESS_ID'                   :    5,
                            '$PID'                          :    5,
                            '$$'                            :    5,
                            '$REAL_GROUP_ID'                :    5,
                            '$GID'                          :    5,
                            '$('                            :    5,
                            '$EFFECTIVE_GROUP_ID'           :    5,
                            '$EGID'                         :    5,
                            '$)'                            :    5,
                            '$PROGRAM_NAME'                 :    5,
                            '$0'                            :    5,
                            '$SUBSCRIPT_SEPARATOR'          :    5,
                            '$SUBSEP'                       :    5,
                            '$;'                            :    5,
                            '$REAL_USER_ID'                 :    5,
                            '$UID'                          :    5,
                            '$<'                            :    5,
                            '$EFFECTIVE_USER_ID'            :    5,
                            '$EUID'                         :    5,
                            '$>'                            :    5,
                            '$a'                            :    5,
                            '$b'                            :    5,
                            '$COMPILING'                    :    5,
                            '$^C'                           :    5,
                            '$DEBUGGING'                    :    5,
                            '$^D'                           :    5,
                            '${^ENCODING}'                  :    5,
                            '$ENV'                          :    5,
                            '%ENV'                          :    5,
                            '$SYSTEM_FD_MAX'                :    5,
                            '$^F'                           :    5,
                            '@F'                            :    5,
                            '${^GLOBAL_PHASE}'              :    5,
                            '$^H'                           :    5,
                            '%^H'                           :    5,
                            '@INC'                          :    5,
                            '%INC'                          :    5,
                            '$INPLACE_EDIT'                 :    5,
                            '$^I'                           :    5,
                            '$^M'                           :    5,
                            '$OSNAME'                       :    5,
                            '$^O'                           :    5,
                            '${^OPEN}'                      :    5,
                            '$PERLDB'                       :    5,
                            '$^P'                           :    5,
                            '$SIG'                          :    5,
                            '%SIG'                          :    5,
                            '$BASETIME'                     :    5,
                            '$^T'                           :    5,
                            '${^TAINT}'                     :    5,
                            '${^UNICODE}'                   :    5,
                            '${^UTF8CACHE}'                 :    5,
                            '${^UTF8LOCALE}'                :    5,
                            '$PERL_VERSION'                 :    5,
                            '$^V'                           :    5,
                            '${^WIN32_SLOPPY_STAT}'         :    5,
                            '$EXECUTABLE_NAME'              :    5,
                            '$^X'                           :    5,
                            '$1'                            :    5, // - regexp $1, $2...
                            '$MATCH'                        :    5,
                            '$&'                            :    5,
                            '${^MATCH}'                     :    5,
                            '$PREMATCH'                     :    5,
                            '$`'                            :    5,
                            '${^PREMATCH}'                  :    5,
                            '$POSTMATCH'                    :    5,
                            "$'"                            :    5,
                            '${^POSTMATCH}'                 :    5,
                            '$LAST_PAREN_MATCH'             :    5,
                            '$+'                            :    5,
                            '$LAST_SUBMATCH_RESULT'         :    5,
                            '$^N'                           :    5,
                            '@LAST_MATCH_END'               :    5,
                            '@+'                            :    5,
                            '%LAST_PAREN_MATCH'             :    5,
                            '%+'                            :    5,
                            '@LAST_MATCH_START'             :    5,
                            '@-'                            :    5,
                            '%LAST_MATCH_START'             :    5,
                            '%-'                            :    5,
                            '$LAST_REGEXP_CODE_RESULT'      :    5,
                            '$^R'                           :    5,
                            '${^RE_DEBUG_FLAGS}'            :    5,
                            '${^RE_TRIE_MAXBUF}'            :    5,
                            '$ARGV'                         :    5,
                            '@ARGV'                         :    5,
                            'ARGV'                          :    5,
                            'ARGVOUT'                       :    5,
                            '$OUTPUT_FIELD_SEPARATOR'       :    5,
                            '$OFS'                          :    5,
                            '$,'                            :    5,
                            '$INPUT_LINE_NUMBER'            :    5,
                            '$NR'                           :    5,
                            '$.'                            :    5,
                            '$INPUT_RECORD_SEPARATOR'       :    5,
                            '$RS'                           :    5,
                            '$/'                            :    5,
                            '$OUTPUT_RECORD_SEPARATOR'      :    5,
                            '$ORS'                          :    5,
                            '$\\'                           :    5,
                            '$OUTPUT_AUTOFLUSH'             :    5,
                            '$|'                            :    5,
                            '$ACCUMULATOR'                  :    5,
                            '$^A'                           :    5,
                            '$FORMAT_FORMFEED'              :    5,
                            '$^L'                           :    5,
                            '$FORMAT_PAGE_NUMBER'           :    5,
                            '$%'                            :    5,
                            '$FORMAT_LINES_LEFT'            :    5,
                            '$-'                            :    5,
                            '$FORMAT_LINE_BREAK_CHARACTERS' :    5,
                            '$:'                            :    5,
                            '$FORMAT_LINES_PER_PAGE'        :    5,
                            '$='                            :    5,
                            '$FORMAT_TOP_NAME'              :    5,
                            '$^'                            :    5,
                            '$FORMAT_NAME'                  :    5,
                            '$~'                            :    5,
                            '${^CHILD_ERROR_NATIVE}'        :    5,
                            '$EXTENDED_OS_ERROR'            :    5,
                            '$^E'                           :    5,
                            '$EXCEPTIONS_BEING_CAUGHT'      :    5,
                            '$^S'                           :    5,
                            '$WARNING'                      :    5,
                            '$^W'                           :    5,
                            '${^WARNING_BITS}'              :    5,
                            '$OS_ERROR'                     :    5,
                            '$ERRNO'                        :    5,
                            '$!'                            :    5,
                            '%OS_ERROR'                     :    5,
                            '%ERRNO'                        :    5,
                            '%!'                            :    5,
                            '$CHILD_ERROR'                  :    5,
                            '$?'                            :    5,
                            '$EVAL_ERROR'                   :    5,
                            '$@'                            :    5,
                            '$OFMT'                         :    5,
                            '$#'                            :    5,
                            '$*'                            :    5,
                            '$ARRAY_BASE'                   :    5,
                            '$['                            :    5,
                            '$OLD_PERL_VERSION'             :    5,
                            '$]'                            :    5,
                                                            //      PERL blocks
                            'if'                            :[1,1],
                            elsif                           :[1,1],
                            'else'                          :[1,1],
                            'while'                         :[1,1],
                            unless                          :[1,1],
                            'for'                           :[1,1],
                            foreach                         :[1,1],
                                                            //      PERL functions
                            'abs'                           :1,     // - absolute value function
                            accept                          :1,     // - accept an incoming socket connect
                            alarm                           :1,     // - schedule a SIGALRM
                            'atan2'                         :1,     // - arctangent of Y/X in the range -PI to PI
                            bind                            :1,     // - binds an address to a socket
                            binmode                         :1,     // - prepare binary files for I/O
                            bless                           :1,     // - create an object
                            bootstrap                       :1,     //
                            'break'                         :1,     // - break out of a "given" block
                            caller                          :1,     // - get context of the current subroutine call
                            chdir                           :1,     // - change your current working directory
                            chmod                           :1,     // - changes the permissions on a list of files
                            chomp                           :1,     // - remove a trailing record separator from a string
                            chop                            :1,     // - remove the last character from a string
                            chown                           :1,     // - change the owership on a list of files
                            chr                             :1,     // - get character this number represents
                            chroot                          :1,     // - make directory new root for path lookups
                            close                           :1,     // - close file (or pipe or socket) handle
                            closedir                        :1,     // - close directory handle
                            connect                         :1,     // - connect to a remote socket
                            'continue'                      :[1,1], // - optional trailing block in a while or foreach
                            'cos'                           :1,     // - cosine function
                            crypt                           :1,     // - one-way passwd-style encryption
                            dbmclose                        :1,     // - breaks binding on a tied dbm file
                            dbmopen                         :1,     // - create binding on a tied dbm file
                            'default'                       :1,     //
                            defined                         :1,     // - test whether a value, variable, or function is defined
                            'delete'                        :1,     // - deletes a value from a hash
                            die                             :1,     // - raise an exception or bail out
                            'do'                            :1,     // - turn a BLOCK into a TERM
                            dump                            :1,     // - create an immediate core dump
                            each                            :1,     // - retrieve the next key/value pair from a hash
                            endgrent                        :1,     // - be done using group file
                            endhostent                      :1,     // - be done using hosts file
                            endnetent                       :1,     // - be done using networks file
                            endprotoent                     :1,     // - be done using protocols file
                            endpwent                        :1,     // - be done using passwd file
                            endservent                      :1,     // - be done using services file
                            eof                             :1,     // - test a filehandle for its end
                            'eval'                          :1,     // - catch exceptions or compile and run code
                            'exec'                          :1,     // - abandon this program to run another
                            exists                          :1,     // - test whether a hash key is present
                            exit                            :1,     // - terminate this program
                            'exp'                           :1,     // - raise I to a power
                            fcntl                           :1,     // - file control system call
                            fileno                          :1,     // - return file descriptor from filehandle
                            flock                           :1,     // - lock an entire file with an advisory lock
                            fork                            :1,     // - create a new process just like this one
                            format                          :1,     // - declare a picture format with use by the write() function
                            formline                        :1,     // - internal function used for formats
                            getc                            :1,     // - get the next character from the filehandle
                            getgrent                        :1,     // - get next group record
                            getgrgid                        :1,     // - get group record given group user ID
                            getgrnam                        :1,     // - get group record given group name
                            gethostbyaddr                   :1,     // - get host record given its address
                            gethostbyname                   :1,     // - get host record given name
                            gethostent                      :1,     // - get next hosts record
                            getlogin                        :1,     // - return who logged in at this tty
                            getnetbyaddr                    :1,     // - get network record given its address
                            getnetbyname                    :1,     // - get networks record given name
                            getnetent                       :1,     // - get next networks record
                            getpeername                     :1,     // - find the other end of a socket connection
                            getpgrp                         :1,     // - get process group
                            getppid                         :1,     // - get parent process ID
                            getpriority                     :1,     // - get current nice value
                            getprotobyname                  :1,     // - get protocol record given name
                            getprotobynumber                :1,     // - get protocol record numeric protocol
                            getprotoent                     :1,     // - get next protocols record
                            getpwent                        :1,     // - get next passwd record
                            getpwnam                        :1,     // - get passwd record given user login name
                            getpwuid                        :1,     // - get passwd record given user ID
                            getservbyname                   :1,     // - get services record given its name
                            getservbyport                   :1,     // - get services record given numeric port
                            getservent                      :1,     // - get next services record
                            getsockname                     :1,     // - retrieve the sockaddr for a given socket
                            getsockopt                      :1,     // - get socket options on a given socket
                            given                           :1,     //
                            glob                            :1,     // - expand filenames using wildcards
                            gmtime                          :1,     // - convert UNIX time into record or string using Greenwich time
                            'goto'                          :1,     // - create spaghetti code
                            grep                            :1,     // - locate elements in a list test true against a given criterion
                            hex                             :1,     // - convert a string to a hexadecimal number
                            'import'                        :1,     // - patch a module's namespace into your own
                            index                           :1,     // - find a substring within a string
                            'int'                           :1,     // - get the integer portion of a number
                            ioctl                           :1,     // - system-dependent device control system call
                            'join'                          :1,     // - join a list into a string using a separator
                            keys                            :1,     // - retrieve list of indices from a hash
                            kill                            :1,     // - send a signal to a process or process group
                            last                            :1,     // - exit a block prematurely
                            lc                              :1,     // - return lower-case version of a string
                            lcfirst                         :1,     // - return a string with just the next letter in lower case
                            length                          :1,     // - return the number of bytes in a string
                            'link'                          :1,     // - create a hard link in the filesytem
                            listen                          :1,     // - register your socket as a server
                            local                           : 2,    // - create a temporary value for a global variable (dynamic scoping)
                            localtime                       :1,     // - convert UNIX time into record or string using local time
                            lock                            :1,     // - get a thread lock on a variable, subroutine, or method
                            'log'                           :1,     // - retrieve the natural logarithm for a number
                            lstat                           :1,     // - stat a symbolic link
                            m                               :null,  // - match a string with a regular expression pattern
                            map                             :1,     // - apply a change to a list to get back a new list with the changes
                            mkdir                           :1,     // - create a directory
                            msgctl                          :1,     // - SysV IPC message control operations
                            msgget                          :1,     // - get SysV IPC message queue
                            msgrcv                          :1,     // - receive a SysV IPC message from a message queue
                            msgsnd                          :1,     // - send a SysV IPC message to a message queue
                            my                              : 2,    // - declare and assign a local variable (lexical scoping)
                            'new'                           :1,     //
                            next                            :1,     // - iterate a block prematurely
                            no                              :1,     // - unimport some module symbols or semantics at compile time
                            oct                             :1,     // - convert a string to an octal number
                            open                            :1,     // - open a file, pipe, or descriptor
                            opendir                         :1,     // - open a directory
                            ord                             :1,     // - find a character's numeric representation
                            our                             : 2,    // - declare and assign a package variable (lexical scoping)
                            pack                            :1,     // - convert a list into a binary representation
                            'package'                       :1,     // - declare a separate global namespace
                            pipe                            :1,     // - open a pair of connected filehandles
                            pop                             :1,     // - remove the last element from an array and return it
                            pos                             :1,     // - find or set the offset for the last/next m//g search
                            print                           :1,     // - output a list to a filehandle
                            printf                          :1,     // - output a formatted list to a filehandle
                            prototype                       :1,     // - get the prototype (if any) of a subroutine
                            push                            :1,     // - append one or more elements to an array
                            q                               :null,  // - singly quote a string
                            qq                              :null,  // - doubly quote a string
                            qr                              :null,  // - Compile pattern
                            quotemeta                       :null,  // - quote regular expression magic characters
                            qw                              :null,  // - quote a list of words
                            qx                              :null,  // - backquote quote a string
                            rand                            :1,     // - retrieve the next pseudorandom number
                            read                            :1,     // - fixed-length buffered input from a filehandle
                            readdir                         :1,     // - get a directory from a directory handle
                            readline                        :1,     // - fetch a record from a file
                            readlink                        :1,     // - determine where a symbolic link is pointing
                            readpipe                        :1,     // - execute a system command and collect standard output
                            recv                            :1,     // - receive a message over a Socket
                            redo                            :1,     // - start this loop iteration over again
                            ref                             :1,     // - find out the type of thing being referenced
                            rename                          :1,     // - change a filename
                            require                         :1,     // - load in external functions from a library at runtime
                            reset                           :1,     // - clear all variables of a given name
                            'return'                        :1,     // - get out of a function early
                            reverse                         :1,     // - flip a string or a list
                            rewinddir                       :1,     // - reset directory handle
                            rindex                          :1,     // - right-to-left substring search
                            rmdir                           :1,     // - remove a directory
                            s                               :null,  // - replace a pattern with a string
                            say                             :1,     // - print with newline
                            scalar                          :1,     // - force a scalar context
                            seek                            :1,     // - reposition file pointer for random-access I/O
                            seekdir                         :1,     // - reposition directory pointer
                            select                          :1,     // - reset default output or do I/O multiplexing
                            semctl                          :1,     // - SysV semaphore control operations
                            semget                          :1,     // - get set of SysV semaphores
                            semop                           :1,     // - SysV semaphore operations
                            send                            :1,     // - send a message over a socket
                            setgrent                        :1,     // - prepare group file for use
                            sethostent                      :1,     // - prepare hosts file for use
                            setnetent                       :1,     // - prepare networks file for use
                            setpgrp                         :1,     // - set the process group of a process
                            setpriority                     :1,     // - set a process's nice value
                            setprotoent                     :1,     // - prepare protocols file for use
                            setpwent                        :1,     // - prepare passwd file for use
                            setservent                      :1,     // - prepare services file for use
                            setsockopt                      :1,     // - set some socket options
                            shift                           :1,     // - remove the first element of an array, and return it
                            shmctl                          :1,     // - SysV shared memory operations
                            shmget                          :1,     // - get SysV shared memory segment identifier
                            shmread                         :1,     // - read SysV shared memory
                            shmwrite                        :1,     // - write SysV shared memory
                            shutdown                        :1,     // - close down just half of a socket connection
                            'sin'                           :1,     // - return the sine of a number
                            sleep                           :1,     // - block for some number of seconds
                            socket                          :1,     // - create a socket
                            socketpair                      :1,     // - create a pair of sockets
                            'sort'                          :1,     // - sort a list of values
                            splice                          :1,     // - add or remove elements anywhere in an array
                            'split'                         :1,     // - split up a string using a regexp delimiter
                            sprintf                         :1,     // - formatted print into a string
                            'sqrt'                          :1,     // - square root function
                            srand                           :1,     // - seed the random number generator
                            stat                            :1,     // - get a file's status information
                            state                           :1,     // - declare and assign a state variable (persistent lexical scoping)
                            study                           :1,     // - optimize input data for repeated searches
                            'sub'                           :1,     // - declare a subroutine, possibly anonymously
                            'substr'                        :1,     // - get or alter a portion of a stirng
                            symlink                         :1,     // - create a symbolic link to a file
                            syscall                         :1,     // - execute an arbitrary system call
                            sysopen                         :1,     // - open a file, pipe, or descriptor
                            sysread                         :1,     // - fixed-length unbuffered input from a filehandle
                            sysseek                         :1,     // - position I/O pointer on handle used with sysread and syswrite
                            system                          :1,     // - run a separate program
                            syswrite                        :1,     // - fixed-length unbuffered output to a filehandle
                            tell                            :1,     // - get current seekpointer on a filehandle
                            telldir                         :1,     // - get current seekpointer on a directory handle
                            tie                             :1,     // - bind a variable to an object class
                            tied                            :1,     // - get a reference to the object underlying a tied variable
                            time                            :1,     // - return number of seconds since 1970
                            times                           :1,     // - return elapsed time for self and child processes
                            tr                              :null,  // - transliterate a string
                            truncate                        :1,     // - shorten a file
                            uc                              :1,     // - return upper-case version of a string
                            ucfirst                         :1,     // - return a string with just the next letter in upper case
                            umask                           :1,     // - set file creation mode mask
                            undef                           :1,     // - remove a variable or function definition
                            unlink                          :1,     // - remove one link to a file
                            unpack                          :1,     // - convert binary structure into normal perl variables
                            unshift                         :1,     // - prepend more elements to the beginning of a list
                            untie                           :1,     // - break a tie binding to a variable
                            use                             :1,     // - load in a module at compile time
                            utime                           :1,     // - set a file's last access and modify times
                            values                          :1,     // - return a list of the values in a hash
                            vec                             :1,     // - test or set particular bits in a string
                            wait                            :1,     // - wait for any child process to die
                            waitpid                         :1,     // - wait for a particular child process to die
                            wantarray                       :1,     // - get void vs scalar vs list context of current subroutine call
                            warn                            :1,     // - print debugging info
                            when                            :1,     //
                            write                           :1,     // - print a picture record
                            y                               :null}; // - transliterate a string
            
                    var RXstyle="string-2";
                    var RXmodifiers=/[goseximacplud]/;              // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
            
                    function tokenChain(stream,state,chain,style,tail){     // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
                            state.chain=null;                               //                                                          12   3tail
                            state.style=null;
                            state.tail=null;
                            state.tokenize=function(stream,state){
                                    var e=false,c,i=0;
                                    while(c=stream.next()){
                                            if(c===chain[i]&&!e){
                                                    if(chain[++i]!==undefined){
                                                            state.chain=chain[i];
                                                            state.style=style;
                                                            state.tail=tail;}
                                                    else if(tail)
                                                            stream.eatWhile(tail);
                                                    state.tokenize=tokenPerl;
                                                    return style;}
                                            e=!e&&c=="\\";}
                                    return style;};
                            return state.tokenize(stream,state);}
            
                    function tokenSOMETHING(stream,state,string){
                            state.tokenize=function(stream,state){
                                    if(stream.string==string)
                                            state.tokenize=tokenPerl;
                                    stream.skipToEnd();
                                    return "string";};
                            return state.tokenize(stream,state);}
            
                    function tokenPerl(stream,state){
                            if(stream.eatSpace())
                                    return null;
                            if(state.chain)
                                    return tokenChain(stream,state,state.chain,state.style,state.tail);
                            if(stream.match(/^\-?[\d\.]/,false))
                                    if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/))
                                            return 'number';
                            if(stream.match(/^<<(?=\w)/)){                  // NOTE: <<SOMETHING\n...\nSOMETHING\n
                                    stream.eatWhile(/\w/);
                                    return tokenSOMETHING(stream,state,stream.current().substr(2));}
                            if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n
                                    return tokenSOMETHING(stream,state,'=cut');}
                            var ch=stream.next();
                            if(ch=='"'||ch=="'"){                           // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n
                                    if(prefix(stream, 3)=="<<"+ch){
                                            var p=stream.pos;
                                            stream.eatWhile(/\w/);
                                            var n=stream.current().substr(1);
                                            if(n&&stream.eat(ch))
                                                    return tokenSOMETHING(stream,state,n);
                                            stream.pos=p;}
                                    return tokenChain(stream,state,[ch],"string");}
                            if(ch=="q"){
                                    var c=look(stream, -2);
                                    if(!(c&&/\w/.test(c))){
                                            c=look(stream, 0);
                                            if(c=="x"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
                                            else if(c=="q"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],"string");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],"string");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],"string");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],"string");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],"string");}}
                                            else if(c=="w"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],"bracket");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],"bracket");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],"bracket");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],"bracket");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],"bracket");}}
                                            else if(c=="r"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
                                            else if(/[\^'"!~\/(\[{<]/.test(c)){
                                                    if(c=="("){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[")"],"string");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,["]"],"string");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,["}"],"string");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[">"],"string");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            return tokenChain(stream,state,[stream.eat(c)],"string");}}}}
                            if(ch=="m"){
                                    var c=look(stream, -2);
                                    if(!(c&&/\w/.test(c))){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}
                                                    if(c=="("){
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}
                            if(ch=="s"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
                            if(ch=="y"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
                            if(ch=="t"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat("r");if(c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}
                            if(ch=="`"){
                                    return tokenChain(stream,state,[ch],"variable-2");}
                            if(ch=="/"){
                                    if(!/~\s*$/.test(prefix(stream)))
                                            return "operator";
                                    else
                                            return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}
                            if(ch=="$"){
                                    var p=stream.pos;
                                    if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
                                            return "variable-2";
                                    else
                                            stream.pos=p;}
                            if(/[$@%]/.test(ch)){
                                    var p=stream.pos;
                                    if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
                                            var c=stream.current();
                                            if(PERL[c])
                                                    return "variable-2";}
                                    stream.pos=p;}
                            if(/[$@%&]/.test(ch)){
                                    if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){
                                            var c=stream.current();
                                            if(PERL[c])
                                                    return "variable-2";
                                            else
                                                    return "variable";}}
                            if(ch=="#"){
                                    if(look(stream, -2)!="$"){
                                            stream.skipToEnd();
                                            return "comment";}}
                            if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
                                    var p=stream.pos;
                                    stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
                                    if(PERL[stream.current()])
                                            return "operator";
                                    else
                                            stream.pos=p;}
                            if(ch=="_"){
                                    if(stream.pos==1){
                                            if(suffix(stream, 6)=="_END__"){
                                                    return tokenChain(stream,state,['\0'],"comment");}
                                            else if(suffix(stream, 7)=="_DATA__"){
                                                    return tokenChain(stream,state,['\0'],"variable-2");}
                                            else if(suffix(stream, 7)=="_C__"){
                                                    return tokenChain(stream,state,['\0'],"string");}}}
                            if(/\w/.test(ch)){
                                    var p=stream.pos;
                                    if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}"))
                                            return "string";
                                    else
                                            stream.pos=p;}
                            if(/[A-Z]/.test(ch)){
                                    var l=look(stream, -2);
                                    var p=stream.pos;
                                    stream.eatWhile(/[A-Z_]/);
                                    if(/[\da-z]/.test(look(stream, 0))){
                                            stream.pos=p;}
                                    else{
                                            var c=PERL[stream.current()];
                                            if(!c)
                                                    return "meta";
                                            if(c[1])
                                                    c=c[0];
                                            if(l!=":"){
                                                    if(c==1)
                                                            return "keyword";
                                                    else if(c==2)
                                                            return "def";
                                                    else if(c==3)
                                                            return "atom";
                                                    else if(c==4)
                                                            return "operator";
                                                    else if(c==5)
                                                            return "variable-2";
                                                    else
                                                            return "meta";}
                                            else
                                                    return "meta";}}
                            if(/[a-zA-Z_]/.test(ch)){
                                    var l=look(stream, -2);
                                    stream.eatWhile(/\w/);
                                    var c=PERL[stream.current()];
                                    if(!c)
                                            return "meta";
                                    if(c[1])
                                            c=c[0];
                                    if(l!=":"){
                                            if(c==1)
                                                    return "keyword";
                                            else if(c==2)
                                                    return "def";
                                            else if(c==3)
                                                    return "atom";
                                            else if(c==4)
                                                    return "operator";
                                            else if(c==5)
                                                    return "variable-2";
                                            else
                                                    return "meta";}
                                    else
                                            return "meta";}
                            return null;}
            
                    return {
                        startState: function() {
                            return {
                                tokenize: tokenPerl,
                                chain: null,
                                style: null,
                                tail: null
                            };
                        },
                        token: function(stream, state) {
                            return (state.tokenize || tokenPerl)(stream, state);
                        },
                        lineComment: '#'
                    };
            });
            
            CodeMirror.registerHelper("wordChars", "perl", /[\w$]/);
            
            CodeMirror.defineMIME("text/x-perl", "perl");
            
            // it's like "peek", but need for look-ahead or look-behind if index < 0
            function look(stream, c){
              return stream.string.charAt(stream.pos+(c||0));
            }
            
            // return a part of prefix of current stream from current position
            function prefix(stream, c){
              if(c){
                var x=stream.pos-c;
                return stream.string.substr((x>=0?x:0),c);}
              else{
                return stream.string.substr(0,stream.pos-1);
              }
            }
            
            // return a part of suffix of current stream from current position
            function suffix(stream, c){
              var y=stream.string.length;
              var x=y-stream.pos+1;
              return stream.string.substr(stream.pos,(c&&c<y?c:x));
            }
            
            // eating and vomiting a part of stream from current position
            function eatSuffix(stream, c){
              var x=stream.pos+c;
              var y;
              if(x<=0)
                stream.pos=0;
              else if(x>=(y=stream.string.length-1))
                stream.pos=y;
              else
                stream.pos=x;
            }
            
            });
            
        • php
          • index.html
            <!doctype html>
            
            <title>CodeMirror: PHP mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="php.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">PHP</a>
              </ul>
            </div>
            
            <article>
            <h2>PHP mode</h2>
            <form><textarea id="code" name="code">
            <?php
            $a = array('a' => 1, 'b' => 2, 3 => 'c');
            
            echo "$a[a] ${a[3] /* } comment */} {$a[b]} \$a[a]";
            
            function hello($who) {
            	return "Hello $who!";
            }
            ?>
            <p>The program says <?= hello("World") ?>.</p>
            <script>
            	alert("And here is some JS code"); // also colored
            </script>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "application/x-httpd-php",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Simple HTML/PHP mode based on
                the <a href="../clike/">C-like</a> mode. Depends on XML,
                JavaScript, CSS, HTMLMixed, and C-like modes.</p>
            
                <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
              </article>
            
          • php.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function keywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // Helper for stringWithEscapes
              function matchSequence(list, end) {
                if (list.length == 0) return stringWithEscapes(end);
                return function (stream, state) {
                  var patterns = list[0];
                  for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {
                    state.tokenize = matchSequence(list.slice(1), end);
                    return patterns[i][1];
                  }
                  state.tokenize = stringWithEscapes(end);
                  return "string";
                };
              }
              function stringWithEscapes(closing) {
                return function(stream, state) { return stringWithEscapes_(stream, state, closing); };
              }
              function stringWithEscapes_(stream, state, closing) {
                // "Complex" syntax
                if (stream.match("${", false) || stream.match("{$", false)) {
                  state.tokenize = null;
                  return "string";
                }
            
                // Simple syntax
                if (stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
                  // After the variable name there may appear array or object operator.
                  if (stream.match("[", false)) {
                    // Match array operator
                    state.tokenize = matchSequence([
                      [["[", null]],
                      [[/\d[\w\.]*/, "number"],
                       [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],
                       [/[\w\$]+/, "variable"]],
                      [["]", null]]
                    ], closing);
                  }
                  if (stream.match(/\-\>\w/, false)) {
                    // Match object operator
                    state.tokenize = matchSequence([
                      [["->", null]],
                      [[/[\w]+/, "variable"]]
                    ], closing);
                  }
                  return "variable-2";
                }
            
                var escaped = false;
                // Normal string
                while (!stream.eol() &&
                       (escaped || (!stream.match("{$", false) &&
                                    !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) {
                  if (!escaped && stream.match(closing)) {
                    state.tokenize = null;
                    state.tokStack.pop(); state.tokStack.pop();
                    break;
                  }
                  escaped = stream.next() == "\\" && !escaped;
                }
                return "string";
              }
            
              var phpKeywords = "abstract and array as break case catch class clone const continue declare default " +
                "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
                "for foreach function global goto if implements interface instanceof namespace " +
                "new or private protected public static switch throw trait try use var while xor " +
                "die echo empty exit eval include include_once isset list require require_once return " +
                "print unset __halt_compiler self static parent yield insteadof finally";
              var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
              var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
              CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
              CodeMirror.registerHelper("wordChars", "php", /[\w$]/);
            
              var phpConfig = {
                name: "clike",
                helperType: "php",
                keywords: keywords(phpKeywords),
                blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),
                atoms: keywords(phpAtoms),
                builtin: keywords(phpBuiltin),
                multiLineStrings: true,
                hooks: {
                  "$": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "variable-2";
                  },
                  "<": function(stream, state) {
                    if (stream.match(/<</)) {
                      stream.eatWhile(/[\w\.]/);
                      var delim = stream.current().slice(3);
                      if (delim) {
                        (state.tokStack || (state.tokStack = [])).push(delim, 0);
                        state.tokenize = stringWithEscapes(delim);
                        return "string";
                      }
                    }
                    return false;
                  },
                  "#": function(stream) {
                    while (!stream.eol() && !stream.match("?>", false)) stream.next();
                    return "comment";
                  },
                  "/": function(stream) {
                    if (stream.eat("/")) {
                      while (!stream.eol() && !stream.match("?>", false)) stream.next();
                      return "comment";
                    }
                    return false;
                  },
                  '"': function(_stream, state) {
                    (state.tokStack || (state.tokStack = [])).push('"', 0);
                    state.tokenize = stringWithEscapes('"');
                    return "string";
                  },
                  "{": function(_stream, state) {
                    if (state.tokStack && state.tokStack.length)
                      state.tokStack[state.tokStack.length - 1]++;
                    return false;
                  },
                  "}": function(_stream, state) {
                    if (state.tokStack && state.tokStack.length > 0 &&
                        !--state.tokStack[state.tokStack.length - 1]) {
                      state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]);
                    }
                    return false;
                  }
                }
              };
            
              CodeMirror.defineMode("php", function(config, parserConfig) {
                var htmlMode = CodeMirror.getMode(config, "text/html");
                var phpMode = CodeMirror.getMode(config, phpConfig);
            
                function dispatch(stream, state) {
                  var isPHP = state.curMode == phpMode;
                  if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null;
                  if (!isPHP) {
                    if (stream.match(/^<\?\w*/)) {
                      state.curMode = phpMode;
                      state.curState = state.php;
                      return "meta";
                    }
                    if (state.pending == '"' || state.pending == "'") {
                      while (!stream.eol() && stream.next() != state.pending) {}
                      var style = "string";
                    } else if (state.pending && stream.pos < state.pending.end) {
                      stream.pos = state.pending.end;
                      var style = state.pending.style;
                    } else {
                      var style = htmlMode.token(stream, state.curState);
                    }
                    if (state.pending) state.pending = null;
                    var cur = stream.current(), openPHP = cur.search(/<\?/), m;
                    if (openPHP != -1) {
                      if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0];
                      else state.pending = {end: stream.pos, style: style};
                      stream.backUp(cur.length - openPHP);
                    }
                    return style;
                  } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
                    state.curMode = htmlMode;
                    state.curState = state.html;
                    return "meta";
                  } else {
                    return phpMode.token(stream, state.curState);
                  }
                }
            
                return {
                  startState: function() {
                    var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
                    return {html: html,
                            php: php,
                            curMode: parserConfig.startOpen ? phpMode : htmlMode,
                            curState: parserConfig.startOpen ? php : html,
                            pending: null};
                  },
            
                  copyState: function(state) {
                    var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
                        php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
                    if (state.curMode == htmlMode) cur = htmlNew;
                    else cur = phpNew;
                    return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
                            pending: state.pending};
                  },
            
                  token: dispatch,
            
                  indent: function(state, textAfter) {
                    if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
                        (state.curMode == phpMode && /^\?>/.test(textAfter)))
                      return htmlMode.indent(state.html, textAfter);
                    return state.curMode.indent(state.curState, textAfter);
                  },
            
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  lineComment: "//",
            
                  innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
                };
              }, "htmlmixed", "clike");
            
              CodeMirror.defineMIME("application/x-httpd-php", "php");
              CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
              CodeMirror.defineMIME("text/x-php", phpConfig);
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "php");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT('simple_test',
                 '[meta <?php] ' +
                 '[keyword echo] [string "aaa"]; ' +
                 '[meta ?>]');
            
              MT('variable_interpolation_non_alphanumeric',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa$~$!$@$#$$$%$^$&$*$($)$.$<$>$/$\\$}$\\\"$:$;$?$|$[[$]]$+$=aaa"]',
                 '[meta ?>]');
            
              MT('variable_interpolation_digits',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa$1$2$3$4$5$6$7$8$9$0aaa"]',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_1',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $aaa][string .aaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_2',
                 '[meta <?php]',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2]',         ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2345]',      ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2.3]',       ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa"];',
            
                 '[keyword echo] [string "1aaa][variable-2 $aaaa][[','[number 2]',         ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[number 2345]',      ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[number 2.3]',       ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_3',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string .aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_escaping',
                 '[meta <?php] [comment /* Escaping */]',
                 '[keyword echo] [string "aaa\\$aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa\\$aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\$aaaa[[asd]]aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\$aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\$aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\aaaaa[[asd]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa[[asd]]aaa.aaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_complex_syntax_1',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa][[','  [number 42]',']]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa');
            
              MT('variable_interpolation_complex_syntax_2',
                 '[meta <?php] [comment /* Monsters */]',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>} $aaa<?php } */]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>*/][[','  [string "aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string "]',']]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa"];');
            
            
              function build_recursive_monsters(nt, t, n){
                var monsters = [t];
                for (var i = 1; i <= n; ++i)
                  monsters[i] = nt.join(monsters[i - 1]);
                return monsters;
              }
            
              var m1 = build_recursive_monsters(
                ['[string "][variable-2 $]{[variable aaa] [operator +] ', '}[string "]'],
                '[comment /* }?>} */] [string "aaa][variable-2 $aaa][string .aaa"]',
                10
              );
            
              MT('variable_interpolation_complex_syntax_3_1',
                 '[meta <?php] [comment /* Recursive monsters */]',
                 '[keyword echo] ' + m1[4] + ';',
                 '[keyword echo] ' + m1[7] + ';',
                 '[keyword echo] ' + m1[8] + ';',
                 '[keyword echo] ' + m1[5] + ';',
                 '[keyword echo] ' + m1[1] + ';',
                 '[keyword echo] ' + m1[6] + ';',
                 '[keyword echo] ' + m1[9] + ';',
                 '[keyword echo] ' + m1[0] + ';',
                 '[keyword echo] ' + m1[10] + ';',
                 '[keyword echo] ' + m1[2] + ';',
                 '[keyword echo] ' + m1[3] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              var m2 = build_recursive_monsters(
                ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', '}[string .a"]'],
                '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]',
                5
              );
            
              MT('variable_interpolation_complex_syntax_3_2',
                 '[meta <?php] [comment /* Recursive monsters 2 */]',
                 '[keyword echo] ' + m2[0] + ';',
                 '[keyword echo] ' + m2[1] + ';',
                 '[keyword echo] ' + m2[5] + ';',
                 '[keyword echo] ' + m2[4] + ';',
                 '[keyword echo] ' + m2[2] + ';',
                 '[keyword echo] ' + m2[3] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              function build_recursive_monsters_2(mf1, mf2, nt, t, n){
                var monsters = [t];
                for (var i = 1; i <= n; ++i)
                  monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3];
                return monsters;
              }
            
              var m3 = build_recursive_monsters_2(
                m1,
                m2,
                ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', ' [operator +] ', '}[string .a"]'],
                '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]',
                4
              );
            
              MT('variable_interpolation_complex_syntax_3_3',
                 '[meta <?php] [comment /* Recursive monsters 2 */]',
                 '[keyword echo] ' + m3[4] + ';',
                 '[keyword echo] ' + m3[0] + ';',
                 '[keyword echo] ' + m3[3] + ';',
                 '[keyword echo] ' + m3[1] + ';',
                 '[keyword echo] ' + m3[2] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              MT("variable_interpolation_heredoc",
                 "[meta <?php]",
                 "[string <<<here]",
                 "[string doc ][variable-2 $]{[variable yay]}[string more]",
                 "[string here]; [comment // normal]");
            })();
            
        • pig
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Pig Latin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="pig.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Pig Latin</a>
              </ul>
            </div>
            
            <article>
            <h2>Pig Latin mode</h2>
            <form><textarea id="code" name="code">
            -- Apache Pig (Pig Latin Language) Demo
            /* 
            This is a multiline comment.
            */
            a = LOAD "\path\to\input" USING PigStorage('\t') AS (x:long, y:chararray, z:bytearray);
            b = GROUP a BY (x,y,3+4);
            c = FOREACH b GENERATE flatten(group) as (x,y), SUM(group.$2) as z;
            STORE c INTO "\path\to\output";
            
            --
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    indentUnit: 4,
                    mode: "text/x-pig"
                  });
                </script>
            
                <p>
                    Simple mode that handles Pig Latin language.
                </p>
            
                <p><strong>MIME type defined:</strong> <code>text/x-pig</code>
                (PIG code)
            </html>
            </article>
            
          • pig.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             *      Pig Latin Mode for CodeMirror 2
             *      @author Prasanth Jayachandran
             *      @link   https://github.com/prasanthj/pig-codemirror-2
             *  This implementation is adapted from PL/SQL mode in CodeMirror 2.
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pig", function(_config, parserConfig) {
              var keywords = parserConfig.keywords,
              builtins = parserConfig.builtins,
              types = parserConfig.types,
              multiLineStrings = parserConfig.multiLineStrings;
            
              var isOperatorChar = /[*+\-%<>=&?:\/!|]/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              var type;
              function ret(tp, style) {
                type = tp;
                return style;
              }
            
              function tokenComment(stream, state) {
                var isEnd = false;
                var ch;
                while(ch = stream.next()) {
                  if(ch == "/" && isEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  isEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      end = true; break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = tokenBase;
                  return ret("string", "error");
                };
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                // is a start of string?
                if (ch == '"' || ch == "'")
                  return chain(stream, state, tokenString(ch));
                // is it one of the special chars
                else if(/[\[\]{}\(\),;\.]/.test(ch))
                  return ret(ch);
                // is it a number?
                else if(/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return ret("number", "number");
                }
                // multi line comment or operator
                else if (ch == "/") {
                  if (stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", "operator");
                  }
                }
                // single line comment or operator
                else if (ch=="-") {
                  if(stream.eat("-")){
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", "operator");
                  }
                }
                // is it an operator
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return ret("operator", "operator");
                }
                else {
                  // get the while word
                  stream.eatWhile(/[\w\$_]/);
                  // is it one of the listed keywords?
                  if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
                    if (stream.eat(")") || stream.eat(".")) {
                      //keywords can be used as variables like flatten(group), group.$0 etc..
                    }
                    else {
                      return ("keyword", "keyword");
                    }
                  }
                  // is it one of the builtin functions?
                  if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))
                  {
                    return ("keyword", "variable-2");
                  }
                  // is it one of the listed types?
                  if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))
                    return ("keyword", "variable-3");
                  // default is a 'variable'
                  return ret("variable", "pig-word");
                }
              }
            
              // Interface
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  if(stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                }
              };
            });
            
            (function() {
              function keywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // builtin funcs taken from trunk revision 1303237
              var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
                + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
                + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
                + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
                + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
                + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
                + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  "
                + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
                + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
                + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER ";
            
              // taken from QueryLexer.g
              var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
                + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
                + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
                + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
                + "NEQ MATCHES TRUE FALSE DUMP";
            
              // data types
              var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP ";
            
              CodeMirror.defineMIME("text/x-pig", {
                name: "pig",
                builtins: keywords(pBuiltins),
                keywords: keywords(pKeywords),
                types: keywords(pTypes)
              });
            
              CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" "));
            }());
            
            });
            
        • properties
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Properties files mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="properties.js"></script>
            <style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Properties files</a>
              </ul>
            </div>
            
            <article>
            <h2>Properties files mode</h2>
            <form><textarea id="code" name="code">
            # This is a properties file
            a.key = A value
            another.key = http://example.com
            ! Exclamation mark as comment
            but.not=Within ! A value # indeed
               # Spaces at the beginning of a line
               spaces.before.key=value
            backslash=Used for multi\
                      line entries,\
                      that's convenient.
            # Unicode sequences
            unicode.key=This is \u0020 Unicode
            no.multiline=here
            # Colons
            colons : can be used too
            # Spaces
            spaces\ in\ keys=Not very common...
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-properties</code>,
                <code>text/x-ini</code>.</p>
            
              </article>
            
          • properties.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("properties", function() {
              return {
                token: function(stream, state) {
                  var sol = stream.sol() || state.afterSection;
                  var eol = stream.eol();
            
                  state.afterSection = false;
            
                  if (sol) {
                    if (state.nextMultiline) {
                      state.inMultiline = true;
                      state.nextMultiline = false;
                    } else {
                      state.position = "def";
                    }
                  }
            
                  if (eol && ! state.nextMultiline) {
                    state.inMultiline = false;
                    state.position = "def";
                  }
            
                  if (sol) {
                    while(stream.eatSpace());
                  }
            
                  var ch = stream.next();
            
                  if (sol && (ch === "#" || ch === "!" || ch === ";")) {
                    state.position = "comment";
                    stream.skipToEnd();
                    return "comment";
                  } else if (sol && ch === "[") {
                    state.afterSection = true;
                    stream.skipTo("]"); stream.eat("]");
                    return "header";
                  } else if (ch === "=" || ch === ":") {
                    state.position = "quote";
                    return null;
                  } else if (ch === "\\" && state.position === "quote") {
                    if (stream.next() !== "u") {    // u = Unicode sequence \u1234
                      // Multiline value
                      state.nextMultiline = true;
                    }
                  }
            
                  return state.position;
                },
            
                startState: function() {
                  return {
                    position : "def",       // Current position, "def", "quote" or "comment"
                    nextMultiline : false,  // Is the next line multiline value
                    inMultiline : false,    // Is the current line a multiline value
                    afterSection : false    // Did we just open a section
                  };
                }
            
              };
            });
            
            CodeMirror.defineMIME("text/x-properties", "properties");
            CodeMirror.defineMIME("text/x-ini", "properties");
            
            });
            
        • puppet
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Puppet mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="puppet.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Puppet</a>
              </ul>
            </div>
            
            <article>
            <h2>Puppet mode</h2>
            <form><textarea id="code" name="code">
            # == Class: automysqlbackup
            #
            # Puppet module to install AutoMySQLBackup for periodic MySQL backups.
            #
            # class { 'automysqlbackup':
            #   backup_dir => '/mnt/backups',
            # }
            #
            
            class automysqlbackup (
              $bin_dir = $automysqlbackup::params::bin_dir,
              $etc_dir = $automysqlbackup::params::etc_dir,
              $backup_dir = $automysqlbackup::params::backup_dir,
              $install_multicore = undef,
              $config = {},
              $config_defaults = {},
            ) inherits automysqlbackup::params {
            
            # Ensure valid paths are assigned
              validate_absolute_path($bin_dir)
              validate_absolute_path($etc_dir)
              validate_absolute_path($backup_dir)
            
            # Create a subdirectory in /etc for config files
              file { $etc_dir:
                ensure => directory,
                owner => 'root',
                group => 'root',
                mode => '0750',
              }
            
            # Create an example backup file, useful for reference
              file { "${etc_dir}/automysqlbackup.conf.example":
                ensure => file,
                owner => 'root',
                group => 'root',
                mode => '0660',
                source => 'puppet:///modules/automysqlbackup/automysqlbackup.conf',
              }
            
            # Add files from the developer
              file { "${etc_dir}/AMB_README":
                ensure => file,
                source => 'puppet:///modules/automysqlbackup/AMB_README',
              }
              file { "${etc_dir}/AMB_LICENSE":
                ensure => file,
                source => 'puppet:///modules/automysqlbackup/AMB_LICENSE',
              }
            
            # Install the actual binary file
              file { "${bin_dir}/automysqlbackup":
                ensure => file,
                owner => 'root',
                group => 'root',
                mode => '0755',
                source => 'puppet:///modules/automysqlbackup/automysqlbackup',
              }
            
            # Create the base backup directory
              file { $backup_dir:
                ensure => directory,
                owner => 'root',
                group => 'root',
                mode => '0755',
              }
            
            # If you'd like to keep your config in hiera and pass it to this class
              if !empty($config) {
                create_resources('automysqlbackup::backup', $config, $config_defaults)
              }
            
            # If using RedHat family, must have the RPMforge repo's enabled
              if $install_multicore {
                package { ['pigz', 'pbzip2']: ensure => installed }
              }
            
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-puppet",
                    matchBrackets: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-puppet</code>.</p>
            
              </article>
            
          • puppet.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("puppet", function () {
              // Stores the words from the define method
              var words = {};
              // Taken, mostly, from the Puppet official variable standards regex
              var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/;
            
              // Takes a string of words separated by spaces and adds them as
              // keys with the value of the first argument 'style'
              function define(style, string) {
                var split = string.split(' ');
                for (var i = 0; i < split.length; i++) {
                  words[split[i]] = style;
                }
              }
            
              // Takes commonly known puppet types/words and classifies them to a style
              define('keyword', 'class define site node include import inherits');
              define('keyword', 'case if else in and elsif default or');
              define('atom', 'false true running present absent file directory undef');
              define('builtin', 'action augeas burst chain computer cron destination dport exec ' +
                'file filebucket group host icmp iniface interface jump k5login limit log_level ' +
                'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' +
                'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' +
                'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' +
                'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' +
                'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' +
                'resources router schedule scheduled_task selboolean selmodule service source ' +
                'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' +
                'user vlan yumrepo zfs zone zpool');
            
              // After finding a start of a string ('|") this function attempts to find the end;
              // If a variable is encountered along the way, we display it differently when it
              // is encapsulated in a double-quoted string.
              function tokenString(stream, state) {
                var current, prev, found_var = false;
                while (!stream.eol() && (current = stream.next()) != state.pending) {
                  if (current === '$' && prev != '\\' && state.pending == '"') {
                    found_var = true;
                    break;
                  }
                  prev = current;
                }
                if (found_var) {
                  stream.backUp(1);
                }
                if (current == state.pending) {
                  state.continueString = false;
                } else {
                  state.continueString = true;
                }
                return "string";
              }
            
              // Main function
              function tokenize(stream, state) {
                // Matches one whole word
                var word = stream.match(/[\w]+/, false);
                // Matches attributes (i.e. ensure => present ; 'ensure' would be matched)
                var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false);
                // Matches non-builtin resource declarations
                // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched)
                var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false);
                // Matches virtual and exported resources (i.e. @@user { ; and the like)
                var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false);
            
                // Finally advance the stream
                var ch = stream.next();
            
                // Have we found a variable?
                if (ch === '$') {
                  if (stream.match(variable_regex)) {
                    // If so, and its in a string, assign it a different color
                    return state.continueString ? 'variable-2' : 'variable';
                  }
                  // Otherwise return an invalid variable
                  return "error";
                }
                // Should we still be looking for the end of a string?
                if (state.continueString) {
                  // If so, go through the loop again
                  stream.backUp(1);
                  return tokenString(stream, state);
                }
                // Are we in a definition (class, node, define)?
                if (state.inDefinition) {
                  // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched)
                  if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) {
                    return 'def';
                  }
                  // Match the rest it the next time around
                  stream.match(/\s+{/);
                  state.inDefinition = false;
                }
                // Are we in an 'include' statement?
                if (state.inInclude) {
                  // Match and return the included class
                  stream.match(/(\s+)?\S+(\s+)?/);
                  state.inInclude = false;
                  return 'def';
                }
                // Do we just have a function on our hands?
                // In 'ensure_resource("myclass")', 'ensure_resource' is matched
                if (stream.match(/(\s+)?\w+\(/)) {
                  stream.backUp(1);
                  return 'def';
                }
                // Have we matched the prior attribute regex?
                if (attribute) {
                  stream.match(/(\s+)?\w+/);
                  return 'tag';
                }
                // Do we have Puppet specific words?
                if (word && words.hasOwnProperty(word)) {
                  // Negates the initial next()
                  stream.backUp(1);
                  // Acutally move the stream
                  stream.match(/[\w]+/);
                  // We want to process these words differently
                  // do to the importance they have in Puppet
                  if (stream.match(/\s+\S+\s+{/, false)) {
                    state.inDefinition = true;
                  }
                  if (word == 'include') {
                    state.inInclude = true;
                  }
                  // Returns their value as state in the prior define methods
                  return words[word];
                }
                // Is there a match on a reference?
                if (/(^|\s+)[A-Z][\w:_]+/.test(word)) {
                  // Negate the next()
                  stream.backUp(1);
                  // Match the full reference
                  stream.match(/(^|\s+)[A-Z][\w:_]+/);
                  return 'def';
                }
                // Have we matched the prior resource regex?
                if (resource) {
                  stream.match(/(\s+)?[\w:_]+/);
                  return 'def';
                }
                // Have we matched the prior special_resource regex?
                if (special_resource) {
                  stream.match(/(\s+)?[@]{1,2}/);
                  return 'special';
                }
                // Match all the comments. All of them.
                if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                // Have we found a string?
                if (ch == "'" || ch == '"') {
                  // Store the type (single or double)
                  state.pending = ch;
                  // Perform the looping function to find the end
                  return tokenString(stream, state);
                }
                // Match all the brackets
                if (ch == '{' || ch == '}') {
                  return 'bracket';
                }
                // Match characters that we are going to assume
                // are trying to be regex
                if (ch == '/') {
                  stream.match(/.*?\//);
                  return 'variable-3';
                }
                // Match all the numbers
                if (ch.match(/[0-9]/)) {
                  stream.eatWhile(/[0-9]+/);
                  return 'number';
                }
                // Match the '=' and '=>' operators
                if (ch == '=') {
                  if (stream.peek() == '>') {
                      stream.next();
                  }
                  return "operator";
                }
                // Keep advancing through all the rest
                stream.eatWhile(/[\w-]/);
                // Return a blank line for everything else
                return null;
              }
              // Start it all
              return {
                startState: function () {
                  var state = {};
                  state.inDefinition = false;
                  state.inInclude = false;
                  state.continueString = false;
                  state.pending = false;
                  return state;
                },
                token: function (stream, state) {
                  // Strip the spaces, but regex will account for them eitherway
                  if (stream.eatSpace()) return null;
                  // Go through the main process
                  return tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-puppet", "puppet");
            
            });
            
        • python
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Python mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="python.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Python</a>
              </ul>
            </div>
            
            <article>
            <h2>Python mode</h2>
            
                <div><textarea id="code" name="code">
            # Literals
            1234
            0.0e101
            .123
            0b01010011100
            0o01234567
            0x0987654321abcdef
            7
            2147483647
            3L
            79228162514264337593543950336L
            0x100000000L
            79228162514264337593543950336
            0xdeadbeef
            3.14j
            10.j
            10j
            .001j
            1e100j
            3.14e-10j
            
            
            # String Literals
            'For\''
            "God\""
            """so loved
            the world"""
            '''that he gave
            his only begotten\' '''
            'that whosoever believeth \
            in him'
            ''
            
            # Identifiers
            __a__
            a.b
            a.b.c
            
            #Unicode identifiers on Python3
            # a = x\ddot
            a⃗ = ẍ
            # a = v\dot
            a⃗ = v̇
            
            #F\vec = m \cdot a\vec
            F⃗ = m•a⃗ 
            
            # Operators
            + - * / % & | ^ ~ < >
            == != <= >= <> << >> // **
            and or not in is
            
            #infix matrix multiplication operator (PEP 465)
            A @ B
            
            # Delimiters
            () [] {} , : ` = ; @ .  # Note that @ and . require the proper context on Python 2.
            += -= *= /= %= &= |= ^=
            //= >>= <<= **=
            
            # Keywords
            as assert break class continue def del elif else except
            finally for from global if import lambda pass raise
            return try while with yield
            
            # Python 2 Keywords (otherwise Identifiers)
            exec print
            
            # Python 3 Keywords (otherwise Identifiers)
            nonlocal
            
            # Types
            bool classmethod complex dict enumerate float frozenset int list object
            property reversed set slice staticmethod str super tuple type
            
            # Python 2 Types (otherwise Identifiers)
            basestring buffer file long unicode xrange
            
            # Python 3 Types (otherwise Identifiers)
            bytearray bytes filter map memoryview open range zip
            
            # Some Example code
            import os
            from package import ParentClass
            
            @nonsenseDecorator
            def doesNothing():
                pass
            
            class ExampleClass(ParentClass):
                @staticmethod
                def example(inputStr):
                    a = list(inputStr)
                    a.reverse()
                    return ''.join(a)
            
                def __init__(self, mixin = 'Hello'):
                    self.mixin = mixin
            
            </textarea></div>
            
            
            <h2>Cython mode</h2>
            
            <div><textarea id="code-cython" name="code-cython">
            
            import numpy as np
            cimport cython
            from libc.math cimport sqrt
            
            @cython.boundscheck(False)
            @cython.wraparound(False)
            def pairwise_cython(double[:, ::1] X):
                cdef int M = X.shape[0]
                cdef int N = X.shape[1]
                cdef double tmp, d
                cdef double[:, ::1] D = np.empty((M, M), dtype=np.float64)
                for i in range(M):
                    for j in range(M):
                        d = 0.0
                        for k in range(N):
                            tmp = X[i, k] - X[j, k]
                            d += tmp * tmp
                        D[i, j] = sqrt(d)
                return np.asarray(D)
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "python",
                           version: 3,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                });
            
                CodeMirror.fromTextArea(document.getElementById("code-cython"), {
                    mode: {name: "text/x-cython",
                           version: 2,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
                <h2>Configuration Options for Python mode:</h2>
                <ul>
                  <li>version - 2/3 - The version of Python to recognize.  Default is 2.</li>
                  <li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>
                  <li>hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.</li>
                </ul>
                <h2>Advanced Configuration Options:</h2>
                <p>Usefull for superset of python syntax like Enthought enaml, IPython magics and  questionmark help</p>
                <ul>
                  <li>singleOperators - RegEx - Regular Expression for single operator matching,  default : <pre>^[\\+\\-\\*/%&amp;|\\^~&lt;&gt;!]</pre> including <pre>@</pre> on Python 3</li>
                  <li>singleDelimiters - RegEx - Regular Expression for single delimiter matching, default :  <pre>^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]</pre></li>
                  <li>doubleOperators - RegEx - Regular Expression for double operators matching, default : <pre>^((==)|(!=)|(&lt;=)|(&gt;=)|(&lt;&gt;)|(&lt;&lt;)|(&gt;&gt;)|(//)|(\\*\\*))</pre></li>
                  <li>doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default : <pre>^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))</pre></li>
                  <li>tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default : <pre>^((//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\*\\*=))</pre></li>
                  <li>identifiers - RegEx - Regular Expression for identifier, default : <pre>^[_A-Za-z][_A-Za-z0-9]*</pre> on Python 2 and <pre>^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*</pre> on Python 3.</li>
                  <li>extra_keywords - list of string - List of extra words ton consider as keywords</li>
                  <li>extra_builtins - list of string - List of extra words ton consider as builtins</li>
                </ul>
            
            
                <p><strong>MIME types defined:</strong> <code>text/x-python</code> and <code>text/x-cython</code>.</p>
              </article>
            
          • python.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var wordOperators = wordRegexp(["and", "or", "not", "is"]);
              var commonKeywords = ["as", "assert", "break", "class", "continue",
                                    "def", "del", "elif", "else", "except", "finally",
                                    "for", "from", "global", "if", "import",
                                    "lambda", "pass", "raise", "return",
                                    "try", "while", "with", "yield", "in"];
              var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
                                    "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
                                    "enumerate", "eval", "filter", "float", "format", "frozenset",
                                    "getattr", "globals", "hasattr", "hash", "help", "hex", "id",
                                    "input", "int", "isinstance", "issubclass", "iter", "len",
                                    "list", "locals", "map", "max", "memoryview", "min", "next",
                                    "object", "oct", "open", "ord", "pow", "property", "range",
                                    "repr", "reversed", "round", "set", "setattr", "slice",
                                    "sorted", "staticmethod", "str", "sum", "super", "tuple",
                                    "type", "vars", "zip", "__import__", "NotImplemented",
                                    "Ellipsis", "__debug__"];
              var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
                                    "file", "intern", "long", "raw_input", "reduce", "reload",
                                    "unichr", "unicode", "xrange", "False", "True", "None"],
                         keywords: ["exec", "print"]};
              var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
                         keywords: ["nonlocal", "False", "True", "None"]};
            
              CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
            
              function top(state) {
                return state.scopes[state.scopes.length - 1];
              }
            
              CodeMirror.defineMode("python", function(conf, parserConf) {
                var ERRORCLASS = "error";
            
                var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
                var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
                var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
                var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
            
                if (parserConf.version && parseInt(parserConf.version, 10) == 3){
                    // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
                    var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]");
                    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*");
                } else {
                    var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
                    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
                }
            
                var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
            
                var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
                if(parserConf.extra_keywords != undefined){
                  myKeywords = myKeywords.concat(parserConf.extra_keywords);
                }
                if(parserConf.extra_builtins != undefined){
                  myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
                }
                if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
                  myKeywords = myKeywords.concat(py3.keywords);
                  myBuiltins = myBuiltins.concat(py3.builtins);
                  var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
                } else {
                  myKeywords = myKeywords.concat(py2.keywords);
                  myBuiltins = myBuiltins.concat(py2.builtins);
                  var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
                }
                var keywords = wordRegexp(myKeywords);
                var builtins = wordRegexp(myBuiltins);
            
                // tokenizers
                function tokenBase(stream, state) {
                  // Handle scope changes
                  if (stream.sol() && top(state).type == "py") {
                    var scopeOffset = top(state).offset;
                    if (stream.eatSpace()) {
                      var lineOffset = stream.indentation();
                      if (lineOffset > scopeOffset)
                        pushScope(stream, state, "py");
                      else if (lineOffset < scopeOffset && dedent(stream, state))
                        state.errorToken = true;
                      return null;
                    } else {
                      var style = tokenBaseInner(stream, state);
                      if (scopeOffset > 0 && dedent(stream, state))
                        style += " " + ERRORCLASS;
                      return style;
                    }
                  }
                  return tokenBaseInner(stream, state);
                }
            
                function tokenBaseInner(stream, state) {
                  if (stream.eatSpace()) return null;
            
                  var ch = stream.peek();
            
                  // Handle Comments
                  if (ch == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  // Handle Number Literals
                  if (stream.match(/^[0-9\.]/, false)) {
                    var floatLiteral = false;
                    // Floats
                    if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
                    if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
                    if (stream.match(/^\.\d+/)) { floatLiteral = true; }
                    if (floatLiteral) {
                      // Float literals may be "imaginary"
                      stream.eat(/J/i);
                      return "number";
                    }
                    // Integers
                    var intLiteral = false;
                    // Hex
                    if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true;
                    // Binary
                    if (stream.match(/^0b[01]+/i)) intLiteral = true;
                    // Octal
                    if (stream.match(/^0o[0-7]+/i)) intLiteral = true;
                    // Decimal
                    if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                      // Decimal literals may be "imaginary"
                      stream.eat(/J/i);
                      // TODO - Can you have imaginary longs?
                      intLiteral = true;
                    }
                    // Zero by itself with no other piece of number.
                    if (stream.match(/^0(?![\dx])/i)) intLiteral = true;
                    if (intLiteral) {
                      // Integer literals may be "long"
                      stream.eat(/L/i);
                      return "number";
                    }
                  }
            
                  // Handle Strings
                  if (stream.match(stringPrefixes)) {
                    state.tokenize = tokenStringFactory(stream.current());
                    return state.tokenize(stream, state);
                  }
            
                  // Handle operators and Delimiters
                  if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
                    return null;
            
                  if (stream.match(doubleOperators)
                      || stream.match(singleOperators)
                      || stream.match(wordOperators))
                    return "operator";
            
                  if (stream.match(singleDelimiters))
                    return null;
            
                  if (stream.match(keywords))
                    return "keyword";
            
                  if (stream.match(builtins))
                    return "builtin";
            
                  if (stream.match(/^(self|cls)\b/))
                    return "variable-2";
            
                  if (stream.match(identifiers)) {
                    if (state.lastToken == "def" || state.lastToken == "class")
                      return "def";
                    return "variable";
                  }
            
                  // Handle non-detected items
                  stream.next();
                  return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                  while ("rub".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
                    delimiter = delimiter.substr(1);
            
                  var singleline = delimiter.length == 1;
                  var OUTCLASS = "string";
            
                  function tokenString(stream, state) {
                    while (!stream.eol()) {
                      stream.eatWhile(/[^'"\\]/);
                      if (stream.eat("\\")) {
                        stream.next();
                        if (singleline && stream.eol())
                          return OUTCLASS;
                      } else if (stream.match(delimiter)) {
                        state.tokenize = tokenBase;
                        return OUTCLASS;
                      } else {
                        stream.eat(/['"]/);
                      }
                    }
                    if (singleline) {
                      if (parserConf.singleLineStringErrors)
                        return ERRORCLASS;
                      else
                        state.tokenize = tokenBase;
                    }
                    return OUTCLASS;
                  }
                  tokenString.isString = true;
                  return tokenString;
                }
            
                function pushScope(stream, state, type) {
                  var offset = 0, align = null;
                  if (type == "py") {
                    while (top(state).type != "py")
                      state.scopes.pop();
                  }
                  offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);
                  if (type != "py" && !stream.match(/^(\s|#.*)*$/, false))
                    align = stream.column() + 1;
                  state.scopes.push({offset: offset, type: type, align: align});
                }
            
                function dedent(stream, state) {
                  var indented = stream.indentation();
                  while (top(state).offset > indented) {
                    if (top(state).type != "py") return true;
                    state.scopes.pop();
                  }
                  return top(state).offset != indented;
                }
            
                function tokenLexer(stream, state) {
                  var style = state.tokenize(stream, state);
                  var current = stream.current();
            
                  // Handle '.' connected identifiers
                  if (current == ".") {
                    style = stream.match(identifiers, false) ? null : ERRORCLASS;
                    if (style == null && state.lastStyle == "meta") {
                      // Apply 'meta' style to '.' connected identifiers when
                      // appropriate.
                      style = "meta";
                    }
                    return style;
                  }
            
                  // Handle decorators
                  if (current == "@"){
                    if(parserConf.version && parseInt(parserConf.version, 10) == 3){
                        return stream.match(identifiers, false) ? "meta" : "operator";
                    } else {
                        return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
                    }
                  }
            
                  if ((style == "variable" || style == "builtin")
                      && state.lastStyle == "meta")
                    style = "meta";
            
                  // Handle scope changes.
                  if (current == "pass" || current == "return")
                    state.dedent += 1;
            
                  if (current == "lambda") state.lambda = true;
                  if (current == ":" && !state.lambda && top(state).type == "py")
                    pushScope(stream, state, "py");
            
                  var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
                  if (delimiter_index != -1)
                    pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
            
                  delimiter_index = "])}".indexOf(current);
                  if (delimiter_index != -1) {
                    if (top(state).type == current) state.scopes.pop();
                    else return ERRORCLASS;
                  }
                  if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
                    if (state.scopes.length > 1) state.scopes.pop();
                    state.dedent -= 1;
                  }
            
                  return style;
                }
            
                var external = {
                  startState: function(basecolumn) {
                    return {
                      tokenize: tokenBase,
                      scopes: [{offset: basecolumn || 0, type: "py", align: null}],
                      lastStyle: null,
                      lastToken: null,
                      lambda: false,
                      dedent: 0
                    };
                  },
            
                  token: function(stream, state) {
                    var addErr = state.errorToken;
                    if (addErr) state.errorToken = false;
                    var style = tokenLexer(stream, state);
            
                    state.lastStyle = style;
            
                    var current = stream.current();
                    if (current && style)
                      state.lastToken = current;
            
                    if (stream.eol() && state.lambda)
                      state.lambda = false;
                    return addErr ? style + " " + ERRORCLASS : style;
                  },
            
                  indent: function(state, textAfter) {
                    if (state.tokenize != tokenBase)
                      return state.tokenize.isString ? CodeMirror.Pass : 0;
            
                    var scope = top(state);
                    var closing = textAfter && textAfter.charAt(0) == scope.type;
                    if (scope.align != null)
                      return scope.align - (closing ? 1 : 0);
                    else if (closing && state.scopes.length > 1)
                      return state.scopes[state.scopes.length - 2].offset;
                    else
                      return scope.offset;
                  },
            
                  lineComment: "#",
                  fold: "indent"
                };
                return external;
              });
            
              CodeMirror.defineMIME("text/x-python", "python");
            
              var words = function(str) { return str.split(" "); };
            
              CodeMirror.defineMIME("text/x-cython", {
                name: "python",
                extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
                                      "extern gil include nogil property public"+
                                      "readonly struct union DEF IF ELIF ELSE")
              });
            
            });
            
        • q
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Q mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="q.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Q</a>
              </ul>
            </div>
            
            <article>
            <h2>Q mode</h2>
            
            
            <div><textarea id="code" name="code">
            / utilities to quickly load a csv file - for more exhaustive analysis of the csv contents see csvguess.q
            / 2009.09.20 - updated to match latest csvguess.q 
            
            / .csv.colhdrs[file] - return a list of colhdrs from file
            / info:.csv.info[file] - return a table of information about the file
            / columns are: 
            /	c - column name; ci - column index; t - load type; mw - max width; 
            /	dchar - distinct characters in values; rule - rule that caught the type
            /	maybe - needs checking, _could_ be say a date, but perhaps just a float?
            / .csv.info0[file;onlycols] - like .csv.info except that it only analyses <onlycols>
            / example:
            /	info:.csv.info0[file;(.csv.colhdrs file)like"*price"]
            /	info:.csv.infolike[file;"*price"]
            /	show delete from info where t=" "
            / .csv.data[file;info] - use the info from .csv.info to read the data
            / .csv.data10[file;info] - like .csv.data but only returns the first 10 rows
            / bulkload[file;info] - bulk loads file into table DATA (which must be already defined :: DATA:() )
            / .csv.read[file]/read10[file] - for when you don't care about checking/tweaking the <info> before reading 
            
            \d .csv
            DELIM:","
            ZAPHDRS:0b / lowercase and remove _ from colhdrs (junk characters are always removed)
            WIDTHHDR:25000 / number of characters read to get the header
            READLINES:222 / number of lines read and used to guess the types
            SYMMAXWIDTH:11 / character columns narrower than this are stored as symbols
            SYMMAXGR:10 / max symbol granularity% before we give up and keep as a * string
            FORCECHARWIDTH:30 / every field (of any type) with values this wide or more is forced to character "*"
            DISCARDEMPTY:0b / completely ignore empty columns if true else set them to "C"
            CHUNKSIZE:50000000 / used in fs2 (modified .Q.fs)
            
            k)nameltrim:{$[~@x;.z.s'x;~(*x)in aA:.Q.a,.Q.A;(+/&\~x in aA)_x;x]}
            k)fs2:{[f;s]((-7!s)>){[f;s;x]i:1+last@&0xa=r:1:(s;x;CHUNKSIZE);f@`\:i#r;x+i}[f;s]/0j}
            cleanhdrs:{{$[ZAPHDRS;lower x except"_";x]}x where x in DELIM,.Q.an}
            cancast:{nw:x$"";if[not x in"BXCS";nw:(min 0#;max 0#;::)@\:nw];$[not any nw in x$(11&count y)#y;$[11<count y;not any nw in x$y;1b];0b]}
            
            read:{[file]data[file;info[file]]}  
            read10:{[file]data10[file;info[file]]}  
            
            colhdrs:{[file]
            	`$nameltrim DELIM vs cleanhdrs first read0(file;0;1+first where 0xa=read1(file;0;WIDTHHDR))}
            data:{[file;info]
            	(exec c from info where not t=" ")xcol(exec t from info;enlist DELIM)0:file}
            data10:{[file;info]
            	data[;info](file;0;1+last 11#where 0xa=read1(file;0;15*WIDTHHDR))}
            info0:{[file;onlycols]
            	colhdrs:`$nameltrim DELIM vs cleanhdrs first head:read0(file;0;1+last where 0xa=read1(file;0;WIDTHHDR));
            	loadfmts:(count colhdrs)#"S";if[count onlycols;loadfmts[where not colhdrs in onlycols]:"C"];
            	breaks:where 0xa=read1(file;0;floor(10+READLINES)*WIDTHHDR%count head);
            	nas:count as:colhdrs xcol(loadfmts;enlist DELIM)0:(file;0;1+last((1+READLINES)&count breaks)#breaks);
            	info:([]c:key flip as;v:value flip as);as:();
            	reserved:key`.q;reserved,:.Q.res;reserved,:`i;
            	info:update res:c in reserved from info;
            	info:update ci:i,t:"?",ipa:0b,mdot:0,mw:0,rule:0,gr:0,ndv:0,maybe:0b,empty:0b,j10:0b,j12:0b from info;
            	info:update ci:`s#ci from info;
            	if[count onlycols;info:update t:" ",rule:10 from info where not c in onlycols];
            	info:update sdv:{string(distinct x)except`}peach v from info; 
            	info:update ndv:count each sdv from info;
            	info:update gr:floor 0.5+100*ndv%nas,mw:{max count each x}peach sdv from info where 0<ndv;
            	info:update t:"*",rule:20 from info where mw>.csv.FORCECHARWIDTH; / long values
            	info:update t:"C "[.csv.DISCARDEMPTY],rule:30,empty:1b from info where t="?",mw=0; / empty columns
            	info:update dchar:{asc distinct raze x}peach sdv from info where t="?";
            	info:update mdot:{max sum each"."=x}peach sdv from info where t="?",{"."in x}each dchar;
            	info:update t:"n",rule:40 from info where t="?",{any x in"0123456789"}each dchar; / vaguely numeric..
            	info:update t:"I",rule:50,ipa:1b from info where t="n",mw within 7 15,mdot=3,{all x in".0123456789"}each dchar,.csv.cancast["I"]peach sdv; / ip-address
            	info:update t:"J",rule:60 from info where t="n",mdot=0,{all x in"+-0123456789"}each dchar,.csv.cancast["J"]peach sdv;
            	info:update t:"I",rule:70 from info where t="J",mw<12,.csv.cancast["I"]peach sdv;
            	info:update t:"H",rule:80 from info where t="I",mw<7,.csv.cancast["H"]peach sdv;
            	info:update t:"F",rule:90 from info where t="n",mdot<2,mw>1,.csv.cancast["F"]peach sdv;
            	info:update t:"E",rule:100,maybe:1b from info where t="F",mw<9;
            	info:update t:"M",rule:110,maybe:1b from info where t in"nIHEF",mdot<2,mw within 4 7,.csv.cancast["M"]peach sdv; 
            	info:update t:"D",rule:120,maybe:1b from info where t in"nI",mdot in 0 2,mw within 6 11,.csv.cancast["D"]peach sdv; 
            	info:update t:"V",rule:130,maybe:1b from info where t="I",mw in 5 6,7<count each dchar,{all x like"*[0-9][0-5][0-9][0-5][0-9]"}peach sdv,.csv.cancast["V"]peach sdv; / 235959 12345        
            	info:update t:"U",rule:140,maybe:1b from info where t="H",mw in 3 4,7<count each dchar,{all x like"*[0-9][0-5][0-9]"}peach sdv,.csv.cancast["U"]peach sdv; /2359
            	info:update t:"U",rule:150,maybe:0b from info where t="n",mw in 4 5,mdot=0,{all x like"*[0-9]:[0-5][0-9]"}peach sdv,.csv.cancast["U"]peach sdv;
            	info:update t:"T",rule:160,maybe:0b from info where t="n",mw within 7 12,mdot<2,{all x like"*[0-9]:[0-5][0-9]:[0-5][0-9]*"}peach sdv,.csv.cancast["T"]peach sdv;
            	info:update t:"V",rule:170,maybe:0b from info where t="T",mw in 7 8,mdot=0,.csv.cancast["V"]peach sdv;
            	info:update t:"T",rule:180,maybe:1b from info where t in"EF",mw within 7 10,mdot=1,{all x like"*[0-9][0-5][0-9][0-5][0-9].*"}peach sdv,.csv.cancast["T"]peach sdv;
            	info:update t:"Z",rule:190,maybe:0b from info where t="n",mw within 11 24,mdot<4,.csv.cancast["Z"]peach sdv;
            	info:update t:"P",rule:200,maybe:1b from info where t="n",mw within 12 29,mdot<4,{all x like"[12]*"}peach sdv,.csv.cancast["P"]peach sdv;
            	info:update t:"N",rule:210,maybe:1b from info where t="n",mw within 3 28,mdot=1,.csv.cancast["N"]peach sdv;
            	info:update t:"?",rule:220,maybe:0b from info where t="n"; / reset remaining maybe numeric
            	info:update t:"C",rule:230,maybe:0b from info where t="?",mw=1; / char
            	info:update t:"B",rule:240,maybe:0b from info where t in"HC",mw=1,mdot=0,{$[all x in"01tTfFyYnN";(any"0fFnN"in x)and any"1tTyY"in x;0b]}each dchar; / boolean
            	info:update t:"B",rule:250,maybe:1b from info where t in"HC",mw=1,mdot=0,{all x in"01tTfFyYnN"}each dchar; / boolean
            	info:update t:"X",rule:260,maybe:0b from info where t="?",mw=2,{$[all x in"0123456789abcdefABCDEF";(any .Q.n in x)and any"abcdefABCDEF"in x;0b]}each dchar; /hex
            	info:update t:"S",rule:270,maybe:1b from info where t="?",mw<.csv.SYMMAXWIDTH,mw>1,gr<.csv.SYMMAXGR; / symbols (max width permitting)
            	info:update t:"*",rule:280,maybe:0b from info where t="?"; / the rest as strings
            	/ flag those S/* columns which could be encoded to integers (.Q.j10/x10/j12/x12) to avoid symbols
            	info:update j12:1b from info where t in"S*",mw<13,{all x in .Q.nA}each dchar;
            	info:update j10:1b from info where t in"S*",mw<11,{all x in .Q.b6}each dchar; 
            	select c,ci,t,maybe,empty,res,j10,j12,ipa,mw,mdot,rule,gr,ndv,dchar from info}
            info:info0[;()] / by default don't restrict columns
            infolike:{[file;pattern] info0[file;{x where x like y}[lower colhdrs[file];pattern]]} / .csv.infolike[file;"*time"]
            
            \d .
            / DATA:()
            bulkload:{[file;info]
            	if[not`DATA in system"v";'`DATA.not.defined];
            	if[count DATA;'`DATA.not.empty];
            	loadhdrs:exec c from info where not t=" ";loadfmts:exec t from info;
            	.csv.fs2[{[file;loadhdrs;loadfmts] `DATA insert $[count DATA;flip loadhdrs!(loadfmts;.csv.DELIM)0:file;loadhdrs xcol(loadfmts;enlist .csv.DELIM)0:file]}[file;loadhdrs;loadfmts]];
            	count DATA}
            @[.:;"\\l csvutil.custom.q";::]; / save your custom settings in csvutil.custom.q to override those set at the beginning of the file 
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME type defined:</strong> <code>text/x-q</code>.</p>
              </article>
            
          • q.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("q",function(config){
              var indentUnit=config.indentUnit,
                  curPunc,
                  keywords=buildRE(["abs","acos","aj","aj0","all","and","any","asc","asin","asof","atan","attr","avg","avgs","bin","by","ceiling","cols","cor","cos","count","cov","cross","csv","cut","delete","deltas","desc","dev","differ","distinct","div","do","each","ej","enlist","eval","except","exec","exit","exp","fby","fills","first","fkeys","flip","floor","from","get","getenv","group","gtime","hclose","hcount","hdel","hopen","hsym","iasc","idesc","if","ij","in","insert","inter","inv","key","keys","last","like","list","lj","load","log","lower","lsq","ltime","ltrim","mavg","max","maxs","mcount","md5","mdev","med","meta","min","mins","mmax","mmin","mmu","mod","msum","neg","next","not","null","or","over","parse","peach","pj","plist","prd","prds","prev","prior","rand","rank","ratios","raze","read0","read1","reciprocal","reverse","rload","rotate","rsave","rtrim","save","scan","select","set","setenv","show","signum","sin","sqrt","ss","ssr","string","sublist","sum","sums","sv","system","tables","tan","til","trim","txf","type","uj","ungroup","union","update","upper","upsert","value","var","view","views","vs","wavg","where","where","while","within","wj","wj1","wsum","xasc","xbar","xcol","xcols","xdesc","xexp","xgroup","xkey","xlog","xprev","xrank"]),
                  E=/[|/&^!+:\\\-*%$=~#;@><,?_\'\"\[\(\]\)\s{}]/;
              function buildRE(w){return new RegExp("^("+w.join("|")+")$");}
              function tokenBase(stream,state){
                var sol=stream.sol(),c=stream.next();
                curPunc=null;
                if(sol)
                  if(c=="/")
                    return(state.tokenize=tokenLineComment)(stream,state);
                  else if(c=="\\"){
                    if(stream.eol()||/\s/.test(stream.peek()))
                      return stream.skipToEnd(),/^\\\s*$/.test(stream.current())?(state.tokenize=tokenCommentToEOF)(stream, state):state.tokenize=tokenBase,"comment";
                    else
                      return state.tokenize=tokenBase,"builtin";
                  }
                if(/\s/.test(c))
                  return stream.peek()=="/"?(stream.skipToEnd(),"comment"):"whitespace";
                if(c=='"')
                  return(state.tokenize=tokenString)(stream,state);
                if(c=='`')
                  return stream.eatWhile(/[A-Z|a-z|\d|_|:|\/|\.]/),"symbol";
                if(("."==c&&/\d/.test(stream.peek()))||/\d/.test(c)){
                  var t=null;
                  stream.backUp(1);
                  if(stream.match(/^\d{4}\.\d{2}(m|\.\d{2}([D|T](\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)?)?)/)
                  || stream.match(/^\d+D(\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)/)
                  || stream.match(/^\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?/)
                  || stream.match(/^\d+[ptuv]{1}/))
                    t="temporal";
                  else if(stream.match(/^0[NwW]{1}/)
                  || stream.match(/^0x[\d|a-f|A-F]*/)
                  || stream.match(/^[0|1]+[b]{1}/)
                  || stream.match(/^\d+[chijn]{1}/)
                  || stream.match(/-?\d*(\.\d*)?(e[+\-]?\d+)?(e|f)?/))
                    t="number";
                  return(t&&(!(c=stream.peek())||E.test(c)))?t:(stream.next(),"error");
                }
                if(/[A-Z|a-z]|\./.test(c))
                  return stream.eatWhile(/[A-Z|a-z|\.|_|\d]/),keywords.test(stream.current())?"keyword":"variable";
                if(/[|/&^!+:\\\-*%$=~#;@><\.,?_\']/.test(c))
                  return null;
                if(/[{}\(\[\]\)]/.test(c))
                  return null;
                return"error";
              }
              function tokenLineComment(stream,state){
                return stream.skipToEnd(),/\/\s*$/.test(stream.current())?(state.tokenize=tokenBlockComment)(stream,state):(state.tokenize=tokenBase),"comment";
              }
              function tokenBlockComment(stream,state){
                var f=stream.sol()&&stream.peek()=="\\";
                stream.skipToEnd();
                if(f&&/^\\\s*$/.test(stream.current()))
                  state.tokenize=tokenBase;
                return"comment";
              }
              function tokenCommentToEOF(stream){return stream.skipToEnd(),"comment";}
              function tokenString(stream,state){
                var escaped=false,next,end=false;
                while((next=stream.next())){
                  if(next=="\""&&!escaped){end=true;break;}
                  escaped=!escaped&&next=="\\";
                }
                if(end)state.tokenize=tokenBase;
                return"string";
              }
              function pushContext(state,type,col){state.context={prev:state.context,indent:state.indent,col:col,type:type};}
              function popContext(state){state.indent=state.context.indent;state.context=state.context.prev;}
              return{
                startState:function(){
                  return{tokenize:tokenBase,
                         context:null,
                         indent:0,
                         col:0};
                },
                token:function(stream,state){
                  if(stream.sol()){
                    if(state.context&&state.context.align==null)
                      state.context.align=false;
                    state.indent=stream.indentation();
                  }
                  //if (stream.eatSpace()) return null;
                  var style=state.tokenize(stream,state);
                  if(style!="comment"&&state.context&&state.context.align==null&&state.context.type!="pattern"){
                    state.context.align=true;
                  }
                  if(curPunc=="(")pushContext(state,")",stream.column());
                  else if(curPunc=="[")pushContext(state,"]",stream.column());
                  else if(curPunc=="{")pushContext(state,"}",stream.column());
                  else if(/[\]\}\)]/.test(curPunc)){
                    while(state.context&&state.context.type=="pattern")popContext(state);
                    if(state.context&&curPunc==state.context.type)popContext(state);
                  }
                  else if(curPunc=="."&&state.context&&state.context.type=="pattern")popContext(state);
                  else if(/atom|string|variable/.test(style)&&state.context){
                    if(/[\}\]]/.test(state.context.type))
                      pushContext(state,"pattern",stream.column());
                    else if(state.context.type=="pattern"&&!state.context.align){
                      state.context.align=true;
                      state.context.col=stream.column();
                    }
                  }
                  return style;
                },
                indent:function(state,textAfter){
                  var firstChar=textAfter&&textAfter.charAt(0);
                  var context=state.context;
                  if(/[\]\}]/.test(firstChar))
                    while (context&&context.type=="pattern")context=context.prev;
                  var closing=context&&firstChar==context.type;
                  if(!context)
                    return 0;
                  else if(context.type=="pattern")
                    return context.col;
                  else if(context.align)
                    return context.col+(closing?0:1);
                  else
                    return context.indent+(closing?0:indentUnit);
                }
              };
            });
            CodeMirror.defineMIME("text/x-q","q");
            
            });
            
        • r
          • index.html
            <!doctype html>
            
            <title>CodeMirror: R mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="r.js"></script>
            <style>
                  .CodeMirror { border-top: 1px solid silver; border-bottom: 1px solid silver; }
                  .cm-s-default span.cm-semi { color: blue; font-weight: bold; }
                  .cm-s-default span.cm-dollar { color: orange; font-weight: bold; }
                  .cm-s-default span.cm-arrow { color: brown; }
                  .cm-s-default span.cm-arg-is { color: brown; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">R</a>
              </ul>
            </div>
            
            <article>
            <h2>R mode</h2>
            <form><textarea id="code" name="code">
            # Code from http://www.mayin.org/ajayshah/KB/R/
            
            # FIRST LEARN ABOUT LISTS --
            X = list(height=5.4, weight=54)
            print("Use default printing --")
            print(X)
            print("Accessing individual elements --")
            cat("Your height is ", X$height, " and your weight is ", X$weight, "\n")
            
            # FUNCTIONS --
            square <- function(x) {
              return(x*x)
            }
            cat("The square of 3 is ", square(3), "\n")
            
                             # default value of the arg is set to 5.
            cube <- function(x=5) {
              return(x*x*x);
            }
            cat("Calling cube with 2 : ", cube(2), "\n")    # will give 2^3
            cat("Calling cube        : ", cube(), "\n")     # will default to 5^3.
            
            # LEARN ABOUT FUNCTIONS THAT RETURN MULTIPLE OBJECTS --
            powers <- function(x) {
              parcel = list(x2=x*x, x3=x*x*x, x4=x*x*x*x);
              return(parcel);
            }
            
            X = powers(3);
            print("Showing powers of 3 --"); print(X);
            
            # WRITING THIS COMPACTLY (4 lines instead of 7)
            
            powerful <- function(x) {
              return(list(x2=x*x, x3=x*x*x, x4=x*x*x*x));
            }
            print("Showing powers of 3 --"); print(powerful(3));
            
            # In R, the last expression in a function is, by default, what is
            # returned. So you could equally just say:
            powerful <- function(x) {list(x2=x*x, x3=x*x*x, x4=x*x*x*x)}
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rsrc</code>.</p>
            
                <p>Development of the CodeMirror R mode was kindly sponsored
                by <a href="https://twitter.com/ubalo">Ubalo</a>.</p>
            
              </article>
            
          • r.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("r", function(config) {
              function wordObj(str) {
                var words = str.split(" "), res = {};
                for (var i = 0; i < words.length; ++i) res[words[i]] = true;
                return res;
              }
              var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_");
              var builtins = wordObj("list quote bquote eval return call parse deparse");
              var keywords = wordObj("if else repeat while function for in next break");
              var blockkeywords = wordObj("if else repeat while function for");
              var opChars = /[+\-*\/^<>=!&|~$:]/;
              var curPunc;
            
              function tokenBase(stream, state) {
                curPunc = null;
                var ch = stream.next();
                if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "0" && stream.eat("x")) {
                  stream.eatWhile(/[\da-f]/i);
                  return "number";
                } else if (ch == "." && stream.eat(/\d/)) {
                  stream.match(/\d*(?:e[+\-]?\d+)?/);
                  return "number";
                } else if (/\d/.test(ch)) {
                  stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/);
                  return "number";
                } else if (ch == "'" || ch == '"') {
                  state.tokenize = tokenString(ch);
                  return "string";
                } else if (ch == "." && stream.match(/.[.\d]+/)) {
                  return "keyword";
                } else if (/[\w\.]/.test(ch) && ch != "_") {
                  stream.eatWhile(/[\w\.]/);
                  var word = stream.current();
                  if (atoms.propertyIsEnumerable(word)) return "atom";
                  if (keywords.propertyIsEnumerable(word)) {
                    // Block keywords start new blocks, except 'else if', which only starts
                    // one new block for the 'if', no block for the 'else'.
                    if (blockkeywords.propertyIsEnumerable(word) &&
                        !stream.match(/\s*if(\s+|$)/, false))
                      curPunc = "block";
                    return "keyword";
                  }
                  if (builtins.propertyIsEnumerable(word)) return "builtin";
                  return "variable";
                } else if (ch == "%") {
                  if (stream.skipTo("%")) stream.next();
                  return "variable-2";
                } else if (ch == "<" && stream.eat("-")) {
                  return "arrow";
                } else if (ch == "=" && state.ctx.argList) {
                  return "arg-is";
                } else if (opChars.test(ch)) {
                  if (ch == "$") return "dollar";
                  stream.eatWhile(opChars);
                  return "operator";
                } else if (/[\(\){}\[\];]/.test(ch)) {
                  curPunc = ch;
                  if (ch == ";") return "semi";
                  return null;
                } else {
                  return null;
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  if (stream.eat("\\")) {
                    var ch = stream.next();
                    if (ch == "x") stream.match(/^[a-f0-9]{2}/i);
                    else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next();
                    else if (ch == "u") stream.match(/^[a-f0-9]{4}/i);
                    else if (ch == "U") stream.match(/^[a-f0-9]{8}/i);
                    else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);
                    return "string-2";
                  } else {
                    var next;
                    while ((next = stream.next()) != null) {
                      if (next == quote) { state.tokenize = tokenBase; break; }
                      if (next == "\\") { stream.backUp(1); break; }
                    }
                    return "string";
                  }
                };
              }
            
              function push(state, type, stream) {
                state.ctx = {type: type,
                             indent: state.indent,
                             align: null,
                             column: stream.column(),
                             prev: state.ctx};
              }
              function pop(state) {
                state.indent = state.ctx.indent;
                state.ctx = state.ctx.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          ctx: {type: "top",
                                indent: -config.indentUnit,
                                align: false},
                          indent: 0,
                          afterIdent: false};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.ctx.align == null) state.ctx.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (style != "comment" && state.ctx.align == null) state.ctx.align = true;
            
                  var ctype = state.ctx.type;
                  if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state);
                  if (curPunc == "{") push(state, "}", stream);
                  else if (curPunc == "(") {
                    push(state, ")", stream);
                    if (state.afterIdent) state.ctx.argList = true;
                  }
                  else if (curPunc == "[") push(state, "]", stream);
                  else if (curPunc == "block") push(state, "block", stream);
                  else if (curPunc == ctype) pop(state);
                  state.afterIdent = style == "variable" || style == "keyword";
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,
                      closing = firstChar == ctx.type;
                  if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indent + (closing ? 0 : config.indentUnit);
                },
            
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-rsrc", "r");
            
            });
            
        • rpm
          • changes
            • index.html
              <!doctype html>
              
              <title>CodeMirror: RPM changes mode</title>
              <meta charset="utf-8"/>
              <link rel=stylesheet href="../../doc/docs.css">
              
                  <link rel="stylesheet" href="../../../lib/codemirror.css">
                  <script src="../../../lib/codemirror.js"></script>
                  <script src="changes.js"></script>
                  <link rel="stylesheet" href="../../../doc/docs.css">
                  <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              
              <div id=nav>
                <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../../doc/logo.png"></a>
              
                <ul>
                  <li><a href="../../../index.html">Home</a>
                  <li><a href="../../../doc/manual.html">Manual</a>
                  <li><a href="https://github.com/codemirror/codemirror">Code</a>
                </ul>
                <ul>
                  <li><a href="../../index.html">Language modes</a>
                  <li><a class=active href="#">RPM changes</a>
                </ul>
              </div>
              
              <article>
              <h2>RPM changes mode</h2>
              
                  <div><textarea id="code" name="code">
              -------------------------------------------------------------------
              Tue Oct 18 13:58:40 UTC 2011 - misterx@example.com
              
              - Update to r60.3
              - Fixes bug in the reflect package
                * disallow Interface method on Value obtained via unexported name
              
              -------------------------------------------------------------------
              Thu Oct  6 08:14:24 UTC 2011 - misterx@example.com
              
              - Update to r60.2
              - Fixes memory leak in certain map types
              
              -------------------------------------------------------------------
              Wed Oct  5 14:34:10 UTC 2011 - misterx@example.com
              
              - Tweaks for gdb debugging
              - go.spec changes:
                - move %go_arch definition to %prep section
                - pass correct location of go specific gdb pretty printer and
                  functions to cpp as HOST_EXTRA_CFLAGS macro
                - install go gdb functions & printer
              - gdb-printer.patch
                - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go
                  gdb functions and pretty printer
              </textarea></div>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "changes"},
                      lineNumbers: true,
                      indentUnit: 4
                    });
                  </script>
              
                  <p><strong>MIME types defined:</strong> <code>text/x-rpm-changes</code>.</p>
              </article>
              
          • index.html
            <!doctype html>
            
            <title>CodeMirror: RPM changes mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="rpm.js"></script>
                <link rel="stylesheet" href="../../doc/docs.css">
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">RPM</a>
              </ul>
            </div>
            
            <article>
            <h2>RPM changes mode</h2>
            
                <div><textarea id="code" name="code">
            -------------------------------------------------------------------
            Tue Oct 18 13:58:40 UTC 2011 - misterx@example.com
            
            - Update to r60.3
            - Fixes bug in the reflect package
              * disallow Interface method on Value obtained via unexported name
            
            -------------------------------------------------------------------
            Thu Oct  6 08:14:24 UTC 2011 - misterx@example.com
            
            - Update to r60.2
            - Fixes memory leak in certain map types
            
            -------------------------------------------------------------------
            Wed Oct  5 14:34:10 UTC 2011 - misterx@example.com
            
            - Tweaks for gdb debugging
            - go.spec changes:
              - move %go_arch definition to %prep section
              - pass correct location of go specific gdb pretty printer and
                functions to cpp as HOST_EXTRA_CFLAGS macro
              - install go gdb functions & printer
            - gdb-printer.patch
              - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go
                gdb functions and pretty printer
            </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "rpm-changes"},
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
            <h2>RPM spec mode</h2>
                
                <div><textarea id="code2" name="code2">
            #
            # spec file for package minidlna
            #
            # Copyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>
            #
            # All modifications and additions to the file contributed by third parties
            # remain the property of their copyright owners, unless otherwise agreed
            # upon. The license for this file, and modifications and additions to the
            # file, is the same license as for the pristine package itself (unless the
            # license for the pristine package is not an Open Source License, in which
            # case the license is the MIT License). An "Open Source License" is a
            # license that conforms to the Open Source Definition (Version 1.9)
            # published by the Open Source Initiative.
            
            
            Name:           libupnp6
            Version:        1.6.13
            Release:        0
            Summary:        Portable Universal Plug and Play (UPnP) SDK
            Group:          System/Libraries
            License:        BSD-3-Clause
            Url:            http://sourceforge.net/projects/pupnp/
            Source0:        http://downloads.sourceforge.net/pupnp/libupnp-%{version}.tar.bz2
            BuildRoot:      %{_tmppath}/%{name}-%{version}-build
            
            %description
            The portable Universal Plug and Play (UPnP) SDK provides support for building
            UPnP-compliant control points, devices, and bridges on several operating
            systems.
            
            %package -n libupnp-devel
            Summary:        Portable Universal Plug and Play (UPnP) SDK
            Group:          Development/Libraries/C and C++
            Provides:       pkgconfig(libupnp)
            Requires:       %{name} = %{version}
            
            %description -n libupnp-devel
            The portable Universal Plug and Play (UPnP) SDK provides support for building
            UPnP-compliant control points, devices, and bridges on several operating
            systems.
            
            %prep
            %setup -n libupnp-%{version}
            
            %build
            %configure --disable-static
            make %{?_smp_mflags}
            
            %install
            %makeinstall
            find %{buildroot} -type f -name '*.la' -exec rm -f {} ';'
            
            %post -p /sbin/ldconfig
            
            %postun -p /sbin/ldconfig
            
            %files
            %defattr(-,root,root,-)
            %doc ChangeLog NEWS README TODO
            %{_libdir}/libixml.so.*
            %{_libdir}/libthreadutil.so.*
            %{_libdir}/libupnp.so.*
            
            %files -n libupnp-devel
            %defattr(-,root,root,-)
            %{_libdir}/pkgconfig/libupnp.pc
            %{_libdir}/libixml.so
            %{_libdir}/libthreadutil.so
            %{_libdir}/libupnp.so
            %{_includedir}/upnp/
            
            %changelog</textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
                    mode: {name: "rpm-spec"},
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rpm-spec</code>, <code>text/x-rpm-changes</code>.</p>
            </article>
            
          • rpm.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("rpm-changes", function() {
              var headerSeperator = /^-+$/;
              var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /;
              var simpleEmail = /^[\w+.-]+@[\w.-]+/;
            
              return {
                token: function(stream) {
                  if (stream.sol()) {
                    if (stream.match(headerSeperator)) { return 'tag'; }
                    if (stream.match(headerLine)) { return 'tag'; }
                  }
                  if (stream.match(simpleEmail)) { return 'string'; }
                  stream.next();
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes");
            
            // Quick and dirty spec file highlighting
            
            CodeMirror.defineMode("rpm-spec", function() {
              var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
            
              var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
              var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
              var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
              var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
              var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
            
              return {
                startState: function () {
                    return {
                      controlFlow: false,
                      macroParameters: false,
                      section: false
                    };
                },
                token: function (stream, state) {
                  var ch = stream.peek();
                  if (ch == "#") { stream.skipToEnd(); return "comment"; }
            
                  if (stream.sol()) {
                    if (stream.match(preamble)) { return "preamble"; }
                    if (stream.match(section)) { return "section"; }
                  }
            
                  if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
                  if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}'
            
                  if (stream.match(control_flow_simple)) { return "keyword"; }
                  if (stream.match(control_flow_complex)) {
                    state.controlFlow = true;
                    return "keyword";
                  }
                  if (state.controlFlow) {
                    if (stream.match(operators)) { return "operator"; }
                    if (stream.match(/^(\d+)/)) { return "number"; }
                    if (stream.eol()) { state.controlFlow = false; }
                  }
            
                  if (stream.match(arch)) { return "number"; }
            
                  // Macros like '%make_install' or '%attr(0775,root,root)'
                  if (stream.match(/^%[\w]+/)) {
                    if (stream.match(/^\(/)) { state.macroParameters = true; }
                    return "macro";
                  }
                  if (state.macroParameters) {
                    if (stream.match(/^\d+/)) { return "number";}
                    if (stream.match(/^\)/)) {
                      state.macroParameters = false;
                      return "macro";
                    }
                  }
                  if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'
            
                  //TODO: Include bash script sub-parser (CodeMirror supports that)
                  stream.next();
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec");
            
            });
            
        • rst
          • index.html
            <!doctype html>
            
            <title>CodeMirror: reStructuredText mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="rst.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">reStructuredText</a>
              </ul>
            </div>
            
            <article>
            <h2>reStructuredText mode</h2>
            <form><textarea id="code" name="code">
            .. This is an excerpt from Sphinx documentation: http://sphinx.pocoo.org/_sources/rest.txt
            
            .. highlightlang:: rest
            
            .. _rst-primer:
            
            reStructuredText Primer
            =======================
            
            This section is a brief introduction to reStructuredText (reST) concepts and
            syntax, intended to provide authors with enough information to author documents
            productively.  Since reST was designed to be a simple, unobtrusive markup
            language, this will not take too long.
            
            .. seealso::
            
               The authoritative `reStructuredText User Documentation
               &lt;http://docutils.sourceforge.net/rst.html&gt;`_.  The "ref" links in this
               document link to the description of the individual constructs in the reST
               reference.
            
            
            Paragraphs
            ----------
            
            The paragraph (:duref:`ref &lt;paragraphs&gt;`) is the most basic block in a reST
            document.  Paragraphs are simply chunks of text separated by one or more blank
            lines.  As in Python, indentation is significant in reST, so all lines of the
            same paragraph must be left-aligned to the same level of indentation.
            
            
            .. _inlinemarkup:
            
            Inline markup
            -------------
            
            The standard reST inline markup is quite simple: use
            
            * one asterisk: ``*text*`` for emphasis (italics),
            * two asterisks: ``**text**`` for strong emphasis (boldface), and
            * backquotes: ````text```` for code samples.
            
            If asterisks or backquotes appear in running text and could be confused with
            inline markup delimiters, they have to be escaped with a backslash.
            
            Be aware of some restrictions of this markup:
            
            * it may not be nested,
            * content may not start or end with whitespace: ``* text*`` is wrong,
            * it must be separated from surrounding text by non-word characters.  Use a
              backslash escaped space to work around that: ``thisis\ *one*\ word``.
            
            These restrictions may be lifted in future versions of the docutils.
            
            reST also allows for custom "interpreted text roles"', which signify that the
            enclosed text should be interpreted in a specific way.  Sphinx uses this to
            provide semantic markup and cross-referencing of identifiers, as described in
            the appropriate section.  The general syntax is ``:rolename:`content```.
            
            Standard reST provides the following roles:
            
            * :durole:`emphasis` -- alternate spelling for ``*emphasis*``
            * :durole:`strong` -- alternate spelling for ``**strong**``
            * :durole:`literal` -- alternate spelling for ````literal````
            * :durole:`subscript` -- subscript text
            * :durole:`superscript` -- superscript text
            * :durole:`title-reference` -- for titles of books, periodicals, and other
              materials
            
            See :ref:`inline-markup` for roles added by Sphinx.
            
            
            Lists and Quote-like blocks
            ---------------------------
            
            List markup (:duref:`ref &lt;bullet-lists&gt;`) is natural: just place an asterisk at
            the start of a paragraph and indent properly.  The same goes for numbered lists;
            they can also be autonumbered using a ``#`` sign::
            
               * This is a bulleted list.
               * It has two items, the second
                 item uses two lines.
            
               1. This is a numbered list.
               2. It has two items too.
            
               #. This is a numbered list.
               #. It has two items too.
            
            
            Nested lists are possible, but be aware that they must be separated from the
            parent list items by blank lines::
            
               * this is
               * a list
            
                 * with a nested list
                 * and some subitems
            
               * and here the parent list continues
            
            Definition lists (:duref:`ref &lt;definition-lists&gt;`) are created as follows::
            
               term (up to a line of text)
                  Definition of the term, which must be indented
            
                  and can even consist of multiple paragraphs
            
               next term
                  Description.
            
            Note that the term cannot have more than one line of text.
            
            Quoted paragraphs (:duref:`ref &lt;block-quotes&gt;`) are created by just indenting
            them more than the surrounding paragraphs.
            
            Line blocks (:duref:`ref &lt;line-blocks&gt;`) are a way of preserving line breaks::
            
               | These lines are
               | broken exactly like in
               | the source file.
            
            There are also several more special blocks available:
            
            * field lists (:duref:`ref &lt;field-lists&gt;`)
            * option lists (:duref:`ref &lt;option-lists&gt;`)
            * quoted literal blocks (:duref:`ref &lt;quoted-literal-blocks&gt;`)
            * doctest blocks (:duref:`ref &lt;doctest-blocks&gt;`)
            
            
            Source Code
            -----------
            
            Literal code blocks (:duref:`ref &lt;literal-blocks&gt;`) are introduced by ending a
            paragraph with the special marker ``::``.  The literal block must be indented
            (and, like all paragraphs, separated from the surrounding ones by blank lines)::
            
               This is a normal text paragraph. The next paragraph is a code sample::
            
                  It is not processed in any way, except
                  that the indentation is removed.
            
                  It can span multiple lines.
            
               This is a normal text paragraph again.
            
            The handling of the ``::`` marker is smart:
            
            * If it occurs as a paragraph of its own, that paragraph is completely left
              out of the document.
            * If it is preceded by whitespace, the marker is removed.
            * If it is preceded by non-whitespace, the marker is replaced by a single
              colon.
            
            That way, the second sentence in the above example's first paragraph would be
            rendered as "The next paragraph is a code sample:".
            
            
            .. _rst-tables:
            
            Tables
            ------
            
            Two forms of tables are supported.  For *grid tables* (:duref:`ref
            &lt;grid-tables&gt;`), you have to "paint" the cell grid yourself.  They look like
            this::
            
               +------------------------+------------+----------+----------+
               | Header row, column 1   | Header 2   | Header 3 | Header 4 |
               | (header rows optional) |            |          |          |
               +========================+============+==========+==========+
               | body row 1, column 1   | column 2   | column 3 | column 4 |
               +------------------------+------------+----------+----------+
               | body row 2             | ...        | ...      |          |
               +------------------------+------------+----------+----------+
            
            *Simple tables* (:duref:`ref &lt;simple-tables&gt;`) are easier to write, but
            limited: they must contain more than one row, and the first column cannot
            contain multiple lines.  They look like this::
            
               =====  =====  =======
               A      B      A and B
               =====  =====  =======
               False  False  False
               True   False  False
               False  True   False
               True   True   True
               =====  =====  =======
            
            
            Hyperlinks
            ----------
            
            External links
            ^^^^^^^^^^^^^^
            
            Use ```Link text &lt;http://example.com/&gt;`_`` for inline web links.  If the link
            text should be the web address, you don't need special markup at all, the parser
            finds links and mail addresses in ordinary text.
            
            You can also separate the link and the target definition (:duref:`ref
            &lt;hyperlink-targets&gt;`), like this::
            
               This is a paragraph that contains `a link`_.
            
               .. _a link: http://example.com/
            
            
            Internal links
            ^^^^^^^^^^^^^^
            
            Internal linking is done via a special reST role provided by Sphinx, see the
            section on specific markup, :ref:`ref-role`.
            
            
            Sections
            --------
            
            Section headers (:duref:`ref &lt;sections&gt;`) are created by underlining (and
            optionally overlining) the section title with a punctuation character, at least
            as long as the text::
            
               =================
               This is a heading
               =================
            
            Normally, there are no heading levels assigned to certain characters as the
            structure is determined from the succession of headings.  However, for the
            Python documentation, this convention is used which you may follow:
            
            * ``#`` with overline, for parts
            * ``*`` with overline, for chapters
            * ``=``, for sections
            * ``-``, for subsections
            * ``^``, for subsubsections
            * ``"``, for paragraphs
            
            Of course, you are free to use your own marker characters (see the reST
            documentation), and use a deeper nesting level, but keep in mind that most
            target formats (HTML, LaTeX) have a limited supported nesting depth.
            
            
            Explicit Markup
            ---------------
            
            "Explicit markup" (:duref:`ref &lt;explicit-markup-blocks&gt;`) is used in reST for
            most constructs that need special handling, such as footnotes,
            specially-highlighted paragraphs, comments, and generic directives.
            
            An explicit markup block begins with a line starting with ``..`` followed by
            whitespace and is terminated by the next paragraph at the same level of
            indentation.  (There needs to be a blank line between explicit markup and normal
            paragraphs.  This may all sound a bit complicated, but it is intuitive enough
            when you write it.)
            
            
            .. _directives:
            
            Directives
            ----------
            
            A directive (:duref:`ref &lt;directives&gt;`) is a generic block of explicit markup.
            Besides roles, it is one of the extension mechanisms of reST, and Sphinx makes
            heavy use of it.
            
            Docutils supports the following directives:
            
            * Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,
              :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,
              :dudir:`tip`, :dudir:`warning` and the generic :dudir:`admonition`.
              (Most themes style only "note" and "warning" specially.)
            
            * Images:
            
              - :dudir:`image` (see also Images_ below)
              - :dudir:`figure` (an image with caption and optional legend)
            
            * Additional body elements:
            
              - :dudir:`contents` (a local, i.e. for the current file only, table of
                contents)
              - :dudir:`container` (a container with a custom class, useful to generate an
                outer ``&lt;div&gt;`` in HTML)
              - :dudir:`rubric` (a heading without relation to the document sectioning)
              - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)
              - :dudir:`parsed-literal` (literal block that supports inline markup)
              - :dudir:`epigraph` (a block quote with optional attribution line)
              - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own
                class attribute)
              - :dudir:`compound` (a compound paragraph)
            
            * Special tables:
            
              - :dudir:`table` (a table with title)
              - :dudir:`csv-table` (a table generated from comma-separated values)
              - :dudir:`list-table` (a table generated from a list of lists)
            
            * Special directives:
            
              - :dudir:`raw` (include raw target-format markup)
              - :dudir:`include` (include reStructuredText from another file)
                -- in Sphinx, when given an absolute include file path, this directive takes
                it as relative to the source directory
              - :dudir:`class` (assign a class attribute to the next element) [1]_
            
            * HTML specifics:
            
              - :dudir:`meta` (generation of HTML ``&lt;meta&gt;`` tags)
              - :dudir:`title` (override document title)
            
            * Influencing markup:
            
              - :dudir:`default-role` (set a new default role)
              - :dudir:`role` (create a new role)
            
              Since these are only per-file, better use Sphinx' facilities for setting the
              :confval:`default_role`.
            
            Do *not* use the directives :dudir:`sectnum`, :dudir:`header` and
            :dudir:`footer`.
            
            Directives added by Sphinx are described in :ref:`sphinxmarkup`.
            
            Basically, a directive consists of a name, arguments, options and content. (Keep
            this terminology in mind, it is used in the next chapter describing custom
            directives.)  Looking at this example, ::
            
               .. function:: foo(x)
                             foo(y, z)
                  :module: some.module.name
            
                  Return a line of text input from the user.
            
            ``function`` is the directive name.  It is given two arguments here, the
            remainder of the first line and the second line, as well as one option
            ``module`` (as you can see, options are given in the lines immediately following
            the arguments and indicated by the colons).  Options must be indented to the
            same level as the directive content.
            
            The directive content follows after a blank line and is indented relative to the
            directive start.
            
            
            Images
            ------
            
            reST supports an image directive (:dudir:`ref &lt;image&gt;`), used like so::
            
               .. image:: gnu.png
                  (options)
            
            When used within Sphinx, the file name given (here ``gnu.png``) must either be
            relative to the source file, or absolute which means that they are relative to
            the top source directory.  For example, the file ``sketch/spam.rst`` could refer
            to the image ``images/spam.png`` as ``../images/spam.png`` or
            ``/images/spam.png``.
            
            Sphinx will automatically copy image files over to a subdirectory of the output
            directory on building (e.g. the ``_static`` directory for HTML output.)
            
            Interpretation of image size options (``width`` and ``height``) is as follows:
            if the size has no unit or the unit is pixels, the given size will only be
            respected for output channels that support pixels (i.e. not in LaTeX output).
            Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
            
            Sphinx extends the standard docutils behavior by allowing an asterisk for the
            extension::
            
               .. image:: gnu.*
            
            Sphinx then searches for all images matching the provided pattern and determines
            their type.  Each builder then chooses the best image out of these candidates.
            For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
            and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
            the former, while the HTML builder would prefer the latter.
            
            .. versionchanged:: 0.4
               Added the support for file names ending in an asterisk.
            
            .. versionchanged:: 0.6
               Image paths can now be absolute.
            
            
            Footnotes
            ---------
            
            For footnotes (:duref:`ref &lt;footnotes&gt;`), use ``[#name]_`` to mark the footnote
            location, and add the footnote body at the bottom of the document after a
            "Footnotes" rubric heading, like so::
            
               Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
            
               .. rubric:: Footnotes
            
               .. [#f1] Text of the first footnote.
               .. [#f2] Text of the second footnote.
            
            You can also explicitly number the footnotes (``[1]_``) or use auto-numbered
            footnotes without names (``[#]_``).
            
            
            Citations
            ---------
            
            Standard reST citations (:duref:`ref &lt;citations&gt;`) are supported, with the
            additional feature that they are "global", i.e. all citations can be referenced
            from all files.  Use them like so::
            
               Lorem ipsum [Ref]_ dolor sit amet.
            
               .. [Ref] Book or article reference, URL or whatever.
            
            Citation usage is similar to footnote usage, but with a label that is not
            numeric or begins with ``#``.
            
            
            Substitutions
            -------------
            
            reST supports "substitutions" (:duref:`ref &lt;substitution-definitions&gt;`), which
            are pieces of text and/or markup referred to in the text by ``|name|``.  They
            are defined like footnotes with explicit markup blocks, like this::
            
               .. |name| replace:: replacement *text*
            
            or this::
            
               .. |caution| image:: warning.png
                            :alt: Warning!
            
            See the :duref:`reST reference for substitutions &lt;substitution-definitions&gt;`
            for details.
            
            If you want to use some substitutions for all documents, put them into
            :confval:`rst_prolog` or put them into a separate file and include it into all
            documents you want to use them in, using the :rst:dir:`include` directive.  (Be
            sure to give the include file a file name extension differing from that of other
            source files, to avoid Sphinx finding it as a standalone document.)
            
            Sphinx defines some default substitutions, see :ref:`default-substitutions`.
            
            
            Comments
            --------
            
            Every explicit markup block which isn't a valid markup construct (like the
            footnotes above) is regarded as a comment (:duref:`ref &lt;comments&gt;`).  For
            example::
            
               .. This is a comment.
            
            You can indent text after a comment start to form multiline comments::
            
               ..
                  This whole indented block
                  is a comment.
            
                  Still in the comment.
            
            
            Source encoding
            ---------------
            
            Since the easiest way to include special characters like em dashes or copyright
            signs in reST is to directly write them as Unicode characters, one has to
            specify an encoding.  Sphinx assumes source files to be encoded in UTF-8 by
            default; you can change this with the :confval:`source_encoding` config value.
            
            
            Gotchas
            -------
            
            There are some problems one commonly runs into while authoring reST documents:
            
            * **Separation of inline markup:** As said above, inline markup spans must be
              separated from the surrounding text by non-word characters, you have to use a
              backslash-escaped space to get around that.  See `the reference
              &lt;http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup&gt;`_
              for the details.
            
            * **No nested inline markup:** Something like ``*see :func:`foo`*`` is not
              possible.
            
            
            .. rubric:: Footnotes
            
            .. [1] When the default domain contains a :rst:dir:`class` directive, this directive
                   will be shadowed.  Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                  });
                </script>
                <p>
                    The <code>python</code> mode will be used for highlighting blocks
                    containing Python/IPython terminal sessions: blocks starting with
                    <code>&gt;&gt;&gt;</code> (for Python) or <code>In [num]:</code> (for
                    IPython).
            
                    Further, the <code>stex</code> mode will be used for highlighting
                    blocks containing LaTex code.
                </p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>
              </article>
            
          • rst.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('rst', function (config, options) {
            
              var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/;
              var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/;
              var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/;
            
              var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
              var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
              var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;
            
              var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://";
              var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})";
              var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*";
              var rx_uri = new RegExp("^" + rx_uri_protocol + rx_uri_domain + rx_uri_path);
            
              var overlay = {
                token: function (stream) {
            
                  if (stream.match(rx_strong) && stream.match (/\W+|$/, false))
                    return 'strong';
                  if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false))
                    return 'em';
                  if (stream.match(rx_literal) && stream.match (/\W+|$/, false))
                    return 'string-2';
                  if (stream.match(rx_number))
                    return 'number';
                  if (stream.match(rx_positive))
                    return 'positive';
                  if (stream.match(rx_negative))
                    return 'negative';
                  if (stream.match(rx_uri))
                    return 'link';
            
                  while (stream.next() != null) {
                    if (stream.match(rx_strong, false)) break;
                    if (stream.match(rx_emphasis, false)) break;
                    if (stream.match(rx_literal, false)) break;
                    if (stream.match(rx_number, false)) break;
                    if (stream.match(rx_positive, false)) break;
                    if (stream.match(rx_negative, false)) break;
                    if (stream.match(rx_uri, false)) break;
                  }
            
                  return null;
                }
              };
            
              var mode = CodeMirror.getMode(
                config, options.backdrop || 'rst-base'
              );
            
              return CodeMirror.overlayMode(mode, overlay, true); // combine
            }, 'python', 'stex');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            CodeMirror.defineMode('rst-base', function (config) {
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function format(string) {
                var args = Array.prototype.slice.call(arguments, 1);
                return string.replace(/{(\d+)}/g, function (match, n) {
                  return typeof args[n] != 'undefined' ? args[n] : match;
                });
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              var mode_python = CodeMirror.getMode(config, 'python');
              var mode_stex = CodeMirror.getMode(config, 'stex');
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              var SEPA = "\\s+";
              var TAIL = "(?:\\s*|\\W|$)",
              rx_TAIL = new RegExp(format('^{0}', TAIL));
            
              var NAME =
                "(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)",
              rx_NAME = new RegExp(format('^{0}', NAME));
              var NAME_WWS =
                "(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)";
              var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);
            
              var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)";
              var TEXT2 = "(?:[^\\`]+)",
              rx_TEXT2 = new RegExp(format('^{0}', TEXT2));
            
              var rx_section = new RegExp(
                "^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$");
              var rx_explicit = new RegExp(
                format('^\\.\\.{0}', SEPA));
              var rx_link = new RegExp(
                format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL));
              var rx_directive = new RegExp(
                format('^{0}::{1}', REF_NAME, TAIL));
              var rx_substitution = new RegExp(
                format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL));
              var rx_footnote = new RegExp(
                format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL));
              var rx_citation = new RegExp(
                format('^\\[{0}\\]{1}', REF_NAME, TAIL));
            
              var rx_substitution_ref = new RegExp(
                format('^\\|{0}\\|', TEXT1));
              var rx_footnote_ref = new RegExp(
                format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME));
              var rx_citation_ref = new RegExp(
                format('^\\[{0}\\]_', REF_NAME));
              var rx_link_ref1 = new RegExp(
                format('^{0}__?', REF_NAME));
              var rx_link_ref2 = new RegExp(
                format('^`{0}`_', TEXT2));
            
              var rx_role_pre = new RegExp(
                format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL));
              var rx_role_suf = new RegExp(
                format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL));
              var rx_role = new RegExp(
                format('^:{0}:{1}', NAME, TAIL));
            
              var rx_directive_name = new RegExp(format('^{0}', REF_NAME));
              var rx_directive_tail = new RegExp(format('^::{0}', TAIL));
              var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1));
              var rx_substitution_sepa = new RegExp(format('^{0}', SEPA));
              var rx_substitution_name = new RegExp(format('^{0}', REF_NAME));
              var rx_substitution_tail = new RegExp(format('^::{0}', TAIL));
              var rx_link_head = new RegExp("^_");
              var rx_link_name = new RegExp(format('^{0}|_', REF_NAME));
              var rx_link_tail = new RegExp(format('^:{0}', TAIL));
            
              var rx_verbatim = new RegExp('^::\\s*$');
              var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s');
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_normal(stream, state) {
                var token = null;
            
                if (stream.sol() && stream.match(rx_examples, false)) {
                  change(state, to_mode, {
                    mode: mode_python, local: CodeMirror.startState(mode_python)
                  });
                } else if (stream.sol() && stream.match(rx_explicit)) {
                  change(state, to_explicit);
                  token = 'meta';
                } else if (stream.sol() && stream.match(rx_section)) {
                  change(state, to_normal);
                  token = 'header';
                } else if (phase(state) == rx_role_pre ||
                           stream.match(rx_role_pre, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role_pre, 1));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role_pre, 2));
                    stream.match(rx_NAME);
                    token = 'keyword';
            
                    if (stream.current().match(/^(?:math|latex)/)) {
                      state.tmp_stex = true;
                    }
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role_pre, 3));
                    stream.match(/^:`/);
                    token = 'meta';
                    break;
                  case 3:
                    if (state.tmp_stex) {
                      state.tmp_stex = undefined; state.tmp = {
                        mode: mode_stex, local: CodeMirror.startState(mode_stex)
                      };
                    }
            
                    if (state.tmp) {
                      if (stream.peek() == '`') {
                        change(state, to_normal, context(rx_role_pre, 4));
                        state.tmp = undefined;
                        break;
                      }
            
                      token = state.tmp.mode.token(stream, state.tmp.local);
                      break;
                    }
            
                    change(state, to_normal, context(rx_role_pre, 4));
                    stream.match(rx_TEXT2);
                    token = 'string';
                    break;
                  case 4:
                    change(state, to_normal, context(rx_role_pre, 5));
                    stream.match(/^`/);
                    token = 'meta';
                    break;
                  case 5:
                    change(state, to_normal, context(rx_role_pre, 6));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_role_suf ||
                           stream.match(rx_role_suf, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role_suf, 1));
                    stream.match(/^`/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role_suf, 2));
                    stream.match(rx_TEXT2);
                    token = 'string';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role_suf, 3));
                    stream.match(/^`:/);
                    token = 'meta';
                    break;
                  case 3:
                    change(state, to_normal, context(rx_role_suf, 4));
                    stream.match(rx_NAME);
                    token = 'keyword';
                    break;
                  case 4:
                    change(state, to_normal, context(rx_role_suf, 5));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 5:
                    change(state, to_normal, context(rx_role_suf, 6));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_role || stream.match(rx_role, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role, 1));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role, 2));
                    stream.match(rx_NAME);
                    token = 'keyword';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role, 3));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 3:
                    change(state, to_normal, context(rx_role, 4));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_substitution_ref ||
                           stream.match(rx_substitution_ref, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_substitution_ref, 1));
                    stream.match(rx_substitution_text);
                    token = 'variable-2';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_substitution_ref, 2));
                    if (stream.match(/^_?_?/)) token = 'link';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_footnote_ref)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_citation_ref)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_link_ref1)) {
                  change(state, to_normal);
                  if (!stream.peek() || stream.peek().match(/^\W$/)) {
                    token = 'link';
                  }
                } else if (phase(state) == rx_link_ref2 ||
                           stream.match(rx_link_ref2, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    if (!stream.peek() || stream.peek().match(/^\W$/)) {
                      change(state, to_normal, context(rx_link_ref2, 1));
                    } else {
                      stream.match(rx_link_ref2);
                    }
                    break;
                  case 1:
                    change(state, to_normal, context(rx_link_ref2, 2));
                    stream.match(/^`/);
                    token = 'link';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_link_ref2, 3));
                    stream.match(rx_TEXT2);
                    break;
                  case 3:
                    change(state, to_normal, context(rx_link_ref2, 4));
                    stream.match(/^`_/);
                    token = 'link';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_verbatim)) {
                  change(state, to_verbatim);
                }
            
                else {
                  if (stream.next()) change(state, to_normal);
                }
            
                return token;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_explicit(stream, state) {
                var token = null;
            
                if (phase(state) == rx_substitution ||
                    stream.match(rx_substitution, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_substitution, 1));
                    stream.match(rx_substitution_text);
                    token = 'variable-2';
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_substitution, 2));
                    stream.match(rx_substitution_sepa);
                    break;
                  case 2:
                    change(state, to_explicit, context(rx_substitution, 3));
                    stream.match(rx_substitution_name);
                    token = 'keyword';
                    break;
                  case 3:
                    change(state, to_explicit, context(rx_substitution, 4));
                    stream.match(rx_substitution_tail);
                    token = 'meta';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_directive ||
                           stream.match(rx_directive, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_directive, 1));
                    stream.match(rx_directive_name);
                    token = 'keyword';
            
                    if (stream.current().match(/^(?:math|latex)/))
                      state.tmp_stex = true;
                    else if (stream.current().match(/^python/))
                      state.tmp_py = true;
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_directive, 2));
                    stream.match(rx_directive_tail);
                    token = 'meta';
            
                    if (stream.match(/^latex\s*$/) || state.tmp_stex) {
                      state.tmp_stex = undefined; change(state, to_mode, {
                        mode: mode_stex, local: CodeMirror.startState(mode_stex)
                      });
                    }
                    break;
                  case 2:
                    change(state, to_explicit, context(rx_directive, 3));
                    if (stream.match(/^python\s*$/) || state.tmp_py) {
                      state.tmp_py = undefined; change(state, to_mode, {
                        mode: mode_python, local: CodeMirror.startState(mode_python)
                      });
                    }
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_link || stream.match(rx_link, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_link, 1));
                    stream.match(rx_link_head);
                    stream.match(rx_link_name);
                    token = 'link';
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_link, 2));
                    stream.match(rx_link_tail);
                    token = 'meta';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_footnote)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_citation)) {
                  change(state, to_normal);
                  token = 'quote';
                }
            
                else {
                  stream.eatSpace();
                  if (stream.eol()) {
                    change(state, to_normal);
                  } else {
                    stream.skipToEnd();
                    change(state, to_comment);
                    token = 'comment';
                  }
                }
            
                return token;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_comment(stream, state) {
                return as_block(stream, state, 'comment');
              }
            
              function to_verbatim(stream, state) {
                return as_block(stream, state, 'meta');
              }
            
              function as_block(stream, state, token) {
                if (stream.eol() || stream.eatSpace()) {
                  stream.skipToEnd();
                  return token;
                } else {
                  change(state, to_normal);
                  return null;
                }
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_mode(stream, state) {
            
                if (state.ctx.mode && state.ctx.local) {
            
                  if (stream.sol()) {
                    if (!stream.eatSpace()) change(state, to_normal);
                    return null;
                  }
            
                  return state.ctx.mode.token(stream, state.ctx.local);
                }
            
                change(state, to_normal);
                return null;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function context(phase, stage, mode, local) {
                return {phase: phase, stage: stage, mode: mode, local: local};
              }
            
              function change(state, tok, ctx) {
                state.tok = tok;
                state.ctx = ctx || {};
              }
            
              function stage(state) {
                return state.ctx.stage || 0;
              }
            
              function phase(state) {
                return state.ctx.phase;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              return {
                startState: function () {
                  return {tok: to_normal, ctx: context(undefined, 0)};
                },
            
                copyState: function (state) {
                  var ctx = state.ctx, tmp = state.tmp;
                  if (ctx.local)
                    ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)};
                  if (tmp)
                    tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)};
                  return {tok: state.tok, ctx: ctx, tmp: tmp};
                },
            
                innerMode: function (state) {
                  return state.tmp      ? {state: state.tmp.local, mode: state.tmp.mode}
                  : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode}
                  : null;
                },
            
                token: function (stream, state) {
                  return state.tok(stream, state);
                }
              };
            }, 'python', 'stex');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            CodeMirror.defineMIME('text/x-rst', 'rst');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            });
            
        • ruby
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Ruby mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="ruby.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Ruby</a>
              </ul>
            </div>
            
            <article>
            <h2>Ruby mode</h2>
            <form><textarea id="code" name="code">
            # Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
            #
            # This program evaluates polynomials.  It first asks for the coefficients
            # of a polynomial, which must be entered on one line, highest-order first.
            # It then requests values of x and will compute the value of the poly for
            # each x.  It will repeatly ask for x values, unless you the user enters
            # a blank line.  It that case, it will ask for another polynomial.  If the
            # user types quit for either input, the program immediately exits.
            #
            
            #
            # Function to evaluate a polynomial at x.  The polynomial is given
            # as a list of coefficients, from the greatest to the least.
            def polyval(x, coef)
                sum = 0
                coef = coef.clone           # Don't want to destroy the original
                while true
                    sum += coef.shift       # Add and remove the next coef
                    break if coef.empty?    # If no more, done entirely.
                    sum *= x                # This happens the right number of times.
                end
                return sum
            end
            
            #
            # Function to read a line containing a list of integers and return
            # them as an array of integers.  If the string conversion fails, it
            # throws TypeError.  If the input line is the word 'quit', then it
            # converts it to an end-of-file exception
            def readints(prompt)
                # Read a line
                print prompt
                line = readline.chomp
                raise EOFError.new if line == 'quit' # You can also use a real EOF.
                        
                # Go through each item on the line, converting each one and adding it
                # to retval.
                retval = [ ]
                for str in line.split(/\s+/)
                    if str =~ /^\-?\d+$/
                        retval.push(str.to_i)
                    else
                        raise TypeError.new
                    end
                end
            
                return retval
            end
            
            #
            # Take a coeff and an exponent and return the string representation, ignoring
            # the sign of the coefficient.
            def term_to_str(coef, exp)
                ret = ""
            
                # Show coeff, unless it's 1 or at the right
                coef = coef.abs
                ret = coef.to_s     unless coef == 1 && exp > 0
                ret += "x" if exp > 0                               # x if exponent not 0
                ret += "^" + exp.to_s if exp > 1                    # ^exponent, if > 1.
            
                return ret
            end
            
            #
            # Create a string of the polynomial in sort-of-readable form.
            def polystr(p)
                # Get the exponent of first coefficient, plus 1.
                exp = p.length
            
                # Assign exponents to each term, making pairs of coeff and exponent,
                # Then get rid of the zero terms.
                p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }
            
                # If there's nothing left, it's a zero
                return "0" if p.empty?
            
                # *** Now p is a non-empty list of [ coef, exponent ] pairs. ***
            
                # Convert the first term, preceded by a "-" if it's negative.
                result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])
            
                # Convert the rest of the terms, in each case adding the appropriate
                # + or - separating them.  
                for term in p[1...p.length]
                    # Add the separator then the rep. of the term.
                    result += (if term[0] < 0 then " - " else " + " end) + 
                            term_to_str(*term)
                end
            
                return result
            end
                    
            #
            # Run until some kind of endfile.
            begin
                # Repeat until an exception or quit gets us out.
                while true
                    # Read a poly until it works.  An EOF will except out of the
                    # program.
                    print "\n"
                    begin
                        poly = readints("Enter a polynomial coefficients: ")
                    rescue TypeError
                        print "Try again.\n"
                        retry
                    end
                    break if poly.empty?
            
                    # Read and evaluate x values until the user types a blank line.
                    # Again, an EOF will except out of the pgm.
                    while true
                        # Request an integer.
                        print "Enter x value or blank line: "
                        x = readline.chomp
                        break if x == ''
                        raise EOFError.new if x == 'quit'
            
                        # If it looks bad, let's try again.
                        if x !~ /^\-?\d+$/
                            print "That doesn't look like an integer.  Please try again.\n"
                            next
                        end
            
                        # Convert to an integer and print the result.
                        x = x.to_i
                        print "p(x) = ", polystr(poly), "\n"
                        print "p(", x, ") = ", polyval(x, poly), "\n"
                    end
                end
            rescue EOFError
                print "\n=== EOF ===\n"
            rescue Interrupt, SignalException
                print "\n=== Interrupted ===\n"
            else
                print "--- Bye ---\n"
            end
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-ruby",
                    matchBrackets: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>
            
                <p>Development of the CodeMirror Ruby mode was kindly sponsored
                by <a href="http://ubalo.com/">Ubalo</a>.</p>
            
              </article>
            
          • ruby.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ruby", function(config) {
              function wordObj(words) {
                var o = {};
                for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
                return o;
              }
              var keywords = wordObj([
                "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
                "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
                "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
                "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
                "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
                "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
              ]);
              var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then",
                                         "catch", "loop", "proc", "begin"]);
              var dedentWords = wordObj(["end", "until"]);
              var matching = {"[": "]", "{": "}", "(": ")"};
              var curPunc;
            
              function chain(newtok, stream, state) {
                state.tokenize.push(newtok);
                return newtok(stream, state);
              }
            
              function tokenBase(stream, state) {
                curPunc = null;
                if (stream.sol() && stream.match("=begin") && stream.eol()) {
                  state.tokenize.push(readBlockComment);
                  return "comment";
                }
                if (stream.eatSpace()) return null;
                var ch = stream.next(), m;
                if (ch == "`" || ch == "'" || ch == '"') {
                  return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
                } else if (ch == "/") {
                  var currentIndex = stream.current().length;
                  if (stream.skipTo("/")) {
                    var search_till = stream.current().length;
                    stream.backUp(stream.current().length - currentIndex);
                    var balance = 0;  // balance brackets
                    while (stream.current().length < search_till) {
                      var chchr = stream.next();
                      if (chchr == "(") balance += 1;
                      else if (chchr == ")") balance -= 1;
                      if (balance < 0) break;
                    }
                    stream.backUp(stream.current().length - currentIndex);
                    if (balance == 0)
                      return chain(readQuoted(ch, "string-2", true), stream, state);
                  }
                  return "operator";
                } else if (ch == "%") {
                  var style = "string", embed = true;
                  if (stream.eat("s")) style = "atom";
                  else if (stream.eat(/[WQ]/)) style = "string";
                  else if (stream.eat(/[r]/)) style = "string-2";
                  else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; }
                  var delim = stream.eat(/[^\w\s=]/);
                  if (!delim) return "operator";
                  if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
                  return chain(readQuoted(delim, style, embed, true), stream, state);
                } else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "<" && (m = stream.match(/^<-?[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) {
                  return chain(readHereDoc(m[1]), stream, state);
                } else if (ch == "0") {
                  if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
                  else if (stream.eat("b")) stream.eatWhile(/[01]/);
                  else stream.eatWhile(/[0-7]/);
                  return "number";
                } else if (/\d/.test(ch)) {
                  stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
                  return "number";
                } else if (ch == "?") {
                  while (stream.match(/^\\[CM]-/)) {}
                  if (stream.eat("\\")) stream.eatWhile(/\w/);
                  else stream.next();
                  return "string";
                } else if (ch == ":") {
                  if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
                  if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
            
                  // :> :>> :< :<< are valid symbols
                  if (stream.eat(/[\<\>]/)) {
                    stream.eat(/[\<\>]/);
                    return "atom";
                  }
            
                  // :+ :- :/ :* :| :& :! are valid symbols
                  if (stream.eat(/[\+\-\*\/\&\|\:\!]/)) {
                    return "atom";
                  }
            
                  // Symbols can't start by a digit
                  if (stream.eat(/[a-zA-Z$@_\xa1-\uffff]/)) {
                    stream.eatWhile(/[\w$\xa1-\uffff]/);
                    // Only one ? ! = is allowed and only as the last character
                    stream.eat(/[\?\!\=]/);
                    return "atom";
                  }
                  return "operator";
                } else if (ch == "@" && stream.match(/^@?[a-zA-Z_\xa1-\uffff]/)) {
                  stream.eat("@");
                  stream.eatWhile(/[\w\xa1-\uffff]/);
                  return "variable-2";
                } else if (ch == "$") {
                  if (stream.eat(/[a-zA-Z_]/)) {
                    stream.eatWhile(/[\w]/);
                  } else if (stream.eat(/\d/)) {
                    stream.eat(/\d/);
                  } else {
                    stream.next(); // Must be a special global like $: or $!
                  }
                  return "variable-3";
                } else if (/[a-zA-Z_\xa1-\uffff]/.test(ch)) {
                  stream.eatWhile(/[\w\xa1-\uffff]/);
                  stream.eat(/[\?\!]/);
                  if (stream.eat(":")) return "atom";
                  return "ident";
                } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
                  curPunc = "|";
                  return null;
                } else if (/[\(\)\[\]{}\\;]/.test(ch)) {
                  curPunc = ch;
                  return null;
                } else if (ch == "-" && stream.eat(">")) {
                  return "arrow";
                } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
                  var more = stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
                  if (ch == "." && !more) curPunc = ".";
                  return "operator";
                } else {
                  return null;
                }
              }
            
              function tokenBaseUntilBrace(depth) {
                if (!depth) depth = 1;
                return function(stream, state) {
                  if (stream.peek() == "}") {
                    if (depth == 1) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length-1](stream, state);
                    } else {
                      state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1);
                    }
                  } else if (stream.peek() == "{") {
                    state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1);
                  }
                  return tokenBase(stream, state);
                };
              }
              function tokenBaseOnce() {
                var alreadyCalled = false;
                return function(stream, state) {
                  if (alreadyCalled) {
                    state.tokenize.pop();
                    return state.tokenize[state.tokenize.length-1](stream, state);
                  }
                  alreadyCalled = true;
                  return tokenBase(stream, state);
                };
              }
              function readQuoted(quote, style, embed, unescaped) {
                return function(stream, state) {
                  var escaped = false, ch;
            
                  if (state.context.type === 'read-quoted-paused') {
                    state.context = state.context.prev;
                    stream.eat("}");
                  }
            
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && (unescaped || !escaped)) {
                      state.tokenize.pop();
                      break;
                    }
                    if (embed && ch == "#" && !escaped) {
                      if (stream.eat("{")) {
                        if (quote == "}") {
                          state.context = {prev: state.context, type: 'read-quoted-paused'};
                        }
                        state.tokenize.push(tokenBaseUntilBrace());
                        break;
                      } else if (/[@\$]/.test(stream.peek())) {
                        state.tokenize.push(tokenBaseOnce());
                        break;
                      }
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return style;
                };
              }
              function readHereDoc(phrase) {
                return function(stream, state) {
                  if (stream.match(phrase)) state.tokenize.pop();
                  else stream.skipToEnd();
                  return "string";
                };
              }
              function readBlockComment(stream, state) {
                if (stream.sol() && stream.match("=end") && stream.eol())
                  state.tokenize.pop();
                stream.skipToEnd();
                return "comment";
              }
            
              return {
                startState: function() {
                  return {tokenize: [tokenBase],
                          indented: 0,
                          context: {type: "top", indented: -config.indentUnit},
                          continuedLine: false,
                          lastTok: null,
                          varList: false};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) state.indented = stream.indentation();
                  var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
                  var thisTok = curPunc;
                  if (style == "ident") {
                    var word = stream.current();
                    style = state.lastTok == "." ? "property"
                      : keywords.propertyIsEnumerable(stream.current()) ? "keyword"
                      : /^[A-Z]/.test(word) ? "tag"
                      : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
                      : "variable";
                    if (style == "keyword") {
                      thisTok = word;
                      if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
                      else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
                      else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
                        kwtype = "indent";
                      else if (word == "do" && state.context.indented < state.indented)
                        kwtype = "indent";
                    }
                  }
                  if (curPunc || (style && style != "comment")) state.lastTok = thisTok;
                  if (curPunc == "|") state.varList = !state.varList;
            
                  if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
                    state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
                  else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
                    state.context = state.context.prev;
            
                  if (stream.eol())
                    state.continuedLine = (curPunc == "\\" || style == "operator");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0);
                  var ct = state.context;
                  var closing = ct.type == matching[firstChar] ||
                    ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
                  return ct.indented + (closing ? 0 : config.indentUnit) +
                    (state.continuedLine ? config.indentUnit : 0);
                },
            
                electricChars: "}de", // enD and rescuE
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-ruby", "ruby");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "ruby");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("divide_equal_operator",
                 "[variable bar] [operator /=] [variable foo]");
            
              MT("divide_equal_operator_no_spacing",
                 "[variable foo][operator /=][number 42]");
            
            })();
            
        • rust
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Rust mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="rust.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Rust</a>
              </ul>
            </div>
            
            <article>
            <h2>Rust mode</h2>
            
            
            <div><textarea id="code" name="code">
            // Demo code.
            
            type foo<T> = int;
            enum bar {
                some(int, foo<float>),
                none
            }
            
            fn check_crate(x: int) {
                let v = 10;
                alt foo {
                  1 to 3 {
                    print_foo();
                    if x {
                        blah() + 10;
                    }
                  }
                  (x, y) { "bye" }
                  _ { "hi" }
                }
            }
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rustsrc</code>.</p>
              </article>
            
          • rust.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("rust", function() {
              var indentUnit = 4, altIndentUnit = 2;
              var valKeywords = {
                "if": "if-style", "while": "if-style", "loop": "else-style", "else": "else-style",
                "do": "else-style", "ret": "else-style", "fail": "else-style",
                "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
                "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",
                "impl": "impl", "type": "type", "enum": "enum", "mod": "mod",
                "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
                "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
                "export": "else-style", "copy": "op", "log": "op", "log_err": "op",
                "use": "op", "bind": "op", "self": "atom", "struct": "enum"
              };
              var typeKeywords = function() {
                var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
                var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
                for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
                return keywords;
              }();
              var operatorChar = /[+\-*&%=<>!?|\.@]/;
            
              // Tokenizer
            
              // Used as scratch variable to communicate multiple values without
              // consing up tons of objects.
              var tcat, content;
              function r(tc, style) {
                tcat = tc;
                return style;
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
                }
                if (ch == "'") {
                  tcat = "atom";
                  if (stream.eat("\\")) {
                    if (stream.skipTo("'")) { stream.next(); return "string"; }
                    else { return "error"; }
                  } else {
                    stream.next();
                    return stream.eat("'") ? "string" : "error";
                  }
                }
                if (ch == "/") {
                  if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment(1);
                    return state.tokenize(stream, state);
                  }
                }
                if (ch == "#") {
                  if (stream.eat("[")) { tcat = "open-attr"; return null; }
                  stream.eatWhile(/\w/);
                  return r("macro", "meta");
                }
                if (ch == ":" && stream.match(":<")) {
                  return r("op", null);
                }
                if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
                  var flp = false;
                  if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
                    stream.eatWhile(/\d/);
                    if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
                    if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
                  }
                  if (flp) stream.match(/^f(?:32|64)/);
                  else stream.match(/^[ui](?:8|16|32|64)/);
                  return r("atom", "number");
                }
                if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
                if (ch == "-" && stream.eat(">")) return r("->", null);
                if (ch.match(operatorChar)) {
                  stream.eatWhile(operatorChar);
                  return r("op", null);
                }
                stream.eatWhile(/\w/);
                content = stream.current();
                if (stream.match(/^::\w/)) {
                  stream.backUp(1);
                  return r("prefix", "variable-2");
                }
                if (state.keywords.propertyIsEnumerable(content))
                  return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword");
                return r("name", "variable");
              }
            
              function tokenString(stream, state) {
                var ch, escaped = false;
                while (ch = stream.next()) {
                  if (ch == '"' && !escaped) {
                    state.tokenize = tokenBase;
                    return r("atom", "string");
                  }
                  escaped = !escaped && ch == "\\";
                }
                // Hack to not confuse the parser when a string is split in
                // pieces.
                return r("op", "string");
              }
            
              function tokenComment(depth) {
                return function(stream, state) {
                  var lastCh = null, ch;
                  while (ch = stream.next()) {
                    if (ch == "/" && lastCh == "*") {
                      if (depth == 1) {
                        state.tokenize = tokenBase;
                        break;
                      } else {
                        state.tokenize = tokenComment(depth - 1);
                        return state.tokenize(stream, state);
                      }
                    }
                    if (ch == "*" && lastCh == "/") {
                      state.tokenize = tokenComment(depth + 1);
                      return state.tokenize(stream, state);
                    }
                    lastCh = ch;
                  }
                  return "comment";
                };
              }
            
              // Parser
            
              var cx = {state: null, stream: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
            
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state;
                  state.lexical = {indented: state.indented, column: cx.stream.column(),
                                   type: type, prev: state.lexical, info: info};
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              function typecx() { cx.state.keywords = typeKeywords; }
              function valcx() { cx.state.keywords = valKeywords; }
              poplex.lex = typecx.lex = valcx.lex = true;
            
              function commasep(comb, end) {
                function more(type) {
                  if (type == ",") return cont(comb, more);
                  if (type == end) return cont();
                  return cont(more);
                }
                return function(type) {
                  if (type == end) return cont();
                  return pass(comb, more);
                };
              }
            
              function stat_of(comb, tag) {
                return cont(pushlex("stat", tag), comb, poplex, block);
              }
              function block(type) {
                if (type == "}") return cont();
                if (type == "let") return stat_of(letdef1, "let");
                if (type == "fn") return stat_of(fndef);
                if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
                if (type == "enum") return stat_of(enumdef);
                if (type == "mod") return stat_of(mod);
                if (type == "iface") return stat_of(iface);
                if (type == "impl") return stat_of(impl);
                if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
                if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block);
                return pass(pushlex("stat"), expression, poplex, endstatement, block);
              }
              function endstatement(type) {
                if (type == ";") return cont();
                return pass();
              }
              function expression(type) {
                if (type == "atom" || type == "name") return cont(maybeop);
                if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
                if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
                if (type.match(/[\]\)\};,]/)) return pass();
                if (type == "if-style") return cont(expression, expression);
                if (type == "else-style" || type == "op") return cont(expression);
                if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
                if (type == "alt") return cont(expression, altbody);
                if (type == "fn") return cont(fndef);
                if (type == "macro") return cont(macro);
                return cont();
              }
              function maybeop(type) {
                if (content == ".") return cont(maybeprop);
                if (content == "::<"){return cont(typarams, maybeop);}
                if (type == "op" || content == ":") return cont(expression);
                if (type == "(" || type == "[") return matchBrackets(type, expression);
                return pass();
              }
              function maybeprop() {
                if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
                return pass(expression);
              }
              function exprbrace(type) {
                if (type == "op") {
                  if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
                  if (content == "||") return cont(poplex, pushlex("}", "block"), block);
                }
                if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
                                             && !cx.stream.match("::", false)))
                  return pass(record_of(expression));
                return pass(block);
              }
              function record_of(comb) {
                function ro(type) {
                  if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);}
                  if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);}
                  if (type == ":") return cont(comb, ro);
                  if (type == "}") return cont();
                  return cont(ro);
                }
                return ro;
              }
              function blockvars(type) {
                if (type == "name") {cx.marked = "def"; return cont(blockvars);}
                if (type == "op" && content == "|") return cont();
                return cont(blockvars);
              }
            
              function letdef1(type) {
                if (type.match(/[\]\)\};]/)) return cont();
                if (content == "=") return cont(expression, letdef2);
                if (type == ",") return cont(letdef1);
                return pass(pattern, maybetype, letdef1);
              }
              function letdef2(type) {
                if (type.match(/[\]\)\};,]/)) return pass(letdef1);
                else return pass(expression, letdef2);
              }
              function maybetype(type) {
                if (type == ":") return cont(typecx, rtype, valcx);
                return pass();
              }
              function inop(type) {
                if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
                return pass();
              }
              function fndef(type) {
                if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);}
                if (type == "name") {cx.marked = "def"; return cont(fndef);}
                if (content == "<") return cont(typarams, fndef);
                if (type == "{") return pass(expression);
                if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
                if (type == "->") return cont(typecx, rtype, valcx, fndef);
                if (type == ";") return cont();
                return cont(fndef);
              }
              function tydef(type) {
                if (type == "name") {cx.marked = "def"; return cont(tydef);}
                if (content == "<") return cont(typarams, tydef);
                if (content == "=") return cont(typecx, rtype, valcx);
                return cont(tydef);
              }
              function enumdef(type) {
                if (type == "name") {cx.marked = "def"; return cont(enumdef);}
                if (content == "<") return cont(typarams, enumdef);
                if (content == "=") return cont(typecx, rtype, valcx, endstatement);
                if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex);
                return cont(enumdef);
              }
              function enumblock(type) {
                if (type == "}") return cont();
                if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock);
                if (content.match(/^\w+$/)) cx.marked = "def";
                return cont(enumblock);
              }
              function mod(type) {
                if (type == "name") {cx.marked = "def"; return cont(mod);}
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function iface(type) {
                if (type == "name") {cx.marked = "def"; return cont(iface);}
                if (content == "<") return cont(typarams, iface);
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function impl(type) {
                if (content == "<") return cont(typarams, impl);
                if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);}
                if (type == "name") {cx.marked = "def"; return cont(impl);}
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function typarams() {
                if (content == ">") return cont();
                if (content == ",") return cont(typarams);
                if (content == ":") return cont(rtype, typarams);
                return pass(rtype, typarams);
              }
              function argdef(type) {
                if (type == "name") {cx.marked = "def"; return cont(argdef);}
                if (type == ":") return cont(typecx, rtype, valcx);
                return pass();
              }
              function rtype(type) {
                if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
                if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
                if (type == "atom") return cont(rtypemaybeparam);
                if (type == "op" || type == "obj") return cont(rtype);
                if (type == "fn") return cont(fntype);
                if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
                return matchBrackets(type, rtype);
              }
              function rtypemaybeparam() {
                if (content == "<") return cont(typarams);
                return pass();
              }
              function fntype(type) {
                if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
                if (type == "->") return cont(rtype);
                return pass();
              }
              function pattern(type) {
                if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
                if (type == "atom") return cont(patternmaybeop);
                if (type == "op") return cont(pattern);
                if (type.match(/[\]\)\};,]/)) return pass();
                return matchBrackets(type, pattern);
              }
              function patternmaybeop(type) {
                if (type == "op" && content == ".") return cont();
                if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
                else return pass();
              }
              function altbody(type) {
                if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex);
                return pass();
              }
              function altblock1(type) {
                if (type == "}") return cont();
                if (type == "|") return cont(altblock1);
                if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);}
                if (type.match(/[\]\);,]/)) return cont(altblock1);
                return pass(pattern, altblock2);
              }
              function altblock2(type) {
                if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1);
                else return pass(altblock1);
              }
            
              function macro(type) {
                if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
                return pass();
              }
              function matchBrackets(type, comb) {
                if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
                if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
                if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
                return cont();
              }
            
              function parse(state, stream, style) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
            
                while (true) {
                  var combinator = cc.length ? cc.pop() : block;
                  if (combinator(tcat)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    return cx.marked || style;
                  }
                }
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    cc: [],
                    lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
                    keywords: valKeywords,
                    indented: 0
                  };
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  tcat = content = null;
                  var style = state.tokenize(stream, state);
                  if (style == "comment") return style;
                  if (!state.lexical.hasOwnProperty("align"))
                    state.lexical.align = true;
                  if (tcat == "prefix") return style;
                  if (!content) content = stream.current();
                  return parse(state, stream, style);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
                      type = lexical.type, closing = firstChar == type;
                  if (type == "stat") return lexical.indented + indentUnit;
                  if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
                },
            
                electricChars: "{}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//",
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME("text/x-rustsrc", "rust");
            
            });
            
        • sass
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Sass mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="sass.js"></script>
            <style>.CodeMirror {border: 1px solid #ddd; font-size:12px; height: 400px}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Sass</a>
              </ul>
            </div>
            
            <article>
            <h2>Sass mode</h2>
            <form><textarea id="code" name="code">// Variable Definitions
            
            $page-width:    800px
            $sidebar-width: 200px
            $primary-color: #eeeeee
            
            // Global Attributes
            
            body
              font:
                family: sans-serif
                size: 30em
                weight: bold
            
            // Scoped Styles
            
            #contents
              width: $page-width
              #sidebar
                float: right
                width: $sidebar-width
              #main
                width: $page-width - $sidebar-width
                background: $primary-color
                h2
                  color: blue
            
            #footer
              height: 200px
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers : true,
                    matchBrackets : true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-sass</code>.</p>
              </article>
            
          • sass.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sass", function(config) {
              function tokenRegexp(words) {
                return new RegExp("^" + words.join("|"));
              }
            
              var keywords = ["true", "false", "null", "auto"];
              var keywordsRegexp = new RegExp("^" + keywords.join("|"));
            
              var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-",
                               "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"];
              var opRegexp = tokenRegexp(operators);
            
              var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/;
            
              function urlTokens(stream, state) {
                var ch = stream.peek();
            
                if (ch === ")") {
                  stream.next();
                  state.tokenizer = tokenBase;
                  return "operator";
                } else if (ch === "(") {
                  stream.next();
                  stream.eatSpace();
            
                  return "operator";
                } else if (ch === "'" || ch === '"') {
                  state.tokenizer = buildStringTokenizer(stream.next());
                  return "string";
                } else {
                  state.tokenizer = buildStringTokenizer(")", false);
                  return "string";
                }
              }
              function comment(indentation, multiLine) {
                return function(stream, state) {
                  if (stream.sol() && stream.indentation() <= indentation) {
                    state.tokenizer = tokenBase;
                    return tokenBase(stream, state);
                  }
            
                  if (multiLine && stream.skipTo("*/")) {
                    stream.next();
                    stream.next();
                    state.tokenizer = tokenBase;
                  } else {
                    stream.skipToEnd();
                  }
            
                  return "comment";
                };
              }
            
              function buildStringTokenizer(quote, greedy) {
                if (greedy == null) { greedy = true; }
            
                function stringTokenizer(stream, state) {
                  var nextChar = stream.next();
                  var peekChar = stream.peek();
                  var previousChar = stream.string.charAt(stream.pos-2);
            
                  var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\"));
            
                  if (endingString) {
                    if (nextChar !== quote && greedy) { stream.next(); }
                    state.tokenizer = tokenBase;
                    return "string";
                  } else if (nextChar === "#" && peekChar === "{") {
                    state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
                    stream.next();
                    return "operator";
                  } else {
                    return "string";
                  }
                }
            
                return stringTokenizer;
              }
            
              function buildInterpolationTokenizer(currentTokenizer) {
                return function(stream, state) {
                  if (stream.peek() === "}") {
                    stream.next();
                    state.tokenizer = currentTokenizer;
                    return "operator";
                  } else {
                    return tokenBase(stream, state);
                  }
                };
              }
            
              function indent(state) {
                if (state.indentCount == 0) {
                  state.indentCount++;
                  var lastScopeOffset = state.scopes[0].offset;
                  var currentOffset = lastScopeOffset + config.indentUnit;
                  state.scopes.unshift({ offset:currentOffset });
                }
              }
            
              function dedent(state) {
                if (state.scopes.length == 1) return;
            
                state.scopes.shift();
              }
            
              function tokenBase(stream, state) {
                var ch = stream.peek();
            
                // Comment
                if (stream.match("/*")) {
                  state.tokenizer = comment(stream.indentation(), true);
                  return state.tokenizer(stream, state);
                }
                if (stream.match("//")) {
                  state.tokenizer = comment(stream.indentation(), false);
                  return state.tokenizer(stream, state);
                }
            
                // Interpolation
                if (stream.match("#{")) {
                  state.tokenizer = buildInterpolationTokenizer(tokenBase);
                  return "operator";
                }
            
                // Strings
                if (ch === '"' || ch === "'") {
                  stream.next();
                  state.tokenizer = buildStringTokenizer(ch);
                  return "string";
                }
            
                if(!state.cursorHalf){// state.cursorHalf === 0
                // first half i.e. before : for key-value pairs
                // including selectors
            
                  if (ch === ".") {
                    stream.next();
                    if (stream.match(/^[\w-]+/)) {
                      indent(state);
                      return "atom";
                    } else if (stream.peek() === "#") {
                      indent(state);
                      return "atom";
                    }
                  }
            
                  if (ch === "#") {
                    stream.next();
                    // ID selectors
                    if (stream.match(/^[\w-]+/)) {
                      indent(state);
                      return "atom";
                    }
                    if (stream.peek() === "#") {
                      indent(state);
                      return "atom";
                    }
                  }
            
                  // Variables
                  if (ch === "$") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    return "variable-2";
                  }
            
                  // Numbers
                  if (stream.match(/^-?[0-9\.]+/))
                    return "number";
            
                  // Units
                  if (stream.match(/^(px|em|in)\b/))
                    return "unit";
            
                  if (stream.match(keywordsRegexp))
                    return "keyword";
            
                  if (stream.match(/^url/) && stream.peek() === "(") {
                    state.tokenizer = urlTokens;
                    return "atom";
                  }
            
                  if (ch === "=") {
                    // Match shortcut mixin definition
                    if (stream.match(/^=[\w-]+/)) {
                      indent(state);
                      return "meta";
                    }
                  }
            
                  if (ch === "+") {
                    // Match shortcut mixin definition
                    if (stream.match(/^\+[\w-]+/)){
                      return "variable-3";
                    }
                  }
            
                  if(ch === "@"){
                    if(stream.match(/@extend/)){
                      if(!stream.match(/\s*[\w]/))
                        dedent(state);
                    }
                  }
            
            
                  // Indent Directives
                  if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {
                    indent(state);
                    return "meta";
                  }
            
                  // Other Directives
                  if (ch === "@") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    return "meta";
                  }
            
                  if (stream.eatWhile(/[\w-]/)){
                    if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){
                      return "propery";
                    }
                    else if(stream.match(/ *:/,false)){
                      indent(state);
                      state.cursorHalf = 1;
                      return "atom";
                    }
                    else if(stream.match(/ *,/,false)){
                      return "atom";
                    }
                    else{
                      indent(state);
                      return "atom";
                    }
                  }
            
                  if(ch === ":"){
                    if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element
                      return "keyword";
                    }
                    stream.next();
                    state.cursorHalf=1;
                    return "operator";
                  }
            
                } // cursorHalf===0 ends here
                else{
            
                  if (ch === "#") {
                    stream.next();
                    // Hex numbers
                    if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){
                      if(!stream.peek()){
                        state.cursorHalf = 0;
                      }
                      return "number";
                    }
                  }
            
                  // Numbers
                  if (stream.match(/^-?[0-9\.]+/)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "number";
                  }
            
                  // Units
                  if (stream.match(/^(px|em|in)\b/)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "unit";
                  }
            
                  if (stream.match(keywordsRegexp)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "keyword";
                  }
            
                  if (stream.match(/^url/) && stream.peek() === "(") {
                    state.tokenizer = urlTokens;
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "atom";
                  }
            
                  // Variables
                  if (ch === "$") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "variable-3";
                  }
            
                  // bang character for !important, !default, etc.
                  if (ch === "!") {
                    stream.next();
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return stream.match(/^[\w]+/) ? "keyword": "operator";
                  }
            
                  if (stream.match(opRegexp)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "operator";
                  }
            
                  // attributes
                  if (stream.eatWhile(/[\w-]/)) {
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "attribute";
                  }
            
                  //stream.eatSpace();
                  if(!stream.peek()){
                    state.cursorHalf = 0;
                    return null;
                  }
            
                } // else ends here
            
                if (stream.match(opRegexp))
                  return "operator";
            
                // If we haven't returned by now, we move 1 character
                // and return an error
                stream.next();
                return null;
              }
            
              function tokenLexer(stream, state) {
                if (stream.sol()) state.indentCount = 0;
                var style = state.tokenizer(stream, state);
                var current = stream.current();
            
                if (current === "@return" || current === "}"){
                  dedent(state);
                }
            
                if (style !== null) {
                  var startOfToken = stream.pos - current.length;
            
                  var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);
            
                  var newScopes = [];
            
                  for (var i = 0; i < state.scopes.length; i++) {
                    var scope = state.scopes[i];
            
                    if (scope.offset <= withCurrentIndent)
                      newScopes.push(scope);
                  }
            
                  state.scopes = newScopes;
                }
            
            
                return style;
              }
            
              return {
                startState: function() {
                  return {
                    tokenizer: tokenBase,
                    scopes: [{offset: 0, type: "sass"}],
                    indentCount: 0,
                    cursorHalf: 0,  // cursor half tells us if cursor lies after (1)
                                    // or before (0) colon (well... more or less)
                    definedVars: [],
                    definedMixins: []
                  };
                },
                token: function(stream, state) {
                  var style = tokenLexer(stream, state);
            
                  state.lastToken = { style: style, content: stream.current() };
            
                  return style;
                },
            
                indent: function(state) {
                  return state.scopes[0].offset;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-sass", "sass");
            
            });
            
        • scheme
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Scheme mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="scheme.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Scheme</a>
              </ul>
            </div>
            
            <article>
            <h2>Scheme mode</h2>
            <form><textarea id="code" name="code">
            ; See if the input starts with a given symbol.
            (define (match-symbol input pattern)
              (cond ((null? (remain input)) #f)
            	((eqv? (car (remain input)) pattern) (r-cdr input))
            	(else #f)))
            
            ; Allow the input to start with one of a list of patterns.
            (define (match-or input pattern)
              (cond ((null? pattern) #f)
            	((match-pattern input (car pattern)))
            	(else (match-or input (cdr pattern)))))
            
            ; Allow a sequence of patterns.
            (define (match-seq input pattern)
              (if (null? pattern)
                  input
                  (let ((match (match-pattern input (car pattern))))
            	(if match (match-seq match (cdr pattern)) #f))))
            
            ; Match with the pattern but no problem if it does not match.
            (define (match-opt input pattern)
              (let ((match (match-pattern input (car pattern))))
                (if match match input)))
            
            ; Match anything (other than '()), until pattern is found. The rather
            ; clumsy form of requiring an ending pattern is needed to decide where
            ; the end of the match is. If none is given, this will match the rest
            ; of the sentence.
            (define (match-any input pattern)
              (cond ((null? (remain input)) #f)
            	((null? pattern) (f-cons (remain input) (clear-remain input)))
            	(else
            	 (let ((accum-any (collector)))
            	   (define (match-pattern-any input pattern)
            	     (cond ((null? (remain input)) #f)
            		   (else (accum-any (car (remain input)))
            			 (cond ((match-pattern (r-cdr input) pattern))
            			       (else (match-pattern-any (r-cdr input) pattern))))))
            	   (let ((retval (match-pattern-any input (car pattern))))
            	     (if retval
            		 (f-cons (accum-any) retval)
            		 #f))))))
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>
            
              </article>
            
          • scheme.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Koh Zi Han, based on implementation by Koh Zi Chun
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("scheme", function () {
                var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
                    ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
                var INDENT_WORD_SKIP = 2;
            
                function makeKeywords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
                var indentKeys = makeKeywords("define let letrec let* lambda");
            
                function stateStack(indent, type, prev) { // represents a state stack object
                    this.indent = indent;
                    this.type = type;
                    this.prev = prev;
                }
            
                function pushStack(state, indent, type) {
                    state.indentStack = new stateStack(indent, type, state.indentStack);
                }
            
                function popStack(state) {
                    state.indentStack = state.indentStack.prev;
                }
            
                var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\/[01]+#*)?i|[-+]?[01]+#*(?:\/[01]+#*)?@[-+]?[01]+#*(?:\/[01]+#*)?|[-+]?[01]+#*(?:\/[01]+#*)?[-+](?:[01]+#*(?:\/[01]+#*)?)?i|[-+]?[01]+#*(?:\/[01]+#*)?)(?=[()\s;"]|$)/i);
                var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?)(?=[()\s;"]|$)/i);
                var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\da-f]+#*(?:\/[\da-f]+#*)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?@[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?[-+](?:[\da-f]+#*(?:\/[\da-f]+#*)?)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?)(?=[()\s;"]|$)/i);
                var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)i|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)@[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)?i|(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*))(?=[()\s;"]|$)/i);
            
                function isBinaryNumber (stream) {
                    return stream.match(binaryMatcher);
                }
            
                function isOctalNumber (stream) {
                    return stream.match(octalMatcher);
                }
            
                function isDecimalNumber (stream, backup) {
                    if (backup === true) {
                        stream.backUp(1);
                    }
                    return stream.match(decimalMatcher);
                }
            
                function isHexNumber (stream) {
                    return stream.match(hexMatcher);
                }
            
                return {
                    startState: function () {
                        return {
                            indentStack: null,
                            indentation: 0,
                            mode: false,
                            sExprComment: false
                        };
                    },
            
                    token: function (stream, state) {
                        if (state.indentStack == null && stream.sol()) {
                            // update indentation, but only if indentStack is empty
                            state.indentation = stream.indentation();
                        }
            
                        // skip spaces
                        if (stream.eatSpace()) {
                            return null;
                        }
                        var returnType = null;
            
                        switch(state.mode){
                            case "string": // multi-line string parsing mode
                                var next, escaped = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "\"" && !escaped) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    escaped = !escaped && next == "\\";
                                }
                                returnType = STRING; // continue on in scheme-string mode
                                break;
                            case "comment": // comment parsing mode
                                var next, maybeEnd = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "#" && maybeEnd) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    maybeEnd = (next == "|");
                                }
                                returnType = COMMENT;
                                break;
                            case "s-expr-comment": // s-expr commenting mode
                                state.mode = false;
                                if(stream.peek() == "(" || stream.peek() == "["){
                                    // actually start scheme s-expr commenting mode
                                    state.sExprComment = 0;
                                }else{
                                    // if not we just comment the entire of the next token
                                    stream.eatWhile(/[^/s]/); // eat non spaces
                                    returnType = COMMENT;
                                    break;
                                }
                            default: // default parsing mode
                                var ch = stream.next();
            
                                if (ch == "\"") {
                                    state.mode = "string";
                                    returnType = STRING;
            
                                } else if (ch == "'") {
                                    returnType = ATOM;
                                } else if (ch == '#') {
                                    if (stream.eat("|")) {                    // Multi-line comment
                                        state.mode = "comment"; // toggle to comment mode
                                        returnType = COMMENT;
                                    } else if (stream.eat(/[tf]/i)) {            // #t/#f (atom)
                                        returnType = ATOM;
                                    } else if (stream.eat(';')) {                // S-Expr comment
                                        state.mode = "s-expr-comment";
                                        returnType = COMMENT;
                                    } else {
                                        var numTest = null, hasExactness = false, hasRadix = true;
                                        if (stream.eat(/[ei]/i)) {
                                            hasExactness = true;
                                        } else {
                                            stream.backUp(1);       // must be radix specifier
                                        }
                                        if (stream.match(/^#b/i)) {
                                            numTest = isBinaryNumber;
                                        } else if (stream.match(/^#o/i)) {
                                            numTest = isOctalNumber;
                                        } else if (stream.match(/^#x/i)) {
                                            numTest = isHexNumber;
                                        } else if (stream.match(/^#d/i)) {
                                            numTest = isDecimalNumber;
                                        } else if (stream.match(/^[-+0-9.]/, false)) {
                                            hasRadix = false;
                                            numTest = isDecimalNumber;
                                        // re-consume the intial # if all matches failed
                                        } else if (!hasExactness) {
                                            stream.eat('#');
                                        }
                                        if (numTest != null) {
                                            if (hasRadix && !hasExactness) {
                                                // consume optional exactness after radix
                                                stream.match(/^#[ei]/i);
                                            }
                                            if (numTest(stream))
                                                returnType = NUMBER;
                                        }
                                    }
                                } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal
                                    returnType = NUMBER;
                                } else if (ch == ";") { // comment
                                    stream.skipToEnd(); // rest of the line is a comment
                                    returnType = COMMENT;
                                } else if (ch == "(" || ch == "[") {
                                  var keyWord = ''; var indentTemp = stream.column(), letter;
                                    /**
                                    Either
                                    (indent-word ..
                                    (non-indent-word ..
                                    (;something else, bracket, etc.
                                    */
            
                                    while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
                                        keyWord += letter;
                                    }
            
                                    if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
            
                                        pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
                                    } else { // non-indent word
                                        // we continue eating the spaces
                                        stream.eatSpace();
                                        if (stream.eol() || stream.peek() == ";") {
                                            // nothing significant after
                                            // we restart indentation 1 space after
                                            pushStack(state, indentTemp + 1, ch);
                                        } else {
                                            pushStack(state, indentTemp + stream.current().length, ch); // else we match
                                        }
                                    }
                                    stream.backUp(stream.current().length - 1); // undo all the eating
            
                                    if(typeof state.sExprComment == "number") state.sExprComment++;
            
                                    returnType = BRACKET;
                                } else if (ch == ")" || ch == "]") {
                                    returnType = BRACKET;
                                    if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
                                        popStack(state);
            
                                        if(typeof state.sExprComment == "number"){
                                            if(--state.sExprComment == 0){
                                                returnType = COMMENT; // final closing bracket
                                                state.sExprComment = false; // turn off s-expr commenting mode
                                            }
                                        }
                                    }
                                } else {
                                    stream.eatWhile(/[\w\$_\-!$%&*+\.\/:<=>?@\^~]/);
            
                                    if (keywords && keywords.propertyIsEnumerable(stream.current())) {
                                        returnType = BUILTIN;
                                    } else returnType = "variable";
                                }
                        }
                        return (typeof state.sExprComment == "number") ? COMMENT : returnType;
                    },
            
                    indent: function (state) {
                        if (state.indentStack == null) return state.indentation;
                        return state.indentStack.indent;
                    },
            
                    lineComment: ";;"
                };
            });
            
            CodeMirror.defineMIME("text/x-scheme", "scheme");
            
            });
            
        • shell
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Shell mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src=shell.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Shell</a>
              </ul>
            </div>
            
            <article>
            <h2>Shell mode</h2>
            
            
            <textarea id=code>
            #!/bin/bash
            
            # clone the repository
            git clone http://github.com/garden/tree
            
            # generate HTTPS credentials
            cd tree
            openssl genrsa -aes256 -out https.key 1024
            openssl req -new -nodes -key https.key -out https.csr
            openssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt
            cp https.key{,.orig}
            openssl rsa -in https.key.orig -out https.key
            
            # start the server in HTTPS mode
            cd web
            sudo node ../server.js 443 'yes' &gt;&gt; ../node.log &amp;
            
            # here is how to stop the server
            for pid in `ps aux | grep 'node ../server.js' | awk '{print $2}'` ; do
              sudo kill -9 $pid 2&gt; /dev/null
            done
            
            exit 0</textarea>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: 'shell',
                lineNumbers: true,
                matchBrackets: true
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-sh</code>.</p>
            </article>
            
          • shell.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('shell', function() {
            
              var words = {};
              function define(style, string) {
                var split = string.split(' ');
                for(var i = 0; i < split.length; i++) {
                  words[split[i]] = style;
                }
              };
            
              // Atoms
              define('atom', 'true false');
            
              // Keywords
              define('keyword', 'if then do else elif while until for in esac fi fin ' +
                'fil done exit set unset export function');
            
              // Commands
              define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +
                'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' +
                'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
                'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +
                'touch vi vim wall wc wget who write yes zsh');
            
              function tokenBase(stream, state) {
                if (stream.eatSpace()) return null;
            
                var sol = stream.sol();
                var ch = stream.next();
            
                if (ch === '\\') {
                  stream.next();
                  return null;
                }
                if (ch === '\'' || ch === '"' || ch === '`') {
                  state.tokens.unshift(tokenString(ch));
                  return tokenize(stream, state);
                }
                if (ch === '#') {
                  if (sol && stream.eat('!')) {
                    stream.skipToEnd();
                    return 'meta'; // 'comment'?
                  }
                  stream.skipToEnd();
                  return 'comment';
                }
                if (ch === '$') {
                  state.tokens.unshift(tokenDollar);
                  return tokenize(stream, state);
                }
                if (ch === '+' || ch === '=') {
                  return 'operator';
                }
                if (ch === '-') {
                  stream.eat('-');
                  stream.eatWhile(/\w/);
                  return 'attribute';
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/\d/);
                  if(stream.eol() || !/\w/.test(stream.peek())) {
                    return 'number';
                  }
                }
                stream.eatWhile(/[\w-]/);
                var cur = stream.current();
                if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
                return words.hasOwnProperty(cur) ? words[cur] : null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var next, end = false, escaped = false;
                  while ((next = stream.next()) != null) {
                    if (next === quote && !escaped) {
                      end = true;
                      break;
                    }
                    if (next === '$' && !escaped && quote !== '\'') {
                      escaped = true;
                      stream.backUp(1);
                      state.tokens.unshift(tokenDollar);
                      break;
                    }
                    escaped = !escaped && next === '\\';
                  }
                  if (end || !escaped) {
                    state.tokens.shift();
                  }
                  return (quote === '`' || quote === ')' ? 'quote' : 'string');
                };
              };
            
              var tokenDollar = function(stream, state) {
                if (state.tokens.length > 1) stream.eat('$');
                var ch = stream.next(), hungry = /\w/;
                if (ch === '{') hungry = /[^}]/;
                if (ch === '(') {
                  state.tokens[0] = tokenString(')');
                  return tokenize(stream, state);
                }
                if (!/\d/.test(ch)) {
                  stream.eatWhile(hungry);
                  stream.eat('}');
                }
                state.tokens.shift();
                return 'def';
              };
            
              function tokenize(stream, state) {
                return (state.tokens[0] || tokenBase) (stream, state);
              };
            
              return {
                startState: function() {return {tokens:[]};},
                token: function(stream, state) {
                  return tokenize(stream, state);
                },
                lineComment: '#',
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME('text/x-sh', 'shell');
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({}, "shell");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("var",
                 "text [def $var] text");
              MT("varBraces",
                 "text[def ${var}]text");
              MT("varVar",
                 "text [def $a$b] text");
              MT("varBracesVarBraces",
                 "text[def ${a}${b}]text");
            
              MT("singleQuotedVar",
                 "[string 'text $var text']");
              MT("singleQuotedVarBraces",
                 "[string 'text ${var} text']");
            
              MT("doubleQuotedVar",
                 '[string "text ][def $var][string  text"]');
              MT("doubleQuotedVarBraces",
                 '[string "text][def ${var}][string text"]');
              MT("doubleQuotedVarPunct",
                 '[string "text ][def $@][string  text"]');
              MT("doubleQuotedVarVar",
                 '[string "][def $a$b][string "]');
              MT("doubleQuotedVarBracesVarBraces",
                 '[string "][def ${a}${b}][string "]');
            
              MT("notAString",
                 "text\\'text");
              MT("escapes",
                 "outside\\'\\\"\\`\\\\[string \"inside\\`\\'\\\"\\\\`\\$notAVar\"]outside\\$\\(notASubShell\\)");
            
              MT("subshell",
                 "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`].");
              MT("doubleQuotedSubshell",
                 "[builtin echo] [string \"][quote $(whoami)][string 's log, stardate `date`.\"]");
            
              MT("hashbang",
                 "[meta #!/bin/bash]");
              MT("comment",
                 "text [comment # Blurb]");
            
              MT("numbers",
                 "[number 0] [number 1] [number 2]");
              MT("keywords",
                 "[keyword while] [atom true]; [keyword do]",
                 "  [builtin sleep] [number 3]",
                 "[keyword done]");
              MT("options",
                 "[builtin ls] [attribute -l] [attribute --human-readable]");
              MT("operator",
                 "[def var][operator =]value");
            })();
            
        • sieve
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Sieve (RFC5228) mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="sieve.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Sieve (RFC5228)</a>
              </ul>
            </div>
            
            <article>
            <h2>Sieve (RFC5228) mode</h2>
            <form><textarea id="code" name="code">
            #
            # Example Sieve Filter
            # Declare any optional features or extension used by the script
            #
            
            require ["fileinto", "reject"];
            
            #
            # Reject any large messages (note that the four leading dots get
            # "stuffed" to three)
            #
            if size :over 1M
            {
              reject text:
            Please do not send me large attachments.
            Put your file on a server and send me the URL.
            Thank you.
            .... Fred
            .
            ;
              stop;
            }
            
            #
            # Handle messages from known mailing lists
            # Move messages from IETF filter discussion list to filter folder
            #
            if header :is "Sender" "owner-ietf-mta-filters@imc.org"
            {
              fileinto "filter";  # move to "filter" folder
            }
            #
            # Keep all messages to or from people in my company
            #
            elsif address :domain :is ["From", "To"] "example.com"
            {
              keep;               # keep in "In" folder
            }
            
            #
            # Try and catch unsolicited email.  If a message is not to me,
            # or it contains a subject known to be spam, file it away.
            #
            elsif anyof (not address :all :contains
                           ["To", "Cc", "Bcc"] "me@example.com",
                         header :matches "subject"
                           ["*make*money*fast*", "*university*dipl*mas*"])
            {
              # If message header does not contain my address,
              # it's from a list.
              fileinto "spam";   # move to "spam" folder
            }
            else
            {
              # Move all other (non-company) mail to "personal"
              # folder.
              fileinto "personal";
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/sieve</code>.</p>
            
              </article>
            
          • sieve.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sieve", function(config) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var keywords = words("if elsif else stop require");
              var atoms = words("true false not");
              var indentUnit = config.indentUnit;
            
              function tokenBase(stream, state) {
            
                var ch = stream.next();
                if (ch == "/" && stream.eat("*")) {
                  state.tokenize = tokenCComment;
                  return tokenCComment(stream, state);
                }
            
                if (ch === '#') {
                  stream.skipToEnd();
                  return "comment";
                }
            
                if (ch == "\"") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
            
                if (ch == "(") {
                  state._indent.push("(");
                  // add virtual angel wings so that editor behaves...
                  // ...more sane incase of broken brackets
                  state._indent.push("{");
                  return null;
                }
            
                if (ch === "{") {
                  state._indent.push("{");
                  return null;
                }
            
                if (ch == ")")  {
                  state._indent.pop();
                  state._indent.pop();
                }
            
                if (ch === "}") {
                  state._indent.pop();
                  return null;
                }
            
                if (ch == ",")
                  return null;
            
                if (ch == ";")
                  return null;
            
            
                if (/[{}\(\),;]/.test(ch))
                  return null;
            
                // 1*DIGIT "K" / "M" / "G"
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\d]/);
                  stream.eat(/[KkMmGg]/);
                  return "number";
                }
            
                // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_")
                if (ch == ":") {
                  stream.eatWhile(/[a-zA-Z_]/);
                  stream.eatWhile(/[a-zA-Z0-9_]/);
            
                  return "operator";
                }
            
                stream.eatWhile(/\w/);
                var cur = stream.current();
            
                // "text:" *(SP / HTAB) (hash-comment / CRLF)
                // *(multiline-literal / multiline-dotstart)
                // "." CRLF
                if ((cur == "text") && stream.eat(":"))
                {
                  state.tokenize = tokenMultiLineString;
                  return "string";
                }
            
                if (keywords.propertyIsEnumerable(cur))
                  return "keyword";
            
                if (atoms.propertyIsEnumerable(cur))
                  return "atom";
            
                return null;
              }
            
              function tokenMultiLineString(stream, state)
              {
                state._multiLineString = true;
                // the first line is special it may contain a comment
                if (!stream.sol()) {
                  stream.eatSpace();
            
                  if (stream.peek() == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  stream.skipToEnd();
                  return "string";
                }
            
                if ((stream.next() == ".")  && (stream.eol()))
                {
                  state._multiLineString = false;
                  state.tokenize = tokenBase;
                }
            
                return "string";
              }
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped)
                      break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          _indent: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace())
                    return null;
            
                  return (state.tokenize || tokenBase)(stream, state);;
                },
            
                indent: function(state, _textAfter) {
                  var length = state._indent.length;
                  if (_textAfter && (_textAfter[0] == "}"))
                    length--;
            
                  if (length <0)
                    length = 0;
            
                  return length * indentUnit;
                },
            
                electricChars: "}"
              };
            });
            
            CodeMirror.defineMIME("application/sieve", "sieve");
            
            });
            
        • slim
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SLIM mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
            <script src="https://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
            <link rel="stylesheet" href="https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlembedded/htmlembedded.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../coffeescript/coffeescript.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../ruby/ruby.js"></script>
            <script src="../markdown/markdown.js"></script>
            <script src="slim.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SLIM</a>
              </ul>
            </div>
            
            <article>
              <h2>SLIM mode</h2>
              <form><textarea id="code" name="code">
            body
              table
                - for user in users
                  td id="user_#{user.id}" class=user.role
                    a href=user_action(user, :edit) Edit #{user.name}
                    a href=(path_to_user user) = user.name
            body
              h1(id="logo") = page_logo
              h2[id="tagline" class="small tagline"] = page_tagline
            
            h2[id="tagline"
               class="small tagline"] = page_tagline
            
            h1 id = "logo" = page_logo
            h2 [ id = "tagline" ] = page_tagline
            
            / comment
              second line
            /! html comment
               second line
            <!-- html comment -->
            <a href="#{'hello' if set}">link</a>
            a.slim href="work" disabled=false running==:atom Text <b>bold</b>
            .clazz data-id="test" == 'hello' unless quark
             | Text mode #{12}
               Second line
            = x ||= :ruby_atom
            #menu.left
              - @env.each do |x|
                li: a = x
            *@dyntag attr="val"
            .first *{:class => [:second, :third]} Text
            .second class=["text","more"]
            .third class=:text,:symbol
            
              </textarea></form>
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  theme: "ambiance",
                  mode: "application/x-slim"
                });
                $('.CodeMirror').resizable({
                  resize: function() {
                    editor.setSize($(this).width(), $(this).height());
                    //editor.refresh();
                  }
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>application/x-slim</code>.</p>
            
              <p>
                <strong>Parsing/Highlighting Tests:</strong>
                <a href="../../test/index.html#slim_*">normal</a>,
                <a href="../../test/index.html#verbose,slim_*">verbose</a>.
              </p>
            </article>
            
          • slim.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
              CodeMirror.defineMode("slim", function(config) {
                var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
                var rubyMode = CodeMirror.getMode(config, "ruby");
                var modes = { html: htmlMode, ruby: rubyMode };
                var embedded = {
                  ruby: "ruby",
                  javascript: "javascript",
                  css: "text/css",
                  sass: "text/x-sass",
                  scss: "text/x-scss",
                  less: "text/x-less",
                  styl: "text/x-styl", // no highlighting so far
                  coffee: "coffeescript",
                  asciidoc: "text/x-asciidoc",
                  markdown: "text/x-markdown",
                  textile: "text/x-textile", // no highlighting so far
                  creole: "text/x-creole", // no highlighting so far
                  wiki: "text/x-wiki", // no highlighting so far
                  mediawiki: "text/x-mediawiki", // no highlighting so far
                  rdoc: "text/x-rdoc", // no highlighting so far
                  builder: "text/x-builder", // no highlighting so far
                  nokogiri: "text/x-nokogiri", // no highlighting so far
                  erb: "application/x-erb"
                };
                var embeddedRegexp = function(map){
                  var arr = [];
                  for(var key in map) arr.push(key);
                  return new RegExp("^("+arr.join('|')+"):");
                }(embedded);
            
                var styleMap = {
                  "commentLine": "comment",
                  "slimSwitch": "operator special",
                  "slimTag": "tag",
                  "slimId": "attribute def",
                  "slimClass": "attribute qualifier",
                  "slimAttribute": "attribute",
                  "slimSubmode": "keyword special",
                  "closeAttributeTag": null,
                  "slimDoctype": null,
                  "lineContinuation": null
                };
                var closing = {
                  "{": "}",
                  "[": "]",
                  "(": ")"
                };
            
                var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
                var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040";
                var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)");
                var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)");
                var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*");
                var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/;
                var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/;
            
                function backup(pos, tokenize, style) {
                  var restore = function(stream, state) {
                    state.tokenize = tokenize;
                    if (stream.pos < pos) {
                      stream.pos = pos;
                      return style;
                    }
                    return state.tokenize(stream, state);
                  };
                  return function(stream, state) {
                    state.tokenize = restore;
                    return tokenize(stream, state);
                  };
                }
            
                function maybeBackup(stream, state, pat, offset, style) {
                  var cur = stream.current();
                  var idx = cur.search(pat);
                  if (idx > -1) {
                    state.tokenize = backup(stream.pos, state.tokenize, style);
                    stream.backUp(cur.length - idx - offset);
                  }
                  return style;
                }
            
                function continueLine(state, column) {
                  state.stack = {
                    parent: state.stack,
                    style: "continuation",
                    indented: column,
                    tokenize: state.line
                  };
                  state.line = state.tokenize;
                }
                function finishContinue(state) {
                  if (state.line == state.tokenize) {
                    state.line = state.stack.tokenize;
                    state.stack = state.stack.parent;
                  }
                }
            
                function lineContinuable(column, tokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    if (stream.match(/^\\$/)) {
                      continueLine(state, column);
                      return "lineContinuation";
                    }
                    var style = tokenize(stream, state);
                    if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) {
                      stream.backUp(1);
                    }
                    return style;
                  };
                }
                function commaContinuable(column, tokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    var style = tokenize(stream, state);
                    if (stream.eol() && stream.current().match(/,$/)) {
                      continueLine(state, column);
                    }
                    return style;
                  };
                }
            
                function rubyInQuote(endQuote, tokenize) {
                  // TODO: add multi line support
                  return function(stream, state) {
                    var ch = stream.peek();
                    if (ch == endQuote && state.rubyState.tokenize.length == 1) {
                      // step out of ruby context as it seems to complete processing all the braces
                      stream.next();
                      state.tokenize = tokenize;
                      return "closeAttributeTag";
                    } else {
                      return ruby(stream, state);
                    }
                  };
                }
                function startRubySplat(tokenize) {
                  var rubyState;
                  var runSplat = function(stream, state) {
                    if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) {
                      stream.backUp(1);
                      if (stream.eatSpace()) {
                        state.rubyState = rubyState;
                        state.tokenize = tokenize;
                        return tokenize(stream, state);
                      }
                      stream.next();
                    }
                    return ruby(stream, state);
                  };
                  return function(stream, state) {
                    rubyState = state.rubyState;
                    state.rubyState = rubyMode.startState();
                    state.tokenize = runSplat;
                    return ruby(stream, state);
                  };
                }
            
                function ruby(stream, state) {
                  return rubyMode.token(stream, state.rubyState);
                }
            
                function htmlLine(stream, state) {
                  if (stream.match(/^\\$/)) {
                    return "lineContinuation";
                  }
                  return html(stream, state);
                }
                function html(stream, state) {
                  if (stream.match(/^#\{/)) {
                    state.tokenize = rubyInQuote("}", state.tokenize);
                    return null;
                  }
                  return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState));
                }
            
                function startHtmlLine(lastTokenize) {
                  return function(stream, state) {
                    var style = htmlLine(stream, state);
                    if (stream.eol()) state.tokenize = lastTokenize;
                    return style;
                  };
                }
            
                function startHtmlMode(stream, state, offset) {
                  state.stack = {
                    parent: state.stack,
                    style: "html",
                    indented: stream.column() + offset, // pipe + space
                    tokenize: state.line
                  };
                  state.line = state.tokenize = html;
                  return null;
                }
            
                function comment(stream, state) {
                  stream.skipToEnd();
                  return state.stack.style;
                }
            
                function commentMode(stream, state) {
                  state.stack = {
                    parent: state.stack,
                    style: "comment",
                    indented: state.indented + 1,
                    tokenize: state.line
                  };
                  state.line = comment;
                  return comment(stream, state);
                }
            
                function attributeWrapper(stream, state) {
                  if (stream.eat(state.stack.endQuote)) {
                    state.line = state.stack.line;
                    state.tokenize = state.stack.tokenize;
                    state.stack = state.stack.parent;
                    return null;
                  }
                  if (stream.match(wrappedAttributeNameRegexp)) {
                    state.tokenize = attributeWrapperAssign;
                    return "slimAttribute";
                  }
                  stream.next();
                  return null;
                }
                function attributeWrapperAssign(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = attributeWrapperValue;
                    return null;
                  }
                  return attributeWrapper(stream, state);
                }
                function attributeWrapperValue(stream, state) {
                  var ch = stream.peek();
                  if (ch == '"' || ch == "\'") {
                    state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper);
                    stream.next();
                    return state.tokenize(stream, state);
                  }
                  if (ch == '[') {
                    return startRubySplat(attributeWrapper)(stream, state);
                  }
                  if (stream.match(/^(true|false|nil)\b/)) {
                    state.tokenize = attributeWrapper;
                    return "keyword";
                  }
                  return startRubySplat(attributeWrapper)(stream, state);
                }
            
                function startAttributeWrapperMode(state, endQuote, tokenize) {
                  state.stack = {
                    parent: state.stack,
                    style: "wrapper",
                    indented: state.indented + 1,
                    tokenize: tokenize,
                    line: state.line,
                    endQuote: endQuote
                  };
                  state.line = state.tokenize = attributeWrapper;
                  return null;
                }
            
                function sub(stream, state) {
                  if (stream.match(/^#\{/)) {
                    state.tokenize = rubyInQuote("}", state.tokenize);
                    return null;
                  }
                  var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize);
                  subStream.pos = stream.pos - state.stack.indented;
                  subStream.start = stream.start - state.stack.indented;
                  subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented;
                  subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented;
                  var style = state.subMode.token(subStream, state.subState);
                  stream.pos = subStream.pos + state.stack.indented;
                  return style;
                }
                function firstSub(stream, state) {
                  state.stack.indented = stream.column();
                  state.line = state.tokenize = sub;
                  return state.tokenize(stream, state);
                }
            
                function createMode(mode) {
                  var query = embedded[mode];
                  var spec = CodeMirror.mimeModes[query];
                  if (spec) {
                    return CodeMirror.getMode(config, spec);
                  }
                  var factory = CodeMirror.modes[query];
                  if (factory) {
                    return factory(config, {name: query});
                  }
                  return CodeMirror.getMode(config, "null");
                }
            
                function getMode(mode) {
                  if (!modes.hasOwnProperty(mode)) {
                    return modes[mode] = createMode(mode);
                  }
                  return modes[mode];
                }
            
                function startSubMode(mode, state) {
                  var subMode = getMode(mode);
                  var subState = subMode.startState && subMode.startState();
            
                  state.subMode = subMode;
                  state.subState = subState;
            
                  state.stack = {
                    parent: state.stack,
                    style: "sub",
                    indented: state.indented + 1,
                    tokenize: state.line
                  };
                  state.line = state.tokenize = firstSub;
                  return "slimSubmode";
                }
            
                function doctypeLine(stream, _state) {
                  stream.skipToEnd();
                  return "slimDoctype";
                }
            
                function startLine(stream, state) {
                  var ch = stream.peek();
                  if (ch == '<') {
                    return (state.tokenize = startHtmlLine(state.tokenize))(stream, state);
                  }
                  if (stream.match(/^[|']/)) {
                    return startHtmlMode(stream, state, 1);
                  }
                  if (stream.match(/^\/(!|\[\w+])?/)) {
                    return commentMode(stream, state);
                  }
                  if (stream.match(/^(-|==?[<>]?)/)) {
                    state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby));
                    return "slimSwitch";
                  }
                  if (stream.match(/^doctype\b/)) {
                    state.tokenize = doctypeLine;
                    return "keyword";
                  }
            
                  var m = stream.match(embeddedRegexp);
                  if (m) {
                    return startSubMode(m[1], state);
                  }
            
                  return slimTag(stream, state);
                }
            
                function slim(stream, state) {
                  if (state.startOfLine) {
                    return startLine(stream, state);
                  }
                  return slimTag(stream, state);
                }
            
                function slimTag(stream, state) {
                  if (stream.eat('*')) {
                    state.tokenize = startRubySplat(slimTagExtras);
                    return null;
                  }
                  if (stream.match(nameRegexp)) {
                    state.tokenize = slimTagExtras;
                    return "slimTag";
                  }
                  return slimClass(stream, state);
                }
                function slimTagExtras(stream, state) {
                  if (stream.match(/^(<>?|><?)/)) {
                    state.tokenize = slimClass;
                    return null;
                  }
                  return slimClass(stream, state);
                }
                function slimClass(stream, state) {
                  if (stream.match(classIdRegexp)) {
                    state.tokenize = slimClass;
                    return "slimId";
                  }
                  if (stream.match(classNameRegexp)) {
                    state.tokenize = slimClass;
                    return "slimClass";
                  }
                  return slimAttribute(stream, state);
                }
                function slimAttribute(stream, state) {
                  if (stream.match(/^([\[\{\(])/)) {
                    return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute);
                  }
                  if (stream.match(attributeNameRegexp)) {
                    state.tokenize = slimAttributeAssign;
                    return "slimAttribute";
                  }
                  if (stream.peek() == '*') {
                    stream.next();
                    state.tokenize = startRubySplat(slimContent);
                    return null;
                  }
                  return slimContent(stream, state);
                }
                function slimAttributeAssign(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = slimAttributeValue;
                    return null;
                  }
                  // should never happen, because of forward lookup
                  return slimAttribute(stream, state);
                }
            
                function slimAttributeValue(stream, state) {
                  var ch = stream.peek();
                  if (ch == '"' || ch == "\'") {
                    state.tokenize = readQuoted(ch, "string", true, false, slimAttribute);
                    stream.next();
                    return state.tokenize(stream, state);
                  }
                  if (ch == '[') {
                    return startRubySplat(slimAttribute)(stream, state);
                  }
                  if (ch == ':') {
                    return startRubySplat(slimAttributeSymbols)(stream, state);
                  }
                  if (stream.match(/^(true|false|nil)\b/)) {
                    state.tokenize = slimAttribute;
                    return "keyword";
                  }
                  return startRubySplat(slimAttribute)(stream, state);
                }
                function slimAttributeSymbols(stream, state) {
                  stream.backUp(1);
                  if (stream.match(/^[^\s],(?=:)/)) {
                    state.tokenize = startRubySplat(slimAttributeSymbols);
                    return null;
                  }
                  stream.next();
                  return slimAttribute(stream, state);
                }
                function readQuoted(quote, style, embed, unescaped, nextTokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    var fresh = stream.current().length == 0;
                    if (stream.match(/^\\$/, fresh)) {
                      if (!fresh) return style;
                      continueLine(state, state.indented);
                      return "lineContinuation";
                    }
                    if (stream.match(/^#\{/, fresh)) {
                      if (!fresh) return style;
                      state.tokenize = rubyInQuote("}", state.tokenize);
                      return null;
                    }
                    var escaped = false, ch;
                    while ((ch = stream.next()) != null) {
                      if (ch == quote && (unescaped || !escaped)) {
                        state.tokenize = nextTokenize;
                        break;
                      }
                      if (embed && ch == "#" && !escaped) {
                        if (stream.eat("{")) {
                          stream.backUp(2);
                          break;
                        }
                      }
                      escaped = !escaped && ch == "\\";
                    }
                    if (stream.eol() && escaped) {
                      stream.backUp(1);
                    }
                    return style;
                  };
                }
                function slimContent(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = ruby;
                    return "slimSwitch";
                  }
                  if (stream.match(/^\/$/)) { // tag close hint
                    state.tokenize = slim;
                    return null;
                  }
                  if (stream.match(/^:/)) { // inline tag
                    state.tokenize = slimTag;
                    return "slimSwitch";
                  }
                  startHtmlMode(stream, state, 0);
                  return state.tokenize(stream, state);
                }
            
                var mode = {
                  // default to html mode
                  startState: function() {
                    var htmlState = htmlMode.startState();
                    var rubyState = rubyMode.startState();
                    return {
                      htmlState: htmlState,
                      rubyState: rubyState,
                      stack: null,
                      last: null,
                      tokenize: slim,
                      line: slim,
                      indented: 0
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
                      rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
                      subMode: state.subMode,
                      subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState),
                      stack: state.stack,
                      last: state.last,
                      tokenize: state.tokenize,
                      line: state.line
                    };
                  },
            
                  token: function(stream, state) {
                    if (stream.sol()) {
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                      state.tokenize = state.line;
                      while (state.stack && state.stack.indented > state.indented && state.last != "slimSubmode") {
                        state.line = state.tokenize = state.stack.tokenize;
                        state.stack = state.stack.parent;
                        state.subMode = null;
                        state.subState = null;
                      }
                    }
                    if (stream.eatSpace()) return null;
                    var style = state.tokenize(stream, state);
                    state.startOfLine = false;
                    if (style) state.last = style;
                    return styleMap.hasOwnProperty(style) ? styleMap[style] : style;
                  },
            
                  blankLine: function(state) {
                    if (state.subMode && state.subMode.blankLine) {
                      return state.subMode.blankLine(state.subState);
                    }
                  },
            
                  innerMode: function(state) {
                    if (state.subMode) return {state: state.subState, mode: state.subMode};
                    return {state: state, mode: mode};
                  }
            
                  //indent: function(state) {
                  //  return state.indented;
                  //}
                };
                return mode;
              }, "htmlmixed", "ruby");
            
              CodeMirror.defineMIME("text/x-slim", "slim");
              CodeMirror.defineMIME("application/x-slim", "slim");
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Requires at least one media query
              MT("elementName",
                 "[tag h1] Hey There");
            
              MT("oneElementPerLine",
                 "[tag h1] Hey There .h2");
            
              MT("idShortcut",
                 "[attribute&def #test] Hey There");
            
              MT("tagWithIdShortcuts",
                 "[tag h1][attribute&def #test] Hey There");
            
              MT("classShortcut",
                 "[attribute&qualifier .hello] Hey There");
            
              MT("tagWithIdAndClassShortcuts",
                 "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There");
            
              MT("docType",
                 "[keyword doctype] xml");
            
              MT("comment",
                 "[comment / Hello WORLD]");
            
              MT("notComment",
                 "[tag h1] This is not a / comment ");
            
              MT("attributes",
                 "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}");
            
              MT("multiLineAttributes",
                 "[tag a]([attribute title]=[string \"test\"]",
                 "  ) [attribute href]=[string \"link\"]}");
            
              MT("htmlCode",
                 "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
            
              MT("rubyBlock",
                 "[operator&special =][variable-2 @item]");
            
              MT("selectorRubyBlock",
                 "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]");
            
              MT("nestedRubyBlock",
                  "[tag a]",
                  "  [operator&special =][variable puts] [string \"test\"]");
            
              MT("multilinePlaintext",
                  "[tag p]",
                  "  | Hello,",
                  "    World");
            
              MT("multilineRuby",
                  "[tag p]",
                  "  [comment /# this is a comment]",
                  "     [comment and this is a comment too]",
                  "  | Date/Time",
                  "  [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]",
                  "  [tag strong][operator&special =] [variable now]",
                  "  [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
                  "     [operator&special =][string \"Happy\"]",
                  "     [operator&special =][string \"Belated\"]",
                  "     [operator&special =][string \"Birthday\"]");
            
              MT("multilineComment",
                  "[comment /]",
                  "  [comment Multiline]",
                  "  [comment Comment]");
            
              MT("hamlAfterRubyTag",
                "[attribute&qualifier .block]",
                "  [tag strong][operator&special =] [variable now]",
                "  [attribute&qualifier .test]",
                "     [operator&special =][variable now]",
                "  [attribute&qualifier .right]");
            
              MT("stretchedRuby",
                 "[operator&special =] [variable puts] [string \"Hello\"],",
                 "   [string \"World\"]");
            
              MT("interpolationInHashAttribute",
                 "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test");
            
              MT("interpolationInHTMLAttribute",
                 "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test");
            })();
            
        • smalltalk
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Smalltalk mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="smalltalk.js"></script>
            <style>
                  .CodeMirror {border: 2px solid #dee; border-right-width: 10px;}
                  .CodeMirror-gutter {border: none; background: #dee;}
                  .CodeMirror-gutter pre {color: white; font-weight: bold;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Smalltalk</a>
              </ul>
            </div>
            
            <article>
            <h2>Smalltalk mode</h2>
            <form><textarea id="code" name="code">
            " 
                This is a test of the Smalltalk code
            "
            Seaside.WAComponent subclass: #MyCounter [
                | count |
                MyCounter class &gt;&gt; canBeRoot [ ^true ]
            
                initialize [
                    super initialize.
                    count := 0.
                ]
                states [ ^{ self } ]
                renderContentOn: html [
                    html heading: count.
                    html anchor callback: [ count := count + 1 ]; with: '++'.
                    html space.
                    html anchor callback: [ count := count - 1 ]; with: '--'.
                ]
            ]
            
            MyCounter registerAsApplication: 'mycounter'
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-stsrc",
                    indentUnit: 4
                  });
                </script>
            
                <p>Simple Smalltalk mode.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-stsrc</code>.</p>
              </article>
            
          • smalltalk.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('smalltalk', function(config) {
            
              var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/;
              var keywords = /true|false|nil|self|super|thisContext/;
            
              var Context = function(tokenizer, parent) {
                this.next = tokenizer;
                this.parent = parent;
              };
            
              var Token = function(name, context, eos) {
                this.name = name;
                this.context = context;
                this.eos = eos;
              };
            
              var State = function() {
                this.context = new Context(next, null);
                this.expectVariable = true;
                this.indentation = 0;
                this.userIndentationDelta = 0;
              };
            
              State.prototype.userIndent = function(indentation) {
                this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;
              };
            
              var next = function(stream, context, state) {
                var token = new Token(null, context, false);
                var aChar = stream.next();
            
                if (aChar === '"') {
                  token = nextComment(stream, new Context(nextComment, context));
            
                } else if (aChar === '\'') {
                  token = nextString(stream, new Context(nextString, context));
            
                } else if (aChar === '#') {
                  if (stream.peek() === '\'') {
                    stream.next();
                    token = nextSymbol(stream, new Context(nextSymbol, context));
                  } else {
                    if (stream.eatWhile(/[^\s.{}\[\]()]/))
                      token.name = 'string-2';
                    else
                      token.name = 'meta';
                  }
            
                } else if (aChar === '$') {
                  if (stream.next() === '<') {
                    stream.eatWhile(/[^\s>]/);
                    stream.next();
                  }
                  token.name = 'string-2';
            
                } else if (aChar === '|' && state.expectVariable) {
                  token.context = new Context(nextTemporaries, context);
            
                } else if (/[\[\]{}()]/.test(aChar)) {
                  token.name = 'bracket';
                  token.eos = /[\[{(]/.test(aChar);
            
                  if (aChar === '[') {
                    state.indentation++;
                  } else if (aChar === ']') {
                    state.indentation = Math.max(0, state.indentation - 1);
                  }
            
                } else if (specialChars.test(aChar)) {
                  stream.eatWhile(specialChars);
                  token.name = 'operator';
                  token.eos = aChar !== ';'; // ; cascaded message expression
            
                } else if (/\d/.test(aChar)) {
                  stream.eatWhile(/[\w\d]/);
                  token.name = 'number';
            
                } else if (/[\w_]/.test(aChar)) {
                  stream.eatWhile(/[\w\d_]/);
                  token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
            
                } else {
                  token.eos = state.expectVariable;
                }
            
                return token;
              };
            
              var nextComment = function(stream, context) {
                stream.eatWhile(/[^"]/);
                return new Token('comment', stream.eat('"') ? context.parent : context, true);
              };
            
              var nextString = function(stream, context) {
                stream.eatWhile(/[^']/);
                return new Token('string', stream.eat('\'') ? context.parent : context, false);
              };
            
              var nextSymbol = function(stream, context) {
                stream.eatWhile(/[^']/);
                return new Token('string-2', stream.eat('\'') ? context.parent : context, false);
              };
            
              var nextTemporaries = function(stream, context) {
                var token = new Token(null, context, false);
                var aChar = stream.next();
            
                if (aChar === '|') {
                  token.context = context.parent;
                  token.eos = true;
            
                } else {
                  stream.eatWhile(/[^|]/);
                  token.name = 'variable';
                }
            
                return token;
              };
            
              return {
                startState: function() {
                  return new State;
                },
            
                token: function(stream, state) {
                  state.userIndent(stream.indentation());
            
                  if (stream.eatSpace()) {
                    return null;
                  }
            
                  var token = state.context.next(stream, state.context, state);
                  state.context = token.context;
                  state.expectVariable = token.eos;
            
                  return token.name;
                },
            
                blankLine: function(state) {
                  state.userIndent(0);
                },
            
                indent: function(state, textAfter) {
                  var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;
                  return (state.indentation + i) * config.indentUnit;
                },
            
                electricChars: ']'
              };
            
            });
            
            CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});
            
            });
            
        • smarty
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Smarty mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="smarty.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Smarty</a>
              </ul>
            </div>
            
            <article>
            <h2>Smarty mode</h2>
            <form><textarea id="code" name="code">
            {extends file="parent.tpl"}
            {include file="template.tpl"}
            
            {* some example Smarty content *}
            {if isset($name) && $name == 'Blog'}
              This is a {$var}.
              {$integer = 451}, {$array[] = "a"}, {$stringvar = "string"}
              {assign var='bob' value=$var.prop}
            {elseif $name == $foo}
              {function name=menu level=0}
                {foreach $data as $entry}
                  {if is_array($entry)}
                    - {$entry@key}
                    {menu data=$entry level=$level+1}
                  {else}
                    {$entry}
                  {/if}
                {/foreach}
              {/function}
            {/if}</textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "smarty"
                  });
                </script>
            
                <br />
            
            	<h3>Smarty 2, custom delimiters</h3>
                <form><textarea id="code2" name="code2">
            {--extends file="parent.tpl"--}
            {--include file="template.tpl"--}
            
            {--* some example Smarty content *--}
            {--if isset($name) && $name == 'Blog'--}
              This is a {--$var--}.
              {--$integer = 451--}, {--$array[] = "a"--}, {--$stringvar = "string"--}
              {--assign var='bob' value=$var.prop--}
            {--elseif $name == $foo--}
              {--function name=menu level=0--}
                {--foreach $data as $entry--}
                  {--if is_array($entry)--}
                    - {--$entry@key--}
                    {--menu data=$entry level=$level+1--}
                  {--else--}
                    {--$entry--}
                  {--/if--}
                {--/foreach--}
              {--/function--}
            {--/if--}</textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
                    lineNumbers: true,
                    mode: {
                      name: "smarty",
                      leftDelimiter: "{--",
                      rightDelimiter: "--}"
                    }
                  });
                </script>
            
            	<br />
            
            	<h3>Smarty 3</h3>
            
            	<textarea id="code3" name="code3">
            Nested tags {$foo={counter one=1 two={inception}}+3} are now valid in Smarty 3.
            
            <script>
            function test() {
            	console.log("Smarty 3 permits single curly braces followed by whitespace to NOT slip into Smarty mode.");
            }
            </script>
            
            {assign var=foo value=[1,2,3]}
            {assign var=foo value=['y'=>'yellow','b'=>'blue']}
            {assign var=foo value=[1,[9,8],3]}
            
            {$foo=$bar+2} {* a comment *}
            {$foo.bar=1}  {* another comment *}
            {$foo = myfunct(($x+$y)*3)}
            {$foo = strlen($bar)}
            {$foo.bar.baz=1}, {$foo[]=1}
            
            Smarty "dot" syntax (note: embedded {} are used to address ambiguities):
            
            {$foo.a.b.c}      => $foo['a']['b']['c']
            {$foo.a.$b.c}     => $foo['a'][$b]['c']
            {$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c']
            {$foo.a.{$b.c}}   => $foo['a'][$b['c']]
            
            {$object->method1($x)->method2($y)}</textarea>
            
            	<script>
            		var editor = CodeMirror.fromTextArea(document.getElementById("code3"), {
            			lineNumbers: true,
            			mode: "smarty",
            			smartyVersion: 3
            		});
            	</script>
            
            
                <p>A plain text/Smarty version 2 or 3 mode, which allows for custom delimiter tags.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-smarty</code></p>
              </article>
            
          • smarty.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Smarty 2 and 3 mode.
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("smarty", function(config) {
              "use strict";
            
              // our default settings; check to see if they're overridden
              var settings = {
                rightDelimiter: '}',
                leftDelimiter: '{',
                smartyVersion: 2 // for backward compatibility
              };
              if (config.hasOwnProperty("leftDelimiter")) {
                settings.leftDelimiter = config.leftDelimiter;
              }
              if (config.hasOwnProperty("rightDelimiter")) {
                settings.rightDelimiter = config.rightDelimiter;
              }
              if (config.hasOwnProperty("smartyVersion") && config.smartyVersion === 3) {
                settings.smartyVersion = 3;
              }
            
              var keyFunctions = ["debug", "extends", "function", "include", "literal"];
              var last;
              var regs = {
                operatorChars: /[+\-*&%=<>!?]/,
                validIdentifier: /[a-zA-Z0-9_]/,
                stringChar: /['"]/
              };
            
              var helpers = {
                cont: function(style, lastType) {
                  last = lastType;
                  return style;
                },
                chain: function(stream, state, parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
              };
            
            
              // our various parsers
              var parsers = {
            
                // the main tokenizer
                tokenizer: function(stream, state) {
                  if (stream.match(settings.leftDelimiter, true)) {
                    if (stream.eat("*")) {
                      return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
                    } else {
                      // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
                      state.depth++;
                      var isEol = stream.eol();
                      var isFollowedByWhitespace = /\s/.test(stream.peek());
                      if (settings.smartyVersion === 3 && settings.leftDelimiter === "{" && (isEol || isFollowedByWhitespace)) {
                        state.depth--;
                        return null;
                      } else {
                        state.tokenize = parsers.smarty;
                        last = "startTag";
                        return "tag";
                      }
                    }
                  } else {
                    stream.next();
                    return null;
                  }
                },
            
                // parsing Smarty content
                smarty: function(stream, state) {
                  if (stream.match(settings.rightDelimiter, true)) {
                    if (settings.smartyVersion === 3) {
                      state.depth--;
                      if (state.depth <= 0) {
                        state.tokenize = parsers.tokenizer;
                      }
                    } else {
                      state.tokenize = parsers.tokenizer;
                    }
                    return helpers.cont("tag", null);
                  }
            
                  if (stream.match(settings.leftDelimiter, true)) {
                    state.depth++;
                    return helpers.cont("tag", "startTag");
                  }
            
                  var ch = stream.next();
                  if (ch == "$") {
                    stream.eatWhile(regs.validIdentifier);
                    return helpers.cont("variable-2", "variable");
                  } else if (ch == "|") {
                    return helpers.cont("operator", "pipe");
                  } else if (ch == ".") {
                    return helpers.cont("operator", "property");
                  } else if (regs.stringChar.test(ch)) {
                    state.tokenize = parsers.inAttribute(ch);
                    return helpers.cont("string", "string");
                  } else if (regs.operatorChars.test(ch)) {
                    stream.eatWhile(regs.operatorChars);
                    return helpers.cont("operator", "operator");
                  } else if (ch == "[" || ch == "]") {
                    return helpers.cont("bracket", "bracket");
                  } else if (ch == "(" || ch == ")") {
                    return helpers.cont("bracket", "operator");
                  } else if (/\d/.test(ch)) {
                    stream.eatWhile(/\d/);
                    return helpers.cont("number", "number");
                  } else {
            
                    if (state.last == "variable") {
                      if (ch == "@") {
                        stream.eatWhile(regs.validIdentifier);
                        return helpers.cont("property", "property");
                      } else if (ch == "|") {
                        stream.eatWhile(regs.validIdentifier);
                        return helpers.cont("qualifier", "modifier");
                      }
                    } else if (state.last == "pipe") {
                      stream.eatWhile(regs.validIdentifier);
                      return helpers.cont("qualifier", "modifier");
                    } else if (state.last == "whitespace") {
                      stream.eatWhile(regs.validIdentifier);
                      return helpers.cont("attribute", "modifier");
                    } if (state.last == "property") {
                      stream.eatWhile(regs.validIdentifier);
                      return helpers.cont("property", null);
                    } else if (/\s/.test(ch)) {
                      last = "whitespace";
                      return null;
                    }
            
                    var str = "";
                    if (ch != "/") {
                      str += ch;
                    }
                    var c = null;
                    while (c = stream.eat(regs.validIdentifier)) {
                      str += c;
                    }
                    for (var i=0, j=keyFunctions.length; i<j; i++) {
                      if (keyFunctions[i] == str) {
                        return helpers.cont("keyword", "keyword");
                      }
                    }
                    if (/\s/.test(ch)) {
                      return null;
                    }
                    return helpers.cont("tag", "tag");
                  }
                },
            
                inAttribute: function(quote) {
                  return function(stream, state) {
                    var prevChar = null;
                    var currChar = null;
                    while (!stream.eol()) {
                      currChar = stream.peek();
                      if (stream.next() == quote && prevChar !== '\\') {
                        state.tokenize = parsers.smarty;
                        break;
                      }
                      prevChar = currChar;
                    }
                    return "string";
                  };
                },
            
                inBlock: function(style, terminator) {
                  return function(stream, state) {
                    while (!stream.eol()) {
                      if (stream.match(terminator)) {
                        state.tokenize = parsers.tokenizer;
                        break;
                      }
                      stream.next();
                    }
                    return style;
                  };
                }
              };
            
            
              // the public API for CodeMirror
              return {
                startState: function() {
                  return {
                    tokenize: parsers.tokenizer,
                    mode: "smarty",
                    last: null,
                    depth: 0
                  };
                },
                token: function(stream, state) {
                  var style = state.tokenize(stream, state);
                  state.last = last;
                  return style;
                },
                electricChars: ""
              };
            });
            
            CodeMirror.defineMIME("text/x-smarty", "smarty");
            
            });
            
        • smartymixed
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Smarty mixed mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../mode/xml/xml.js"></script>
            <script src="../../mode/javascript/javascript.js"></script>
            <script src="../../mode/css/css.js"></script>
            <script src="../../mode/htmlmixed/htmlmixed.js"></script>
            <script src="../../mode/smarty/smarty.js"></script>
            <script src="../../mode/smartymixed/smartymixed.js"></script>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Smarty mixed</a>
              </ul>
            </div>
            
            <article>
            <h2>Smarty mixed mode</h2>
            <form><textarea id="code" name="code">
            {**
            * @brief Smarty mixed mode
            * @author Ruslan Osmanov
            * @date 29.06.2013
            *}
            <html>
            <head>
              <title>{$title|htmlspecialchars|truncate:30}</title>
            </head>
            <body class="{$bodyclass}">
              {* Multiline smarty
              * comment, no {$variables} here
              *}
              {literal}
              {literal} is just an HTML text.
              <script type="text/javascript">//<![CDATA[
                var a = {$just_a_normal_js_object : "value"};
                var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode           : "smartymixed",
                  tabSize        : 2,
                  indentUnit     : 2,
                  indentWithTabs : false,
                  lineNumbers    : true,
                  smartyVersion  : 3
                });
                // ]]>
              </script>
              <style>
                /* CSS content 
                {$no_smarty} */
                .some-class { font-weight: bolder; color: "orange"; }
              </style>
              {/literal}
            
              {extends file="parent.tpl"}
              {include file="template.tpl"}
            
              {* some example Smarty content *}
              {if isset($name) && $name == 'Blog'}
                This is a {$var}.
                {$integer = 4511}, {$array[] = "a"}, {$stringvar = "string"}
                {$integer = 4512} {$array[] = "a"} {$stringvar = "string"}
                {assign var='bob' value=$var.prop}
              {elseif $name == $foo}
                {function name=menu level=0}
                {foreach $data as $entry}
                  {if is_array($entry)}
                  - {$entry@key}
                  {menu data=$entry level=$level+1}
                  {else}
                  {$entry}
                  {* One
                  * Two
                  * Three
                  *}
                  {/if}
                {/foreach}
                {/function}
              {/if}
              </body>
              <!-- R.O. -->
            </html>
            </textarea></form>
            
                <script type="text/javascript">
                  var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode           : "smartymixed",
                    tabSize        : 2,
                    indentUnit     : 2,
                    indentWithTabs : false,
                    lineNumbers    : true,
                    smartyVersion  : 3,
                    matchBrackets  : true,
                  });
                </script>
            
                <p>The Smarty mixed mode depends on the Smarty and HTML mixed modes. HTML
                mixed mode itself depends on XML, JavaScript, and CSS modes.</p>
            
                <p>It takes the same options, as Smarty and HTML mixed modes.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-smarty</code>.</p>
              </article>
            
          • smartymixed.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
            * @file smartymixed.js
            * @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)
            * @author Ruslan Osmanov <rrosmanov at gmail dot com>
            * @version 3.0
            * @date 05.07.2013
            */
            
            // Warning: Don't base other modes on this one. This here is a
            // terrible way to write a mixed mode.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../smarty/smarty"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../smarty/smarty"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("smartymixed", function(config) {
              var htmlMixedMode = CodeMirror.getMode(config, "htmlmixed");
              var smartyMode = CodeMirror.getMode(config, "smarty");
            
              var settings = {
                rightDelimiter: '}',
                leftDelimiter: '{'
              };
            
              if (config.hasOwnProperty("leftDelimiter")) {
                settings.leftDelimiter = config.leftDelimiter;
              }
              if (config.hasOwnProperty("rightDelimiter")) {
                settings.rightDelimiter = config.rightDelimiter;
              }
            
              function reEsc(str) { return str.replace(/[^\s\w]/g, "\\$&"); }
            
              var reLeft = reEsc(settings.leftDelimiter), reRight = reEsc(settings.rightDelimiter);
              var regs = {
                smartyComment: new RegExp("^" + reRight + "\\*"),
                literalOpen: new RegExp(reLeft + "literal" + reRight),
                literalClose: new RegExp(reLeft + "\/literal" + reRight),
                hasLeftDelimeter: new RegExp(".*" + reLeft),
                htmlHasLeftDelimeter: new RegExp("[^<>]*" + reLeft)
              };
            
              var helpers = {
                chain: function(stream, state, parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                },
            
                cleanChain: function(stream, state, parser) {
                  state.tokenize = null;
                  state.localState = null;
                  state.localMode = null;
                  return (typeof parser == "string") ? (parser ? parser : null) : parser(stream, state);
                },
            
                maybeBackup: function(stream, pat, style) {
                  var cur = stream.current();
                  var close = cur.search(pat),
                  m;
                  if (close > - 1) stream.backUp(cur.length - close);
                  else if (m = cur.match(/<\/?$/)) {
                    stream.backUp(cur.length);
                    if (!stream.match(pat, false)) stream.match(cur[0]);
                  }
                  return style;
                }
              };
            
              var parsers = {
                html: function(stream, state) {
                  var htmlTagName = state.htmlMixedState.htmlState.context && state.htmlMixedState.htmlState.context.tagName
                    ? state.htmlMixedState.htmlState.context.tagName
                    : null;
            
                  if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && htmlTagName === null) {
                    state.tokenize = parsers.smarty;
                    state.localMode = smartyMode;
                    state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));
                    return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));
                  } else if (!state.inLiteral && stream.match(settings.leftDelimiter, false)) {
                    state.tokenize = parsers.smarty;
                    state.localMode = smartyMode;
                    state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));
                    return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));
                  }
                  return htmlMixedMode.token(stream, state.htmlMixedState);
                },
            
                smarty: function(stream, state) {
                  if (stream.match(settings.leftDelimiter, false)) {
                    if (stream.match(regs.smartyComment, false)) {
                      return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
                    }
                  } else if (stream.match(settings.rightDelimiter, false)) {
                    stream.eat(settings.rightDelimiter);
                    state.tokenize = parsers.html;
                    state.localMode = htmlMixedMode;
                    state.localState = state.htmlMixedState;
                    return "tag";
                  }
            
                  return helpers.maybeBackup(stream, settings.rightDelimiter, smartyMode.token(stream, state.localState));
                },
            
                inBlock: function(style, terminator) {
                  return function(stream, state) {
                    while (!stream.eol()) {
                      if (stream.match(terminator)) {
                        helpers.cleanChain(stream, state, "");
                        break;
                      }
                      stream.next();
                    }
                    return style;
                  };
                }
              };
            
              return {
                startState: function() {
                  var state = htmlMixedMode.startState();
                  return {
                    token: parsers.html,
                    localMode: null,
                    localState: null,
                    htmlMixedState: state,
                    tokenize: null,
                    inLiteral: false
                  };
                },
            
                copyState: function(state) {
                  var local = null, tok = (state.tokenize || state.token);
                  if (state.localState) {
                    local = CodeMirror.copyState((tok != parsers.html ? smartyMode : htmlMixedMode), state.localState);
                  }
                  return {
                    token: state.token,
                    tokenize: state.tokenize,
                    localMode: state.localMode,
                    localState: local,
                    htmlMixedState: CodeMirror.copyState(htmlMixedMode, state.htmlMixedState),
                    inLiteral: state.inLiteral
                  };
                },
            
                token: function(stream, state) {
                  if (stream.match(settings.leftDelimiter, false)) {
                    if (!state.inLiteral && stream.match(regs.literalOpen, true)) {
                      state.inLiteral = true;
                      return "keyword";
                    } else if (state.inLiteral && stream.match(regs.literalClose, true)) {
                      state.inLiteral = false;
                      return "keyword";
                    }
                  }
                  if (state.inLiteral && state.localState != state.htmlMixedState) {
                    state.tokenize = parsers.html;
                    state.localMode = htmlMixedMode;
                    state.localState = state.htmlMixedState;
                  }
            
                  var style = (state.tokenize || state.token)(stream, state);
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.localMode == smartyMode
                      || (state.inLiteral && !state.localMode)
                     || regs.hasLeftDelimeter.test(textAfter)) {
                    return CodeMirror.Pass;
                  }
                  return htmlMixedMode.indent(state.htmlMixedState, textAfter);
                },
            
                innerMode: function(state) {
                  return {
                    state: state.localState || state.htmlMixedState,
                    mode: state.localMode || htmlMixedMode
                  };
                }
              };
            }, "htmlmixed", "smarty");
            
            CodeMirror.defineMIME("text/x-smarty", "smartymixed");
            // vim: et ts=2 sts=2 sw=2
            
            });
            
        • solr
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Solr mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="solr.js"></script>
            <style type="text/css">
              .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
              }
            
              .CodeMirror .cm-operator {
                color: orange;
              }
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Solr</a>
              </ul>
            </div>
            
            <article>
              <h2>Solr mode</h2>
            
              <div>
                <textarea id="code" name="code">author:Camus
            
            title:"The Rebel" and author:Camus
            
            philosophy:Existentialism -author:Kierkegaard
            
            hardToSpell:Dostoevsky~
            
            published:[194* TO 1960] and author:(Sartre or "Simone de Beauvoir")</textarea>
              </div>
            
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: 'solr',
                  lineNumbers: true
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>text/x-solr</code>.</p>
            </article>
            
          • solr.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("solr", function() {
              "use strict";
            
              var isStringChar = /[^\s\|\!\+\-\*\?\~\^\&\:\(\)\[\]\{\}\^\"\\]/;
              var isOperatorChar = /[\|\!\+\-\*\?\~\^\&]/;
              var isOperatorString = /^(OR|AND|NOT|TO)$/i;
            
              function isNumber(word) {
                return parseFloat(word, 10).toString() === word;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) break;
                    escaped = !escaped && next == "\\";
                  }
            
                  if (!escaped) state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenOperator(operator) {
                return function(stream, state) {
                  var style = "operator";
                  if (operator == "+")
                    style += " positive";
                  else if (operator == "-")
                    style += " negative";
                  else if (operator == "|")
                    stream.eat(/\|/);
                  else if (operator == "&")
                    stream.eat(/\&/);
                  else if (operator == "^")
                    style += " boost";
            
                  state.tokenize = tokenBase;
                  return style;
                };
              }
            
              function tokenWord(ch) {
                return function(stream, state) {
                  var word = ch;
                  while ((ch = stream.peek()) && ch.match(isStringChar) != null) {
                    word += stream.next();
                  }
            
                  state.tokenize = tokenBase;
                  if (isOperatorString.test(word))
                    return "operator";
                  else if (isNumber(word))
                    return "number";
                  else if (stream.peek() == ":")
                    return "field";
                  else
                    return "string";
                };
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"')
                  state.tokenize = tokenString(ch);
                else if (isOperatorChar.test(ch))
                  state.tokenize = tokenOperator(ch);
                else if (isStringChar.test(ch))
                  state.tokenize = tokenWord(ch);
            
                return (state.tokenize != tokenBase) ? state.tokenize(stream, state) : null;
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase
                  };
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-solr", "solr");
            
            });
            
        • soy
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Soy (Closure Template) mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="soy.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Soy (Closure Template)</a>
              </ul>
            </div>
            
            <article>
            <h2>Soy (Closure Template) mode</h2>
            <form><textarea id="code" name="code">
            {namespace example}
            
            /**
             * Says hello to the world.
             */
            {template .helloWorld}
              {@param name: string}
              {@param? score: number}
              Hello <b>{$name}</b>!
              <div>
                {if $score}
                  <em>{$score} points</em>
                {else}
                  no score
                {/if}
              </div>
            {/template}
            
            {template .alertHelloWorld kind="js"}
              alert('Hello World');
            {/template}
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-soy",
                    indentUnit: 2,
                    indentWithTabs: false
                  });
                </script>
            
                <p>A mode for <a href="https://developers.google.com/closure/templates/">Closure Templates</a> (Soy).</p>
                <p><strong>MIME type defined:</strong> <code>text/x-soy</code>.</p>
              </article>
            
          • soy.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif",
                                   "else", "switch", "case", "default", "foreach", "ifempty", "for",
                                   "call", "param", "deltemplate", "delcall", "log"];
            
              CodeMirror.defineMode("soy", function(config) {
                var textMode = CodeMirror.getMode(config, "text/plain");
                var modes = {
                  html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}),
                  attributes: textMode,
                  text: textMode,
                  uri: textMode,
                  css: CodeMirror.getMode(config, "text/css"),
                  js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit})
                };
            
                function last(array) {
                  return array[array.length - 1];
                }
            
                function tokenUntil(stream, state, untilRegExp) {
                  var oldString = stream.string;
                  var match = untilRegExp.exec(oldString.substr(stream.pos));
                  if (match) {
                    // We don't use backUp because it backs up just the position, not the state.
                    // This uses an undocumented API.
                    stream.string = oldString.substr(0, stream.pos + match.index);
                  }
                  var result = stream.hideFirstChars(state.indent, function() {
                    return state.localMode.token(stream, state.localState);
                  });
                  stream.string = oldString;
                  return result;
                }
            
                return {
                  startState: function() {
                    return {
                      kind: [],
                      kindTag: [],
                      soyState: [],
                      indent: 0,
                      localMode: modes.html,
                      localState: CodeMirror.startState(modes.html)
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      tag: state.tag, // Last seen Soy tag.
                      kind: state.kind.concat([]), // Values of kind="" attributes.
                      kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes.
                      soyState: state.soyState.concat([]),
                      indent: state.indent, // Indentation of the following line.
                      localMode: state.localMode,
                      localState: CodeMirror.copyState(state.localMode, state.localState)
                    };
                  },
            
                  token: function(stream, state) {
                    var match;
            
                    switch (last(state.soyState)) {
                      case "comment":
                        if (stream.match(/^.*?\*\//)) {
                          state.soyState.pop();
                        } else {
                          stream.skipToEnd();
                        }
                        return "comment";
            
                      case "variable":
                        if (stream.match(/^}/)) {
                          state.indent -= 2 * config.indentUnit;
                          state.soyState.pop();
                          return "variable-2";
                        }
                        stream.next();
                        return null;
            
                      case "tag":
                        if (stream.match(/^\/?}/)) {
                          if (state.tag == "/template" || state.tag == "/deltemplate") state.indent = 0;
                          else state.indent -= (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit;
                          state.soyState.pop();
                          return "keyword";
                        } else if (stream.match(/^(\w+)(?==)/)) {
                          if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) {
                            var kind = match[1];
                            state.kind.push(kind);
                            state.kindTag.push(state.tag);
                            state.localMode = modes[kind] || modes.html;
                            state.localState = CodeMirror.startState(state.localMode);
                          }
                          return "attribute";
                        } else if (stream.match(/^"/)) {
                          state.soyState.push("string");
                          return "string";
                        }
                        stream.next();
                        return null;
            
                      case "literal":
                        if (stream.match(/^(?=\{\/literal})/)) {
                          state.indent -= config.indentUnit;
                          state.soyState.pop();
                          return this.token(stream, state);
                        }
                        return tokenUntil(stream, state, /\{\/literal}/);
            
                      case "string":
                        if (stream.match(/^.*?"/)) {
                          state.soyState.pop();
                        } else {
                          stream.skipToEnd();
                        }
                        return "string";
                    }
            
                    if (stream.match(/^\/\*/)) {
                      state.soyState.push("comment");
                      return "comment";
                    } else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) {
                      return "comment";
                    } else if (stream.match(/^\{\$\w*/)) {
                      state.indent += 2 * config.indentUnit;
                      state.soyState.push("variable");
                      return "variable-2";
                    } else if (stream.match(/^\{literal}/)) {
                      state.indent += config.indentUnit;
                      state.soyState.push("literal");
                      return "keyword";
                    } else if (match = stream.match(/^\{([\/@\\]?\w*)/)) {
                      if (match[1] != "/switch")
                        state.indent += (/^(\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit;
                      state.tag = match[1];
                      if (state.tag == "/" + last(state.kindTag)) {
                        // We found the tag that opened the current kind="".
                        state.kind.pop();
                        state.kindTag.pop();
                        state.localMode = modes[last(state.kind)] || modes.html;
                        state.localState = CodeMirror.startState(state.localMode);
                      }
                      state.soyState.push("tag");
                      return "keyword";
                    }
            
                    return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/);
                  },
            
                  indent: function(state, textAfter) {
                    var indent = state.indent, top = last(state.soyState);
                    if (top == "comment") return CodeMirror.Pass;
            
                    if (top == "literal") {
                      if (/^\{\/literal}/.test(textAfter)) indent -= config.indentUnit;
                    } else {
                      if (/^\s*\{\/(template|deltemplate)\b/.test(textAfter)) return 0;
                      if (/^\{(\/|(fallbackmsg|elseif|else|ifempty)\b)/.test(textAfter)) indent -= config.indentUnit;
                      if (state.tag != "switch" && /^\{(case|default)\b/.test(textAfter)) indent -= config.indentUnit;
                      if (/^\{\/switch\b/.test(textAfter)) indent -= config.indentUnit;
                    }
                    if (indent && state.localMode.indent)
                      indent += state.localMode.indent(state.localState, textAfter);
                    return indent;
                  },
            
                  innerMode: function(state) {
                    if (state.soyState.length && last(state.soyState) != "literal") return null;
                    else return {state: state.localState, mode: state.localMode};
                  },
            
                  electricInput: /^\s*\{(\/|\/template|\/deltemplate|\/switch|fallbackmsg|elseif|else|case|default|ifempty|\/literal\})$/,
                  lineComment: "//",
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  blockCommentContinue: " * ",
                  fold: "indent"
                };
              }, "htmlmixed");
            
              CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat(
                  ["delpackage", "namespace", "alias", "print", "css", "debugger"]));
            
              CodeMirror.defineMIME("text/x-soy", "soy");
            });
            
        • sparql
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SPARQL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="sparql.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SPARQL</a>
              </ul>
            </div>
            
            <article>
            <h2>SPARQL mode</h2>
            <form><textarea id="code" name="code">
            PREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>
            PREFIX dc: &lt;http://purl.org/dc/elements/1.1/>
            PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>
            PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#>
            
            # Comment!
            
            SELECT ?given ?family
            WHERE {
              {
                ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .
                ?annot dc:creator ?c .
                OPTIONAL {?c foaf:givenName ?given ;
                             foaf:familyName ?family }
              } UNION {
                ?c !foaf:knows/foaf:knows? ?thing.
                ?thing rdfs
              } MINUS {
                ?thing rdfs:label "剛柔流"@jp
              }
              FILTER isBlank(?c)
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "application/sparql-query",
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/sparql-query</code>.</p>
            
              </article>
            
          • sparql.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sparql", function(config) {
              var indentUnit = config.indentUnit;
              var curPunc;
            
              function wordRegexp(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
                                    "iri", "uri", "bnode", "count", "sum", "min", "max", "avg", "sample",
                                    "group_concat", "rand", "abs", "ceil", "floor", "round", "concat", "substr", "strlen",
                                    "replace", "ucase", "lcase", "encode_for_uri", "contains", "strstarts", "strends",
                                    "strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds",
                                    "timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384",
                                    "sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists",
                                    "isblank", "isliteral", "a"]);
              var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
                                         "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
                                         "graph", "by", "asc", "desc", "as", "having", "undef", "values", "group",
                                         "minus", "in", "not", "service", "silent", "using", "insert", "delete", "union",
                                         "true", "false", "with",
                                         "data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]);
              var operatorChars = /[*+\-<>=&|\^\/!\?]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                curPunc = null;
                if (ch == "$" || ch == "?") {
                  if(ch == "?" && stream.match(/\s/, false)){
                    return "operator";
                  }
                  stream.match(/^[\w\d]*/);
                  return "variable-2";
                }
                else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
                  stream.match(/^[^\s\u00a0>]*>?/);
                  return "atom";
                }
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                }
                else if (/[{}\(\),\.;\[\]]/.test(ch)) {
                  curPunc = ch;
                  return "bracket";
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (operatorChars.test(ch)) {
                  stream.eatWhile(operatorChars);
                  return "operator";
                }
                else if (ch == ":") {
                  stream.eatWhile(/[\w\d\._\-]/);
                  return "atom";
                }
                else if (ch == "@") {
                  stream.eatWhile(/[a-z\d\-]/i);
                  return "meta";
                }
                else {
                  stream.eatWhile(/[_\w\d]/);
                  if (stream.eat(":")) {
                    stream.eatWhile(/[\w\d_\-]/);
                    return "atom";
                  }
                  var word = stream.current();
                  if (ops.test(word))
                    return "builtin";
                  else if (keywords.test(word))
                    return "keyword";
                  else
                    return "variable";
                }
              }
            
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
            
              function pushContext(state, type, col) {
                state.context = {prev: state.context, indent: state.indent, col: col, type: type};
              }
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          context: null,
                          indent: 0,
                          col: 0};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null) state.context.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
                    state.context.align = true;
                  }
            
                  if (curPunc == "(") pushContext(state, ")", stream.column());
                  else if (curPunc == "[") pushContext(state, "]", stream.column());
                  else if (curPunc == "{") pushContext(state, "}", stream.column());
                  else if (/[\]\}\)]/.test(curPunc)) {
                    while (state.context && state.context.type == "pattern") popContext(state);
                    if (state.context && curPunc == state.context.type) popContext(state);
                  }
                  else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
                  else if (/atom|string|variable/.test(style) && state.context) {
                    if (/[\}\]]/.test(state.context.type))
                      pushContext(state, "pattern", stream.column());
                    else if (state.context.type == "pattern" && !state.context.align) {
                      state.context.align = true;
                      state.context.col = stream.column();
                    }
                  }
            
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var firstChar = textAfter && textAfter.charAt(0);
                  var context = state.context;
                  if (/[\]\}]/.test(firstChar))
                    while (context && context.type == "pattern") context = context.prev;
            
                  var closing = context && firstChar == context.type;
                  if (!context)
                    return 0;
                  else if (context.type == "pattern")
                    return context.col;
                  else if (context.align)
                    return context.col + (closing ? 0 : 1);
                  else
                    return context.indent + (closing ? 0 : indentUnit);
                }
              };
            });
            
            CodeMirror.defineMIME("application/sparql-query", "sparql");
            
            });
            
        • spreadsheet
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Spreadsheet mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="spreadsheet.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Spreadsheet</a>
              </ul>
            </div>
            
            <article>
              <h2>Spreadsheet mode</h2>
              <form><textarea id="code" name="code">=IF(A1:B2, TRUE, FALSE) / 100</textarea></form>
            
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  matchBrackets: true,
                  extraKeys: {"Tab":  "indentAuto"}
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>text/x-spreadsheet</code>.</p>
              
              <h3>The Spreadsheet Mode</h3>
              <p> Created by <a href="https://github.com/robertleeplummerjr">Robert Plummer</a></p>
            </article>
            
          • spreadsheet.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("spreadsheet", function () {
                return {
                  startState: function () {
                    return {
                      stringType: null,
                      stack: []
                    };
                  },
                  token: function (stream, state) {
                    if (!stream) return;
            
                    //check for state changes
                    if (state.stack.length === 0) {
                      //strings
                      if ((stream.peek() == '"') || (stream.peek() == "'")) {
                        state.stringType = stream.peek();
                        stream.next(); // Skip quote
                        state.stack.unshift("string");
                      }
                    }
            
                    //return state
                    //stack has
                    switch (state.stack[0]) {
                    case "string":
                      while (state.stack[0] === "string" && !stream.eol()) {
                        if (stream.peek() === state.stringType) {
                          stream.next(); // Skip quote
                          state.stack.shift(); // Clear flag
                        } else if (stream.peek() === "\\") {
                          stream.next();
                          stream.next();
                        } else {
                          stream.match(/^.[^\\\"\']*/);
                        }
                      }
                      return "string";
            
                    case "characterClass":
                      while (state.stack[0] === "characterClass" && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./)))
                          state.stack.shift();
                      }
                      return "operator";
                    }
            
                    var peek = stream.peek();
            
                    //no stack
                    switch (peek) {
                    case "[":
                      stream.next();
                      state.stack.unshift("characterClass");
                      return "bracket";
                    case ":":
                      stream.next();
                      return "operator";
                    case "\\":
                      if (stream.match(/\\[a-z]+/)) return "string-2";
                      else return null;
                    case ".":
                    case ",":
                    case ";":
                    case "*":
                    case "-":
                    case "+":
                    case "^":
                    case "<":
                    case "/":
                    case "=":
                      stream.next();
                      return "atom";
                    case "$":
                      stream.next();
                      return "builtin";
                    }
            
                    if (stream.match(/\d+/)) {
                      if (stream.match(/^\w+/)) return "error";
                      return "number";
                    } else if (stream.match(/^[a-zA-Z_]\w*/)) {
                      if (stream.match(/(?=[\(.])/, false)) return "keyword";
                      return "variable-2";
                    } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) {
                      stream.next();
                      return "bracket";
                    } else if (!stream.eatSpace()) {
                      stream.next();
                    }
                    return null;
                  }
                };
              });
            
              CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet");
            });
            
        • sql
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SQL Mode for CodeMirror</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css" />
            <script src="../../lib/codemirror.js"></script>
            <script src="sql.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css" />
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/sql-hint.js"></script>
            <style>
            .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
            }
                    </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SQL Mode for CodeMirror</a>
              </ul>
            </div>
            
            <article>
            <h2>SQL Mode for CodeMirror</h2>
            <form>
                        <textarea id="code" name="code">-- SQL Mode for CodeMirror
            SELECT SQL_NO_CACHE DISTINCT
            		@var1 AS `val1`, @'val2', @global.'sql_mode',
            		1.1 AS `float_val`, .14 AS `another_float`, 0.09e3 AS `int_with_esp`,
            		0xFA5 AS `hex`, x'fa5' AS `hex2`, 0b101 AS `bin`, b'101' AS `bin2`,
            		DATE '1994-01-01' AS `sql_date`, { T "1994-01-01" } AS `odbc_date`,
            		'my string', _utf8'your string', N'her string',
                    TRUE, FALSE, UNKNOWN
            	FROM DUAL
            	-- space needed after '--'
            	# 1 line comment
            	/* multiline
            	comment! */
            	LIMIT 1 OFFSET 0;
            </textarea>
                        </form>
                        <p><strong>MIME types defined:</strong> 
                        <code><a href="?mime=text/x-sql">text/x-sql</a></code>,
                        <code><a href="?mime=text/x-mysql">text/x-mysql</a></code>,
                        <code><a href="?mime=text/x-mariadb">text/x-mariadb</a></code>,
                        <code><a href="?mime=text/x-cassandra">text/x-cassandra</a></code>,
                        <code><a href="?mime=text/x-plsql">text/x-plsql</a></code>,
                        <code><a href="?mime=text/x-mssql">text/x-mssql</a></code>,
                        <code><a href="?mime=text/x-hive">text/x-hive</a></code>.
                    </p>
            <script>
            window.onload = function() {
              var mime = 'text/x-mariadb';
              // get mime type
              if (window.location.href.indexOf('mime=') > -1) {
                mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);
              }
              window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: mime,
                indentWithTabs: true,
                smartIndent: true,
                lineNumbers: true,
                matchBrackets : true,
                autofocus: true,
                extraKeys: {"Ctrl-Space": "autocomplete"},
                hintOptions: {tables: {
                  users: {name: null, score: null, birthDate: null},
                  countries: {name: null, population: null, size: null}
                }}
              });
            };
            </script>
            
            </article>
            
          • sql.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sql", function(config, parserConfig) {
              "use strict";
            
              var client         = parserConfig.client || {},
                  atoms          = parserConfig.atoms || {"false": true, "true": true, "null": true},
                  builtin        = parserConfig.builtin || {},
                  keywords       = parserConfig.keywords || {},
                  operatorChars  = parserConfig.operatorChars || /^[*+\-%<>!=&|~^]/,
                  support        = parserConfig.support || {},
                  hooks          = parserConfig.hooks || {},
                  dateSQL        = parserConfig.dateSQL || {"date" : true, "time" : true, "timestamp" : true};
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                // call hooks from the mime type
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
            
                if (support.hexNumber == true &&
                  ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/))
                  || (ch == "x" || ch == "X") && stream.match(/^'[0-9a-fA-F]+'/))) {
                  // hex
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/hexadecimal-literals.html
                  return "number";
                } else if (support.binaryNumber == true &&
                  (((ch == "b" || ch == "B") && stream.match(/^'[01]+'/))
                  || (ch == "0" && stream.match(/^b[01]+/)))) {
                  // bitstring
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/bit-field-literals.html
                  return "number";
                } else if (ch.charCodeAt(0) > 47 && ch.charCodeAt(0) < 58) {
                  // numbers
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/number-literals.html
                      stream.match(/^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/);
                  support.decimallessFloat == true && stream.eat('.');
                  return "number";
                } else if (ch == "?" && (stream.eatSpace() || stream.eol() || stream.eat(";"))) {
                  // placeholders
                  return "variable-3";
                } else if (ch == "'" || (ch == '"' && support.doubleQuote)) {
                  // strings
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                } else if ((((support.nCharCast == true && (ch == "n" || ch == "N"))
                    || (support.charsetCast == true && ch == "_" && stream.match(/[a-z][a-z0-9]*/i)))
                    && (stream.peek() == "'" || stream.peek() == '"'))) {
                  // charset casting: _utf8'str', N'str', n'str'
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html
                  return "keyword";
                } else if (/^[\(\),\;\[\]]/.test(ch)) {
                  // no highlightning
                  return null;
                } else if (support.commentSlashSlash && ch == "/" && stream.eat("/")) {
                  // 1-line comment
                  stream.skipToEnd();
                  return "comment";
                } else if ((support.commentHash && ch == "#")
                    || (ch == "-" && stream.eat("-") && (!support.commentSpaceRequired || stream.eat(" ")))) {
                  // 1-line comments
                  // ref: https://kb.askmonty.org/en/comment-syntax/
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "/" && stream.eat("*")) {
                  // multi-line comments
                  // ref: https://kb.askmonty.org/en/comment-syntax/
                  state.tokenize = tokenComment;
                  return state.tokenize(stream, state);
                } else if (ch == ".") {
                  // .1 for 0.1
                  if (support.zerolessFloat == true && stream.match(/^(?:\d+(?:e[+-]?\d+)?)/i)) {
                    return "number";
                  }
                  // .table_name (ODBC)
                  // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html
                  if (support.ODBCdotTable == true && stream.match(/^[a-zA-Z_]+/)) {
                    return "variable-2";
                  }
                } else if (operatorChars.test(ch)) {
                  // operators
                  stream.eatWhile(operatorChars);
                  return null;
                } else if (ch == '{' &&
                    (stream.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/) || stream.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/))) {
                  // dates (weird ODBC syntax)
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html
                  return "number";
                } else {
                  stream.eatWhile(/^[_\w\d]/);
                  var word = stream.current().toLowerCase();
                  // dates (standard SQL syntax)
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html
                  if (dateSQL.hasOwnProperty(word) && (stream.match(/^( )+'[^']*'/) || stream.match(/^( )+"[^"]*"/)))
                    return "number";
                  if (atoms.hasOwnProperty(word)) return "atom";
                  if (builtin.hasOwnProperty(word)) return "builtin";
                  if (keywords.hasOwnProperty(word)) return "keyword";
                  if (client.hasOwnProperty(word)) return "string-2";
                  return null;
                }
              }
            
              // 'string', with char specified in quote escaped by '\'
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
              function tokenComment(stream, state) {
                while (true) {
                  if (stream.skipTo("*")) {
                    stream.next();
                    if (stream.eat("/")) {
                      state.tokenize = tokenBase;
                      break;
                    }
                  } else {
                    stream.skipToEnd();
                    break;
                  }
                }
                return "comment";
              }
            
              function pushContext(stream, state, type) {
                state.context = {
                  prev: state.context,
                  indent: stream.indentation(),
                  col: stream.column(),
                  type: type
                };
              }
            
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase, context: null};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null)
                      state.context.align = false;
                  }
                  if (stream.eatSpace()) return null;
            
                  var style = state.tokenize(stream, state);
                  if (style == "comment") return style;
            
                  if (state.context && state.context.align == null)
                    state.context.align = true;
            
                  var tok = stream.current();
                  if (tok == "(")
                    pushContext(stream, state, ")");
                  else if (tok == "[")
                    pushContext(stream, state, "]");
                  else if (state.context && state.context.type == tok)
                    popContext(state);
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var cx = state.context;
                  if (!cx) return CodeMirror.Pass;
                  var closing = textAfter.charAt(0) == cx.type;
                  if (cx.align) return cx.col + (closing ? 0 : 1);
                  else return cx.indent + (closing ? 0 : config.indentUnit);
                },
            
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: support.commentSlashSlash ? "//" : support.commentHash ? "#" : null
              };
            });
            
            (function() {
              "use strict";
            
              // `identifier`
              function hookIdentifier(stream) {
                // MySQL/MariaDB identifiers
                // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html
                var ch;
                while ((ch = stream.next()) != null) {
                  if (ch == "`" && !stream.eat("`")) return "variable-2";
                }
                stream.backUp(stream.current().length - 1);
                return stream.eatWhile(/\w/) ? "variable-2" : null;
              }
            
              // variable token
              function hookVar(stream) {
                // variables
                // @@prefix.varName @varName
                // varName can be quoted with ` or ' or "
                // ref: http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
                if (stream.eat("@")) {
                  stream.match(/^session\./);
                  stream.match(/^local\./);
                  stream.match(/^global\./);
                }
            
                if (stream.eat("'")) {
                  stream.match(/^.*'/);
                  return "variable-2";
                } else if (stream.eat('"')) {
                  stream.match(/^.*"/);
                  return "variable-2";
                } else if (stream.eat("`")) {
                  stream.match(/^.*`/);
                  return "variable-2";
                } else if (stream.match(/^[0-9a-zA-Z$\.\_]+/)) {
                  return "variable-2";
                }
                return null;
              };
            
              // short client keyword token
              function hookClient(stream) {
                // \N means NULL
                // ref: http://dev.mysql.com/doc/refman/5.5/en/null-values.html
                if (stream.eat("N")) {
                    return "atom";
                }
                // \g, etc
                // ref: http://dev.mysql.com/doc/refman/5.5/en/mysql-commands.html
                return stream.match(/^[a-zA-Z.#!?]/) ? "variable-2" : null;
              }
            
              // these keywords are used by all SQL dialects (however, a mode can still overwrite it)
              var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from having in insert into is join like not on or order select set table union update values where ";
            
              // turn a space-separated list into an array
              function set(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // A generic SQL Mode. It's not a standard, it just try to support what is generally supported
              CodeMirror.defineMIME("text/x-sql", {
                name: "sql",
                keywords: set(sqlKeywords + "begin"),
                builtin: set("bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable doubleQuote binaryNumber hexNumber")
              });
            
              CodeMirror.defineMIME("text/x-mssql", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered"),
                builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date datetimeoffset datetime2 smalldatetime datetime time"),
                hooks: {
                  "@":   hookVar
                }
              });
            
              CodeMirror.defineMIME("text/x-mysql", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
                builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=&|^]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
                hooks: {
                  "@":   hookVar,
                  "`":   hookIdentifier,
                  "\\":  hookClient
                }
              });
            
              CodeMirror.defineMIME("text/x-mariadb", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
                builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=&|^]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
                hooks: {
                  "@":   hookVar,
                  "`":   hookIdentifier,
                  "\\":  hookClient
                }
              });
            
              // the query language used by Apache Cassandra is called CQL, but this mime type
              // is called Cassandra to avoid confusion with Contextual Query Language
              CodeMirror.defineMIME("text/x-cassandra", {
                name: "sql",
                client: { },
                keywords: set("use select from using consistency where limit first reversed first and in insert into values using consistency ttl update set delete truncate begin batch apply create keyspace with columnfamily primary key index on drop alter type add any one quorum all local_quorum each_quorum"),
                builtin: set("ascii bigint blob boolean counter decimal double float int text timestamp uuid varchar varint"),
                atoms: set("false true"),
                operatorChars: /^[<>=]/,
                dateSQL: { },
                support: set("commentSlashSlash decimallessFloat"),
                hooks: { }
              });
            
              // this is based on Peter Raganitsch's 'plsql' mode
              CodeMirror.defineMIME("text/x-plsql", {
                name:       "sql",
                client:     set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
                keywords:   set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
                builtin:    set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),
                operatorChars: /^[*+\-%<>!=~]/,
                dateSQL:    set("date time timestamp"),
                support:    set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")
              });
            
              // Created to support specific hive keywords
              CodeMirror.defineMIME("text/x-hive", {
                name: "sql",
                keywords: set("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"),
                builtin: set("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date timestamp"),
                support: set("ODBCdotTable doubleQuote binaryNumber hexNumber")
              });
            }());
            
            });
            
            /*
              How Properties of Mime Types are used by SQL Mode
              =================================================
            
              keywords:
                A list of keywords you want to be highlighted.
              builtin:
                A list of builtin types you want to be highlighted (if you want types to be of class "builtin" instead of "keyword").
              operatorChars:
                All characters that must be handled as operators.
              client:
                Commands parsed and executed by the client (not the server).
              support:
                A list of supported syntaxes which are not common, but are supported by more than 1 DBMS.
                * ODBCdotTable: .tableName
                * zerolessFloat: .1
                * doubleQuote
                * nCharCast: N'string'
                * charsetCast: _utf8'string'
                * commentHash: use # char for comments
                * commentSlashSlash: use // for comments
                * commentSpaceRequired: require a space after -- for comments
              atoms:
                Keywords that must be highlighted as atoms,. Some DBMS's support more atoms than others:
                UNKNOWN, INFINITY, UNDERFLOW, NaN...
              dateSQL:
                Used for date/time SQL standard syntax, because not all DBMS's support same temporal types.
            */
            
        • stex
          • index.html
            <!doctype html>
            
            <title>CodeMirror: sTeX mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="stex.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">sTeX</a>
              </ul>
            </div>
            
            <article>
            <h2>sTeX mode</h2>
            <form><textarea id="code" name="code">
            \begin{module}[id=bbt-size]
            \importmodule[balanced-binary-trees]{balanced-binary-trees}
            \importmodule[\KWARCslides{dmath/en/cardinality}]{cardinality}
            
            \begin{frame}
              \frametitle{Size Lemma for Balanced Trees}
              \begin{itemize}
              \item
                \begin{assertion}[id=size-lemma,type=lemma] 
                Let $G=\tup{V,E}$ be a \termref[cd=binary-trees]{balanced binary tree} 
                of \termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set
                 $\defeq{\livar{V}i}{\setst{\inset{v}{V}}{\gdepth{v} = i}}$ of
                \termref[cd=graphs-intro,name=node]{nodes} at 
                \termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has
                \termref[cd=cardinality,name=cardinality]{cardinality} $\power2i$.
               \end{assertion}
              \item
                \begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}
                  \begin{spfcases}{We have to consider two cases}
                    \begin{spfcase}{$i=0$}
                      \begin{spfstep}[display=flow]
                        then $\livar{V}i=\set{\livar{v}r}$, where $\livar{v}r$ is the root, so
                        $\eq{\card{\livar{V}0},\card{\set{\livar{v}r}},1,\power20}$.
                      \end{spfstep}
                    \end{spfcase}
                    \begin{spfcase}{$i>0$}
                      \begin{spfstep}[display=flow]
                       then $\livar{V}{i-1}$ contains $\power2{i-1}$ vertexes 
                       \begin{justification}[method=byIH](IH)\end{justification}
                      \end{spfstep}
                      \begin{spfstep}
                       By the \begin{justification}[method=byDef]definition of a binary
                          tree\end{justification}, each $\inset{v}{\livar{V}{i-1}}$ is a leaf or has
                        two children that are at depth $i$.
                      \end{spfstep}
                      \begin{spfstep}
                       As $G$ is \termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\gdepth{G}=n>i$, $\livar{V}{i-1}$ cannot contain
                        leaves.
                      \end{spfstep}
                      \begin{spfstep}[type=conclusion]
                       Thus $\eq{\card{\livar{V}i},{\atimes[cdot]{2,\card{\livar{V}{i-1}}}},{\atimes[cdot]{2,\power2{i-1}}},\power2i}$.
                      \end{spfstep}
                    \end{spfcase}
                  \end{spfcases}
                \end{sproof}
              \item 
                \begin{assertion}[id=fbbt,type=corollary]	
                  A fully balanced tree of depth $d$ has $\power2{d+1}-1$ nodes.
                \end{assertion}
              \item
                  \begin{sproof}[for=fbbt,id=fbbt-pf]{}
                    \begin{spfstep}
                      Let $\defeq{G}{\tup{V,E}}$ be a fully balanced tree
                    \end{spfstep}
                    \begin{spfstep}
                      Then $\card{V}=\Sumfromto{i}1d{\power2i}= \power2{d+1}-1$.
                    \end{spfstep}
                  \end{sproof}
                \end{itemize}
              \end{frame}
            \begin{note}
              \begin{omtext}[type=conclusion,for=binary-tree]
                This shows that balanced binary trees grow in breadth very quickly, a consequence of
                this is that they are very shallow (and this compute very fast), which is the essence of
                the next result.
              \end{omtext}
            \end{note}
            \end{module}
            
            %%% Local Variables: 
            %%% mode: LaTeX
            %%% TeX-master: "all"
            %%% End: \end{document}
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#stex_*">normal</a>,  <a href="../../test/index.html#verbose,stex_*">verbose</a>.</p>
            
              </article>
            
          • stex.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
             * Licence: MIT
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("stex", function() {
                "use strict";
            
                function pushCommand(state, command) {
                  state.cmdState.push(command);
                }
            
                function peekCommand(state) {
                  if (state.cmdState.length > 0) {
                    return state.cmdState[state.cmdState.length - 1];
                  } else {
                    return null;
                  }
                }
            
                function popCommand(state) {
                  var plug = state.cmdState.pop();
                  if (plug) {
                    plug.closeBracket();
                  }
                }
            
                // returns the non-default plugin closest to the end of the list
                function getMostPowerful(state) {
                  var context = state.cmdState;
                  for (var i = context.length - 1; i >= 0; i--) {
                    var plug = context[i];
                    if (plug.name == "DEFAULT") {
                      continue;
                    }
                    return plug;
                  }
                  return { styleIdentifier: function() { return null; } };
                }
            
                function addPluginPattern(pluginName, cmdStyle, styles) {
                  return function () {
                    this.name = pluginName;
                    this.bracketNo = 0;
                    this.style = cmdStyle;
                    this.styles = styles;
                    this.argument = null;   // \begin and \end have arguments that follow. These are stored in the plugin
            
                    this.styleIdentifier = function() {
                      return this.styles[this.bracketNo - 1] || null;
                    };
                    this.openBracket = function() {
                      this.bracketNo++;
                      return "bracket";
                    };
                    this.closeBracket = function() {};
                  };
                }
            
                var plugins = {};
            
                plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
                plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
                plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
                plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
                plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
            
                plugins["DEFAULT"] = function () {
                  this.name = "DEFAULT";
                  this.style = "tag";
            
                  this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
                };
            
                function setState(state, f) {
                  state.f = f;
                }
            
                // called when in a normal (no environment) context
                function normal(source, state) {
                  var plug;
                  // Do we look like '\command' ?  If so, attempt to apply the plugin 'command'
                  if (source.match(/^\\[a-zA-Z@]+/)) {
                    var cmdName = source.current().slice(1);
                    plug = plugins[cmdName] || plugins["DEFAULT"];
                    plug = new plug();
                    pushCommand(state, plug);
                    setState(state, beginParams);
                    return plug.style;
                  }
            
                  // escape characters
                  if (source.match(/^\\[$&%#{}_]/)) {
                    return "tag";
                  }
            
                  // white space control characters
                  if (source.match(/^\\[,;!\/\\]/)) {
                    return "tag";
                  }
            
                  // find if we're starting various math modes
                  if (source.match("\\[")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
                    return "keyword";
                  }
                  if (source.match("$$")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
                    return "keyword";
                  }
                  if (source.match("$")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "$"); });
                    return "keyword";
                  }
            
                  var ch = source.next();
                  if (ch == "%") {
                    source.skipToEnd();
                    return "comment";
                  } else if (ch == '}' || ch == ']') {
                    plug = peekCommand(state);
                    if (plug) {
                      plug.closeBracket(ch);
                      setState(state, beginParams);
                    } else {
                      return "error";
                    }
                    return "bracket";
                  } else if (ch == '{' || ch == '[') {
                    plug = plugins["DEFAULT"];
                    plug = new plug();
                    pushCommand(state, plug);
                    return "bracket";
                  } else if (/\d/.test(ch)) {
                    source.eatWhile(/[\w.%]/);
                    return "atom";
                  } else {
                    source.eatWhile(/[\w\-_]/);
                    plug = getMostPowerful(state);
                    if (plug.name == 'begin') {
                      plug.argument = source.current();
                    }
                    return plug.styleIdentifier();
                  }
                }
            
                function inMathMode(source, state, endModeSeq) {
                  if (source.eatSpace()) {
                    return null;
                  }
                  if (source.match(endModeSeq)) {
                    setState(state, normal);
                    return "keyword";
                  }
                  if (source.match(/^\\[a-zA-Z@]+/)) {
                    return "tag";
                  }
                  if (source.match(/^[a-zA-Z]+/)) {
                    return "variable-2";
                  }
                  // escape characters
                  if (source.match(/^\\[$&%#{}_]/)) {
                    return "tag";
                  }
                  // white space control characters
                  if (source.match(/^\\[,;!\/]/)) {
                    return "tag";
                  }
                  // special math-mode characters
                  if (source.match(/^[\^_&]/)) {
                    return "tag";
                  }
                  // non-special characters
                  if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
                    return null;
                  }
                  if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
                    return "number";
                  }
                  var ch = source.next();
                  if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
                    return "bracket";
                  }
            
                  if (ch == "%") {
                    source.skipToEnd();
                    return "comment";
                  }
                  return "error";
                }
            
                function beginParams(source, state) {
                  var ch = source.peek(), lastPlug;
                  if (ch == '{' || ch == '[') {
                    lastPlug = peekCommand(state);
                    lastPlug.openBracket(ch);
                    source.eat(ch);
                    setState(state, normal);
                    return "bracket";
                  }
                  if (/[ \t\r]/.test(ch)) {
                    source.eat(ch);
                    return null;
                  }
                  setState(state, normal);
                  popCommand(state);
            
                  return normal(source, state);
                }
            
                return {
                  startState: function() {
                    return {
                      cmdState: [],
                      f: normal
                    };
                  },
                  copyState: function(s) {
                    return {
                      cmdState: s.cmdState.slice(),
                      f: s.f
                    };
                  },
                  token: function(stream, state) {
                    return state.f(stream, state);
                  },
                  blankLine: function(state) {
                    state.f = normal;
                    state.cmdState.length = 0;
                  },
                  lineComment: "%"
                };
              });
            
              CodeMirror.defineMIME("text/x-stex", "stex");
              CodeMirror.defineMIME("text/x-latex", "stex");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "stex");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("word",
                 "foo");
            
              MT("twoWords",
                 "foo bar");
            
              MT("beginEndDocument",
                 "[tag \\begin][bracket {][atom document][bracket }]",
                 "[tag \\end][bracket {][atom document][bracket }]");
            
              MT("beginEndEquation",
                 "[tag \\begin][bracket {][atom equation][bracket }]",
                 "  E=mc^2",
                 "[tag \\end][bracket {][atom equation][bracket }]");
            
              MT("beginModule",
                 "[tag \\begin][bracket {][atom module][bracket }[[]]]");
            
              MT("beginModuleId",
                 "[tag \\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]");
            
              MT("importModule",
                 "[tag \\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]");
            
              MT("importModulePath",
                 "[tag \\importmodule][bracket [[][tag \\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]");
            
              MT("psForPDF",
                 "[tag \\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]");
            
              MT("comment",
                 "[comment % foo]");
            
              MT("tagComment",
                 "[tag \\item][comment % bar]");
            
              MT("commentTag",
                 " [comment % \\item]");
            
              MT("commentLineBreak",
                 "[comment %]",
                 "foo");
            
              MT("tagErrorCurly",
                 "[tag \\begin][error }][bracket {]");
            
              MT("tagErrorSquare",
                 "[tag \\item][error ]]][bracket {]");
            
              MT("commentCurly",
                 "[comment % }]");
            
              MT("tagHash",
                 "the [tag \\#] key");
            
              MT("tagNumber",
                 "a [tag \\$][atom 5] stetson");
            
              MT("tagPercent",
                 "[atom 100][tag \\%] beef");
            
              MT("tagAmpersand",
                 "L [tag \\&] N");
            
              MT("tagUnderscore",
                 "foo[tag \\_]bar");
            
              MT("tagBracketOpen",
                 "[tag \\emph][bracket {][tag \\{][bracket }]");
            
              MT("tagBracketClose",
                 "[tag \\emph][bracket {][tag \\}][bracket }]");
            
              MT("tagLetterNumber",
                 "section [tag \\S][atom 1]");
            
              MT("textTagNumber",
                 "para [tag \\P][atom 2]");
            
              MT("thinspace",
                 "x[tag \\,]y");
            
              MT("thickspace",
                 "x[tag \\;]y");
            
              MT("negativeThinspace",
                 "x[tag \\!]y");
            
              MT("periodNotSentence",
                 "J.\\ L.\\ is");
            
              MT("periodSentence",
                 "X[tag \\@]. The");
            
              MT("italicCorrection",
                 "[bracket {][tag \\em] If[tag \\/][bracket }] I");
            
              MT("tagBracket",
                 "[tag \\newcommand][bracket {][tag \\pop][bracket }]");
            
              MT("inlineMathTagFollowedByNumber",
                 "[keyword $][tag \\pi][number 2][keyword $]");
            
              MT("inlineMath",
                 "[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text");
            
              MT("displayMath",
                 "More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text");
            
              MT("mathWithComment",
                 "[keyword $][variable-2 x] [comment % $]",
                 "[variable-2 y][keyword $] other text");
            
              MT("lineBreakArgument",
                "[tag \\\\][bracket [[][atom 1cm][bracket ]]]");
            })();
            
        • stylus
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Stylus mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="stylus.js"></script>
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/css-hint.js"></script>
            <style>.CodeMirror {background: #f8f8f8;} form{margin-bottom: .7em;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Stylus</a>
              </ul>
            </div>
            
            <article>
            <h2>Stylus mode</h2>
            <form><textarea id="code" name="code">
            /* Stylus mode */
            #id
            .class
            article
              font-family Arial, sans-serif
            
            #id,
            .class,
            article {
              font-family: Arial, sans-serif;
            }
            
            // Variables
            font-size-base = 16px
            line-height-base = 1.5
            font-family-base = "Helvetica Neue", Helvetica, Arial, sans-serif
            text-color = lighten(#000, 20%)
            
            body
              font font-size-base/line-height-base font-family-base
              color text-color
            
            body {
              font: 400 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
              color: #333;
            }
            
            // Variables
            link-color = darken(#428bca, 6.5%)
            link-hover-color = darken(link-color, 15%)
            link-decoration = none
            link-hover-decoration = false
            
            // Mixin
            tab-focus()
              outline thin dotted
              outline 5px auto -webkit-focus-ring-color
              outline-offset -2px
            
            a
              color link-color
              if link-decoration
                text-decoration link-decoration
              &:hover
              &:focus
                color link-hover-color
                if link-hover-decoration
                  text-decoration link-hover-decoration
              &:focus
                tab-focus()
            
            a {
              color: #3782c4;
              text-decoration: none;
            }
            a:hover,
            a:focus {
              color: #2f6ea7;
            }
            a:focus {
              outline: thin dotted;
              outline: 5px auto -webkit-focus-ring-color;
              outline-offset: -2px;
            }
            </textarea>
            </form>
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                extraKeys: {"Ctrl-Space": "autocomplete"},
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-styl</code>.</p>
            
            </article>
            
          • stylus.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("stylus", function(config) {
            
                var operatorsRegexp = /^(\?:?|\+[+=]?|-[\-=]?|\*[\*=]?|\/=?|[=!:\?]?=|<=?|>=?|%=?|&&|\|=?|\~|!|\^|\\)/,
                    delimitersRegexp = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/,
                    wordOperatorsRegexp = wordRegexp(wordOperators),
                    commonKeywordsRegexp = wordRegexp(commonKeywords),
                    commonAtomsRegexp = wordRegexp(commonAtoms),
                    commonDefRegexp = wordRegexp(commonDef),
                    vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/),
                    cssValuesWithBracketsRegexp = new RegExp("^(" + cssValuesWithBrackets_.join("|") + ")\\([\\w\-\\#\\,\\.\\%\\s\\(\\)]*\\)");
            
                var tokenBase = function(stream, state) {
            
                  if (stream.eatSpace()) return null;
            
                  var ch = stream.peek();
            
                  // Single line Comment
                  if (stream.match('//')) {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  // Multiline Comment
                  if (stream.match('/*')) {
                    state.tokenizer = multilineComment;
                    return state.tokenizer(stream, state);
                  }
            
                  // Strings
                  if (ch === '"' || ch === "'") {
                    stream.next();
                    state.tokenizer = buildStringTokenizer(ch);
                    return "string";
                  }
            
                  // Def
                  if (ch === "@") {
                    stream.next();
                    if (stream.match(/extend/)) {
                      dedent(state); // remove indentation after selectors
                    } else if (stream.match(/media[\w-\s]*[\w-]/)) {
                      indent(state);
                    } else if(stream.eatWhile(/[\w-]/)) {
                      if(stream.current().match(commonDefRegexp)) {
                        indent(state);
                      }
                    }
                    return "def";
                  }
            
                  // Number
                  if (stream.match(/^-?[0-9\.]/, false)) {
            
                    // Floats
                    if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i) || stream.match(/^-?\d+\.\d*/)) {
            
                      // Prevent from getting extra . on 1..
                      if (stream.peek() == ".") {
                        stream.backUp(1);
                      }
                      // Units
                      stream.eatWhile(/[a-z%]/i);
                      return "number";
                    }
                    // Integers
                    if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/) || stream.match(/^-?0(?![\dx])/i)) {
                      // Units
                      stream.eatWhile(/[a-z%]/i);
                      return "number";
                    }
                  }
            
                  // Hex color and id selector
                  if (ch === "#") {
                    stream.next();
            
                    // Hex color
                    if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) {
                      return "atom";
                    }
            
                    // ID selector
                    if (stream.match(/^[\w-]+/i)) {
                      indent(state);
                      return "builtin";
                    }
                  }
            
                  // Vendor prefixes
                  if (stream.match(vendorPrefixesRegexp)) {
                    return "meta";
                  }
            
                  // Gradients and animation as CSS value
                  if (stream.match(cssValuesWithBracketsRegexp)) {
                    return "atom";
                  }
            
                  // Mixins / Functions with indentation
                  if (stream.sol() && stream.match(/^\.?[a-z][\w-]*\(/i)) {
                    stream.backUp(1);
                    indent(state);
                    return "keyword";
                  }
            
                  // Mixins / Functions
                  if (stream.match(/^\.?[a-z][\w-]*\(/i)) {
                    stream.backUp(1);
                    return "keyword";
                  }
            
                  // +Block mixins
                  if (stream.match(/^(\+|\-)[a-z][\w-]+\(/i)) {
                    stream.backUp(1);
                    indent(state);
                    return "keyword";
                  }
            
                  // url tokens
                  if (stream.match(/^url/) && stream.peek() === "(") {
                    state.tokenizer = urlTokens;
                    if(!stream.peek()) {
                      state.cursorHalf = 0;
                    }
                    return "atom";
                  }
            
                  // Class
                  if (stream.match(/^\.[a-z][\w-]*/i)) {
                    indent(state);
                    return "qualifier";
                  }
            
                  // & Parent Reference with BEM naming
                  if (stream.match(/^(_|__|-|--)[a-z0-9-]+/)) {
                    return "qualifier";
                  }
            
                  // Pseudo elements/classes
                  if (ch == ':' && stream.match(/^::?[\w-]+/)) {
                    indent(state);
                    return "variable-3";
                  }
            
                  // Conditionals
                  if (stream.match(wordRegexp(["for", "if", "else", "unless"]))) {
                    indent(state);
                    return "keyword";
                  }
            
                  // Keywords
                  if (stream.match(commonKeywordsRegexp)) {
                    return "keyword";
                  }
            
                  // Atoms
                  if (stream.match(commonAtomsRegexp)) {
                    return "atom";
                  }
            
                  // Variables
                  if (stream.match(/^\$?[a-z][\w-]+\s?=(\s|[\w-'"\$])/i)) {
                    stream.backUp(2);
                    var cssPropertie = stream.current().toLowerCase().match(/[\w-]+/)[0];
                    return cssProperties[cssPropertie] === undefined ? "variable-2" : "property";
                  } else if (stream.match(/\$[\w-\.]+/i)) {
                    return "variable-2";
                  } else if (stream.match(/\$?[\w-]+\.[\w-]+/i)) {
                    var cssTypeSelector = stream.current().toLowerCase().match(/[\w]+/)[0];
                    if(cssTypeSelectors[cssTypeSelector] === undefined) {
                      return "variable-2";
                    } else stream.backUp(stream.current().length);
                  }
            
                  // !important
                  if (ch === "!") {
                    stream.next();
                    return stream.match(/^[\w]+/) ? "keyword": "operator";
                  }
            
                  // / Root Reference
                  if (stream.match(/^\/(:|\.|#|[a-z])/)) {
                    stream.backUp(1);
                    return "variable-3";
                  }
            
                  // Operators and delimiters
                  if (stream.match(operatorsRegexp) || stream.match(wordOperatorsRegexp)) {
                    return "operator";
                  }
                  if (stream.match(delimitersRegexp)) {
                    return null;
                  }
            
                  // & Parent Reference
                  if (ch === "&") {
                    stream.next();
                    return "variable-3";
                  }
            
                  // Font family
                  if (stream.match(/^[A-Z][a-z0-9-]+/)) {
                    return "string";
                  }
            
                  // CSS rule
                  // NOTE: Some css selectors and property values have the same name
                  // (embed, menu, pre, progress, sub, table),
                  // so they will have the same color (.cm-atom).
                  if (stream.match(/[\w-]*/i)) {
            
                    var word = stream.current().toLowerCase();
            
                    if(cssProperties[word] !== undefined) {
                      // CSS property
                      if(!stream.eol())
                        return "property";
                      else
                        return "variable-2";
            
                    } else if(cssValues[word] !== undefined) {
                      // CSS value
                      return "atom";
            
                    } else if(cssTypeSelectors[word] !== undefined) {
                      // CSS type selectors
                      indent(state);
                      return "tag";
            
                    } else if(word) {
                      // By default variable-2
                      return "variable-2";
                    }
                  }
            
                  // Handle non-detected items
                  stream.next();
                  return null;
            
                };
            
                var tokenLexer = function(stream, state) {
            
                  if (stream.sol()) {
                    state.indentCount = 0;
                  }
            
                  var style = state.tokenizer(stream, state);
                  var current = stream.current();
            
                  if (stream.eol() && (current === "}" || current === ",")) {
                    dedent(state);
                  }
            
                  if (style !== null) {
                    var startOfToken = stream.pos - current.length;
                    var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);
            
                    var newScopes = [];
            
                    for (var i = 0; i < state.scopes.length; i++) {
                      var scope = state.scopes[i];
            
                      if (scope.offset <= withCurrentIndent) {
                        newScopes.push(scope);
                      }
                    }
            
                    state.scopes = newScopes;
                  }
            
                  return style;
                };
            
                return {
                  startState: function() {
                    return {
                      tokenizer: tokenBase,
                      scopes: [{offset: 0, type: 'styl'}]
                    };
                  },
            
                  token: function(stream, state) {
                    var style = tokenLexer(stream, state);
                    state.lastToken = { style: style, content: stream.current() };
                    return style;
                  },
            
                  indent: function(state) {
                    return state.scopes[0].offset;
                  },
            
                  lineComment: "//",
                  fold: "indent"
            
                };
            
                function urlTokens(stream, state) {
                  var ch = stream.peek();
            
                  if (ch === ")") {
                    stream.next();
                    state.tokenizer = tokenBase;
                    return "operator";
                  } else if (ch === "(") {
                    stream.next();
                    stream.eatSpace();
            
                    return "operator";
                  } else if (ch === "'" || ch === '"') {
                    state.tokenizer = buildStringTokenizer(stream.next());
                    return "string";
                  } else {
                    state.tokenizer = buildStringTokenizer(")", false);
                    return "string";
                  }
                }
            
                function multilineComment(stream, state) {
                  if (stream.skipTo("*/")) {
                    stream.next();
                    stream.next();
                    state.tokenizer = tokenBase;
                  } else {
                    stream.next();
                  }
                  return "comment";
                }
            
                function buildStringTokenizer(quote, greedy) {
            
                  if(greedy == null) {
                    greedy = true;
                  }
            
                  function stringTokenizer(stream, state) {
                    var nextChar = stream.next();
                    var peekChar = stream.peek();
                    var previousChar = stream.string.charAt(stream.pos-2);
            
                    var endingString = ((nextChar !== "\\" && peekChar === quote) ||
                                        (nextChar === quote && previousChar !== "\\"));
            
                    if (endingString) {
                      if (nextChar !== quote && greedy) {
                        stream.next();
                      }
                      state.tokenizer = tokenBase;
                      return "string";
                    } else if (nextChar === "#" && peekChar === "{") {
                      state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
                      stream.next();
                      return "operator";
                    } else {
                      return "string";
                    }
                  }
            
                  return stringTokenizer;
                }
            
                function buildInterpolationTokenizer(currentTokenizer) {
                  return function(stream, state) {
                    if (stream.peek() === "}") {
                      stream.next();
                      state.tokenizer = currentTokenizer;
                      return "operator";
                    } else {
                      return tokenBase(stream, state);
                    }
                  };
                }
            
                function indent(state) {
                  if (state.indentCount == 0) {
                    state.indentCount++;
                    var lastScopeOffset = state.scopes[0].offset;
                    var currentOffset = lastScopeOffset + config.indentUnit;
                    state.scopes.unshift({ offset:currentOffset });
                  }
                }
            
                function dedent(state) {
                  if (state.scopes.length == 1) { return true; }
                  state.scopes.shift();
                }
            
              });
            
              // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
              var cssTypeSelectors_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi","bdo","bgsound","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"];
              // https://github.com/csscomb/csscomb.js/blob/master/config/zen.json
              var cssProperties_ = ["position","top","right","bottom","left","z-index","display","visibility","flex-direction","flex-order","flex-pack","float","clear","flex-align","overflow","overflow-x","overflow-y","overflow-scrolling","clip","box-sizing","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left","min-width","min-height","max-width","max-height","width","height","outline","outline-width","outline-style","outline-color","outline-offset","border","border-spacing","border-collapse","border-width","border-style","border-color","border-top","border-top-width","border-top-style","border-top-color","border-right","border-right-width","border-right-style","border-right-color","border-bottom","border-bottom-width","border-bottom-style","border-bottom-color","border-left","border-left-width","border-left-style","border-left-color","border-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","border-top-image","border-right-image","border-bottom-image","border-left-image","border-corner-image","border-top-left-image","border-top-right-image","border-bottom-right-image","border-bottom-left-image","background","filter:progid:DXImageTransform\\.Microsoft\\.AlphaImageLoader","background-color","background-image","background-attachment","background-position","background-position-x","background-position-y","background-clip","background-origin","background-size","background-repeat","box-decoration-break","box-shadow","color","table-layout","caption-side","empty-cells","list-style","list-style-position","list-style-type","list-style-image","quotes","content","counter-increment","counter-reset","writing-mode","vertical-align","text-align","text-align-last","text-decoration","text-emphasis","text-emphasis-position","text-emphasis-style","text-emphasis-color","text-indent","-ms-text-justify","text-justify","text-outline","text-transform","text-wrap","text-overflow","text-overflow-ellipsis","text-overflow-mode","text-size-adjust","text-shadow","white-space","word-spacing","word-wrap","word-break","tab-size","hyphens","letter-spacing","font","font-weight","font-style","font-variant","font-size-adjust","font-stretch","font-size","font-family","src","line-height","opacity","filter:\\\\\\\\'progid:DXImageTransform.Microsoft.Alpha","filter:progid:DXImageTransform.Microsoft.Alpha\\(Opacity","interpolation-mode","filter","resize","cursor","nav-index","nav-up","nav-right","nav-down","nav-left","transition","transition-delay","transition-timing-function","transition-duration","transition-property","transform","transform-origin","animation","animation-name","animation-duration","animation-play-state","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","pointer-events","unicode-bidi","direction","columns","column-span","column-width","column-count","column-fill","column-gap","column-rule","column-rule-width","column-rule-style","column-rule-color","break-before","break-inside","break-after","page-break-before","page-break-inside","page-break-after","orphans","widows","zoom","max-zoom","min-zoom","user-zoom","orientation","text-rendering","speak","animation-fill-mode","backface-visibility","user-drag","user-select","appearance"];
              // https://github.com/codemirror/CodeMirror/blob/master/mode/css/css.js#L501
              var cssValues_ = ["above","absolute","activeborder","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","cambodian","capitalize","caps-lock-indicator","captiontext","caret","cell","center","checkbox","circle","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","cover","crop","cross","crosshair","currentcolor","cursive","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ew-resize","expanded","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-table","inset","inside","intrinsic","invert","italic","justify","kannada","katakana","katakana-iroha","keep-all","khmer","landscape","lao","large","larger","left","level","lighter","line-through","linear","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","single","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","telugu","text","text-bottom","text-top","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"];
              var cssColorValues_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
              var cssValuesWithBrackets_ = ["gradient","linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","cubic-bezier","translateX","translateY","translate3d","rotate3d","scale","scale3d","perspective","skewX"];
            
              var wordOperators = ["in", "and", "or", "not", "is a", "is", "isnt", "defined", "if unless"],
                  commonKeywords = ["for", "if", "else", "unless", "return"],
                  commonAtoms = ["null", "true", "false", "href", "title", "type", "not-allowed", "readonly", "disabled"],
                  commonDef = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"],
                  cssTypeSelectors = keySet(cssTypeSelectors_),
                  cssProperties = keySet(cssProperties_),
                  cssValues = keySet(cssValues_.concat(cssColorValues_)),
                  hintWords = wordOperators.concat(commonKeywords,
                                                   commonAtoms,
                                                   commonDef,
                                                   cssTypeSelectors_,
                                                   cssProperties_,
                                                   cssValues_,
                                                   cssValuesWithBrackets_,
                                                   cssColorValues_);
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              };
            
              function keySet(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) {
                  keys[array[i]] = true;
                }
                return keys;
              };
            
              CodeMirror.registerHelper("hintWords", "stylus", hintWords);
              CodeMirror.defineMIME("text/x-styl", "stylus");
            
            });
            
        • tcl
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tcl mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="tcl.js"></script>
            <script src="../../addon/scroll/scrollpastend.js"></script>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tcl</a>
              </ul>
            </div>
            
            <article>
            <h2>Tcl mode</h2>
            <form><textarea id="code" name="code">
            ##############################################################################################
            ##  ##     whois.tcl for eggdrop by Ford_Lawnmower irc.geekshed.net #Script-Help        ##  ##
            ##############################################################################################
            ## To use this script you must set channel flag +whois (ie .chanset #chan +whois)           ##
            ##############################################################################################
            ##      ____                __                 ###########################################  ##
            ##     / __/___ _ ___ _ ___/ /____ ___   ___   ###########################################  ##
            ##    / _/ / _ `// _ `// _  // __// _ \ / _ \  ###########################################  ##
            ##   /___/ \_, / \_, / \_,_//_/   \___// .__/  ###########################################  ##
            ##        /___/ /___/                 /_/      ###########################################  ##
            ##                                             ###########################################  ##
            ##############################################################################################
            ##  ##                             Start Setup.                                         ##  ##
            ##############################################################################################
            namespace eval whois {
            ## change cmdchar to the trigger you want to use                                        ##  ##
              variable cmdchar "!"
            ## change command to the word trigger you would like to use.                            ##  ##
            ## Keep in mind, This will also change the .chanset +/-command                          ##  ##
              variable command "whois"
            ## change textf to the colors you want for the text.                                    ##  ##
              variable textf "\017\00304"
            ## change tagf to the colors you want for tags:                                         ##  ##
              variable tagf "\017\002"
            ## Change logo to the logo you want at the start of the line.                           ##  ##
              variable logo "\017\00304\002\[\00306W\003hois\00304\]\017"
            ## Change lineout to the results you want. Valid results are channel users modes topic  ##  ##
              variable lineout "channel users modes topic"
            ##############################################################################################
            ##  ##                           End Setup.                                              ## ##
            ##############################################################################################
              variable channel ""
              setudef flag $whois::command
              bind pub -|- [string trimleft $whois::cmdchar]${whois::command} whois::list
              bind raw -|- "311" whois::311
              bind raw -|- "312" whois::312
              bind raw -|- "319" whois::319
              bind raw -|- "317" whois::317
              bind raw -|- "313" whois::multi
              bind raw -|- "310" whois::multi
              bind raw -|- "335" whois::multi
              bind raw -|- "301" whois::301
              bind raw -|- "671" whois::multi
              bind raw -|- "320" whois::multi
              bind raw -|- "401" whois::multi
              bind raw -|- "318" whois::318
              bind raw -|- "307" whois::307
            }
            proc whois::311 {from key text} {
              if {[regexp -- {^[^\s]+\s(.+?)\s(.+?)\s(.+?)\s\*\s\:(.+)$} $text wholematch nick ident host realname]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Host:${whois::textf} \
                    $nick \(${ident}@${host}\) ${whois::tagf}Realname:${whois::textf} $realname"
              }
            }
            proc whois::multi {from key text} {
              if {[regexp {\:(.*)$} $text match $key]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Note:${whois::textf} [subst $$key]"
                    return 1
              }
            }
            proc whois::312 {from key text} {
              regexp {([^\s]+)\s\:} $text match server
              putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Server:${whois::textf} $server"
            }
            proc whois::319 {from key text} {
              if {[regexp {.+\:(.+)$} $text match channels]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Channels:${whois::textf} $channels"
              }
            }
            proc whois::317 {from key text} {
              if {[regexp -- {.*\s(\d+)\s(\d+)\s\:} $text wholematch idle signon]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Connected:${whois::textf} \
                    [ctime $signon] ${whois::tagf}Idle:${whois::textf} [duration $idle]"
              }
            }
            proc whois::301 {from key text} {
              if {[regexp {^.+\s[^\s]+\s\:(.*)$} $text match awaymsg]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Away:${whois::textf} $awaymsg"
              }
            }
            proc whois::318 {from key text} {
              namespace eval whois {
                    variable channel ""
              }
              variable whois::channel ""
            }
            proc whois::307 {from key text} {
              putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Services:${whois::textf} Registered Nick"
            }
            proc whois::list {nick host hand chan text} {
              if {[lsearch -exact [channel info $chan] "+${whois::command}"] != -1} {
                namespace eval whois {
                      variable channel ""
                    }
                variable whois::channel $chan
                putserv "WHOIS $text"
              }
            }
            putlog "\002*Loaded* \017\00304\002\[\00306W\003hois\00304\]\017 \002by \
            Ford_Lawnmower irc.GeekShed.net #Script-Help"
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "night",
                    lineNumbers: true,
                    indentUnit: 2,
                    scrollPastEnd: true,
                    mode: "text/x-tcl"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tcl</code>.</p>
            
              </article>
            
          • tcl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            //tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("tcl", function() {
              function parseWords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = parseWords("Tcl safe after append array auto_execok auto_import auto_load " +
                    "auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror " +
                    "binary break catch cd close concat continue dde eof encoding error " +
                    "eval exec exit expr fblocked fconfigure fcopy file fileevent filename " +
                    "filename flush for foreach format gets glob global history http if " +
                    "incr info interp join lappend lindex linsert list llength load lrange " +
                    "lreplace lsearch lset lsort memory msgcat namespace open package parray " +
                    "pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp " +
                    "registry regsub rename resource return scan seek set socket source split " +
                    "string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord " +
                    "tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest " +
                    "tclvars tell time trace unknown unset update uplevel upvar variable " +
                "vwait");
                var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
                var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
                function chain(stream, state, f) {
                  state.tokenize = f;
                  return f(stream, state);
                }
                function tokenBase(stream, state) {
                  var beforeParams = state.beforeParams;
                  state.beforeParams = false;
                  var ch = stream.next();
                  if ((ch == '"' || ch == "'") && state.inParams)
                    return chain(stream, state, tokenString(ch));
                  else if (/[\[\]{}\(\),;\.]/.test(ch)) {
                    if (ch == "(" && beforeParams) state.inParams = true;
                    else if (ch == ")") state.inParams = false;
                      return null;
                  }
                  else if (/\d/.test(ch)) {
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  else if (ch == "#" && stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  }
                  else if (ch == "#" && stream.match(/ *\[ *\[/)) {
                    return chain(stream, state, tokenUnparsed);
                  }
                  else if (ch == "#" && stream.eat("#")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  else if (ch == '"') {
                    stream.skipTo(/"/);
                    return "comment";
                  }
                  else if (ch == "$") {
                    stream.eatWhile(/[$_a-z0-9A-Z\.{:]/);
                    stream.eatWhile(/}/);
                    state.beforeParams = true;
                    return "builtin";
                  }
                  else if (isOperatorChar.test(ch)) {
                    stream.eatWhile(isOperatorChar);
                    return "comment";
                  }
                  else {
                    stream.eatWhile(/[\w\$_{}\xa1-\uffff]/);
                    var word = stream.current().toLowerCase();
                    if (keywords && keywords.propertyIsEnumerable(word))
                      return "keyword";
                    if (functions && functions.propertyIsEnumerable(word)) {
                      state.beforeParams = true;
                      return "keyword";
                    }
                    return null;
                  }
                }
                function tokenString(quote) {
                  return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      end = true;
                      break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end) state.tokenize = tokenBase;
                    return "string";
                  };
                }
                function tokenComment(stream, state) {
                  var maybeEnd = false, ch;
                  while (ch = stream.next()) {
                    if (ch == "#" && maybeEnd) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return "comment";
                }
                function tokenUnparsed(stream, state) {
                  var maybeEnd = 0, ch;
                  while (ch = stream.next()) {
                    if (ch == "#" && maybeEnd == 2) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    if (ch == "]")
                      maybeEnd++;
                    else if (ch != " ")
                      maybeEnd = 0;
                  }
                  return "meta";
                }
                return {
                  startState: function() {
                    return {
                      tokenize: tokenBase,
                      beforeParams: false,
                      inParams: false
                    };
                  },
                  token: function(stream, state) {
                    if (stream.eatSpace()) return null;
                    return state.tokenize(stream, state);
                  }
                };
            });
            CodeMirror.defineMIME("text/x-tcl", "tcl");
            
            });
            
        • textile
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Textile mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="textile.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/marijnh/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class="active" href="#">Textile</a>
              </ul>
            </div>
            
            <article>
                <h2>Textile mode</h2>
                <form><textarea id="code" name="code">
            h1. Textile Mode
            
            A paragraph without formatting.
            
            p. A simple Paragraph.
            
            
            h2. Phrase Modifiers
            
            Here are some simple phrase modifiers: *strong*, _emphasis_, **bold**, and __italic__.
            
            A ??citation??, -deleted text-, +inserted text+, some ^superscript^, and some ~subscript~.
            
            A %span element% and @code element@
            
            A "link":http://example.com, a "link with (alt text)":urlAlias
            
            [urlAlias]http://example.com/
            
            An image: !http://example.com/image.png! and an image with a link: !http://example.com/image.png!:http://example.com
            
            A sentence with a footnote.[123]
            
            fn123. The footnote is defined here.
            
            Registered(r), Trademark(tm), and Copyright(c)
            
            
            h2. Headers
            
            h1. Top level
            h2. Second level
            h3. Third level
            h4. Fourth level
            h5. Fifth level
            h6. Lowest level
            
            
            h2.  Lists
            
            * An unordered list
            ** foo bar
            *** foo bar
            **** foo bar
            ** foo bar
            
            # An ordered list
            ## foo bar
            ### foo bar
            #### foo bar
            ## foo bar
            
            - definition list := description
            - another item    := foo bar
            - spanning ines   :=
                                 foo bar
            
                                 foo bar =:
            
            
            h2. Attributes
            
            Layouts and phrase modifiers can be modified with various kinds of attributes: alignment, CSS ID, CSS class names, language, padding, and CSS styles.
            
            h3. Alignment
            
            div<. left align
            div>. right align
            
            h3. CSS ID and class name
            
            You are a %(my-id#my-classname) rad% person.
            
            h3. Language
            
            p[en_CA]. Strange weather, eh?
            
            h3. Horizontal Padding
            
            p(())). 2em left padding, 3em right padding
            
            h3. CSS styling
            
            p{background: red}. Fire!
            
            
            h2. Table
            
            |_.              Header 1               |_.      Header 2        |
            |{background:#ddd}. Cell with background|         Normal         |
            |\2.         Cell spanning 2 columns                             |
            |/2.         Cell spanning 2 rows       |(cell-class). one       |
            |                                                two             |
            |>.                  Right aligned cell |<. Left aligned cell    |
            
            
            h3. A table with attributes:
            
            table(#prices).
            |Adults|$5|
            |Children|$2|
            
            
            h2. Code blocks
            
            bc.
            function factorial(n) {
                if (n === 0) {
                    return 1;
                }
                return n * factorial(n - 1);
            }
            
            pre..
                            ,,,,,,
                        o#'9MMHb':'-,o,
                     .oH":HH$' "' ' -*R&o,
                    dMMM*""'`'      .oM"HM?.
                   ,MMM'          "HLbd< ?&H\
                  .:MH ."\          ` MM  MM&b
                 . "*H    -        &MMMMMMMMMH:
                 .    dboo        MMMMMMMMMMMM.
                 .   dMMMMMMb      *MMMMMMMMMP.
                 .    MMMMMMMP        *MMMMMP .
                      `#MMMMM           MM6P ,
                   '    `MMMP"           HM*`,
                    '    :MM             .- ,
                     '.   `#?..  .       ..'
                        -.   .         .-
                          ''-.oo,oo.-''
            
            \. _(9>
             \==_)
              -'=
            
            h2. Temporarily disabling textile markup
            
            notextile. Don't __touch this!__
            
            Surround text with double-equals to disable textile inline. Example: Use ==*asterisks*== for *strong* text.
            
            
            h2. HTML
            
            Some block layouts are simply textile versions of HTML tags with the same name, like @div@, @pre@, and @p@. HTML tags can also exist on their own line:
            
            <section>
              <h1>Title</h1>
              <p>Hello!</p>
            </section>
            
            </textarea></form>
                <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                        lineNumbers: true,
                        mode: "text/x-textile"
                    });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-textile</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#textile_*">normal</a>,  <a href="../../test/index.html#verbose,textile_*">verbose</a>.</p>
            
            </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, 'textile');
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT('simpleParagraphs',
                  'Some text.',
                  '',
                  'Some more text.');
            
              /*
               * Phrase Modifiers
               */
            
              MT('em',
                  'foo [em _bar_]');
            
              MT('emBoogus',
                  'code_mirror');
            
              MT('strong',
                  'foo [strong *bar*]');
            
              MT('strongBogus',
                  '3 * 3 = 9');
            
              MT('italic',
                  'foo [em __bar__]');
            
              MT('italicBogus',
                  'code__mirror');
            
              MT('bold',
                  'foo [strong **bar**]');
            
              MT('boldBogus',
                  '3 ** 3 = 27');
            
              MT('simpleLink',
                  '[link "CodeMirror":http://codemirror.net]');
            
              MT('referenceLink',
                  '[link "CodeMirror":code_mirror]',
                  'Normal Text.',
                  '[link [[code_mirror]]http://codemirror.net]');
            
              MT('footCite',
                  'foo bar[qualifier [[1]]]');
            
              MT('footCiteBogus',
                  'foo bar[[1a2]]');
            
              MT('special-characters',
                      'Registered [tag (r)], ' +
                      'Trademark [tag (tm)], and ' +
                      'Copyright [tag (c)] 2008');
            
              MT('cite',
                  "A book is [keyword ??The Count of Monte Cristo??] by Dumas.");
            
              MT('additionAndDeletion',
                  'The news networks declared [negative -Al Gore-] ' +
                    '[positive +George W. Bush+] the winner in Florida.');
            
              MT('subAndSup',
                  'f(x, n) = log [builtin ~4~] x [builtin ^n^]');
            
              MT('spanAndCode',
                  'A [quote %span element%] and [atom @code element@]');
            
              MT('spanBogus',
                  'Percentage 25% is not a span.');
            
              MT('citeBogus',
                  'Question? is not a citation.');
            
              MT('codeBogus',
                  'user@example.com');
            
              MT('subBogus',
                  '~username');
            
              MT('supBogus',
                  'foo ^ bar');
            
              MT('deletionBogus',
                  '3 - 3 = 0');
            
              MT('additionBogus',
                  '3 + 3 = 6');
            
              MT('image',
                  'An image: [string !http://www.example.com/image.png!]');
            
              MT('imageWithAltText',
                  'An image: [string !http://www.example.com/image.png (Alt Text)!]');
            
              MT('imageWithUrl',
                  'An image: [string !http://www.example.com/image.png!:http://www.example.com/]');
            
              /*
               * Headers
               */
            
              MT('h1',
                  '[header&header-1 h1. foo]');
            
              MT('h2',
                  '[header&header-2 h2. foo]');
            
              MT('h3',
                  '[header&header-3 h3. foo]');
            
              MT('h4',
                  '[header&header-4 h4. foo]');
            
              MT('h5',
                  '[header&header-5 h5. foo]');
            
              MT('h6',
                  '[header&header-6 h6. foo]');
            
              MT('h7Bogus',
                  'h7. foo');
            
              MT('multipleHeaders',
                  '[header&header-1 h1. Heading 1]',
                  '',
                  'Some text.',
                  '',
                  '[header&header-2 h2. Heading 2]',
                  '',
                  'More text.');
            
              MT('h1inline',
                  '[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1  baz]');
            
              /*
               * Lists
               */
            
              MT('ul',
                  'foo',
                  'bar',
                  '',
                  '[variable-2 * foo]',
                  '[variable-2 * bar]');
            
              MT('ulNoBlank',
                  'foo',
                  'bar',
                  '[variable-2 * foo]',
                  '[variable-2 * bar]');
            
              MT('ol',
                  'foo',
                  'bar',
                  '',
                  '[variable-2 # foo]',
                  '[variable-2 # bar]');
            
              MT('olNoBlank',
                  'foo',
                  'bar',
                  '[variable-2 # foo]',
                  '[variable-2 # bar]');
            
              MT('ulFormatting',
                  '[variable-2 * ][variable-2&em _foo_][variable-2  bar]',
                  '[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]' +
                    '[variable-2&strong *][variable-2  bar]',
                  '[variable-2 * ][variable-2&strong *foo*][variable-2  bar]');
            
              MT('olFormatting',
                  '[variable-2 # ][variable-2&em _foo_][variable-2  bar]',
                  '[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]' +
                    '[variable-2&strong *][variable-2  bar]',
                  '[variable-2 # ][variable-2&strong *foo*][variable-2  bar]');
            
              MT('ulNested',
                  '[variable-2 * foo]',
                  '[variable-3 ** bar]',
                  '[keyword *** bar]',
                  '[variable-2 **** bar]',
                  '[variable-3 ** bar]');
            
              MT('olNested',
                  '[variable-2 # foo]',
                  '[variable-3 ## bar]',
                  '[keyword ### bar]',
                  '[variable-2 #### bar]',
                  '[variable-3 ## bar]');
            
              MT('ulNestedWithOl',
                  '[variable-2 * foo]',
                  '[variable-3 ## bar]',
                  '[keyword *** bar]',
                  '[variable-2 #### bar]',
                  '[variable-3 ** bar]');
            
              MT('olNestedWithUl',
                  '[variable-2 # foo]',
                  '[variable-3 ** bar]',
                  '[keyword ### bar]',
                  '[variable-2 **** bar]',
                  '[variable-3 ## bar]');
            
              MT('definitionList',
                  '[number - coffee := Hot ][number&em _and_][number  black]',
                  '',
                  'Normal text.');
            
              MT('definitionListSpan',
                  '[number - coffee :=]',
                  '',
                  '[number Hot ][number&em _and_][number  black =:]',
                  '',
                  'Normal text.');
            
              MT('boo',
                  '[number - dog := woof woof]',
                  '[number - cat := meow meow]',
                  '[number - whale :=]',
                  '[number Whale noises.]',
                  '',
                  '[number Also, ][number&em _splashing_][number . =:]');
            
              /*
               * Attributes
               */
            
              MT('divWithAttribute',
                  '[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]');
            
              MT('divWithAttributeAnd2emRightPadding',
                  '[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]');
            
              MT('divWithClassAndId',
                  '[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]');
            
              MT('paragraphWithCss',
                  'p[attribute {color:red;}]. foo bar');
            
              MT('paragraphNestedStyles',
                  'p. [strong *foo ][strong&em _bar_][strong *]');
            
              MT('paragraphWithLanguage',
                  'p[attribute [[fr]]]. Parlez-vous français?');
            
              MT('paragraphLeftAlign',
                  'p[attribute <]. Left');
            
              MT('paragraphRightAlign',
                  'p[attribute >]. Right');
            
              MT('paragraphRightAlign',
                  'p[attribute =]. Center');
            
              MT('paragraphJustified',
                  'p[attribute <>]. Justified');
            
              MT('paragraphWithLeftIndent1em',
                  'p[attribute (]. Left');
            
              MT('paragraphWithRightIndent1em',
                  'p[attribute )]. Right');
            
              MT('paragraphWithLeftIndent2em',
                  'p[attribute ((]. Left');
            
              MT('paragraphWithRightIndent2em',
                  'p[attribute ))]. Right');
            
              MT('paragraphWithLeftIndent3emRightIndent2em',
                  'p[attribute ((())]. Right');
            
              MT('divFormatting',
                  '[punctuation div. ][punctuation&strong *foo ]' +
                    '[punctuation&strong&em _bar_][punctuation&strong *]');
            
              MT('phraseModifierAttributes',
                  'p[attribute (my-class)]. This is a paragraph that has a class and' +
                  ' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]' +
                  ' has an id.');
            
              MT('linkWithClass',
                  '[link "(my-class). This is a link with class":http://redcloth.org]');
            
              /*
               * Layouts
               */
            
              MT('paragraphLayouts',
                  'p. This is one paragraph.',
                  '',
                  'p. This is another.');
            
              MT('div',
                  '[punctuation div. foo bar]');
            
              MT('pre',
                  '[operator pre. Text]');
            
              MT('bq.',
                  '[bracket bq. foo bar]',
                  '',
                  'Normal text.');
            
              MT('footnote',
                  '[variable fn123. foo ][variable&strong *bar*]');
            
              /*
               * Spanning Layouts
               */
            
              MT('bq..ThenParagraph',
                  '[bracket bq.. foo bar]',
                  '',
                  '[bracket More quote.]',
                  'p. Normal Text');
            
              MT('bq..ThenH1',
                  '[bracket bq.. foo bar]',
                  '',
                  '[bracket More quote.]',
                  '[header&header-1 h1. Header Text]');
            
              MT('bc..ThenParagraph',
                  '[atom bc.. # Some ruby code]',
                  '[atom obj = {foo: :bar}]',
                  '[atom puts obj]',
                  '',
                  '[atom obj[[:love]] = "*love*"]',
                  '[atom puts obj.love.upcase]',
                  '',
                  'p. Normal text.');
            
              MT('fn1..ThenParagraph',
                  '[variable fn1.. foo bar]',
                  '',
                  '[variable More.]',
                  'p. Normal Text');
            
              MT('pre..ThenParagraph',
                  '[operator pre.. foo bar]',
                  '',
                  '[operator More.]',
                  'p. Normal Text');
            
              /*
               * Tables
               */
            
              MT('table',
                  '[variable-3&operator |_. name |_. age|]',
                  '[variable-3 |][variable-3&strong *Walter*][variable-3 |   5  |]',
                  '[variable-3 |Florence|   6  |]',
                  '',
                  'p. Normal text.');
            
              MT('tableWithAttributes',
                  '[variable-3&operator |_. name |_. age|]',
                  '[variable-3 |][variable-3&attribute /2.][variable-3  Jim |]',
                  '[variable-3 |][variable-3&attribute \\2{color: red}.][variable-3  Sam |]');
            
              /*
               * HTML
               */
            
              MT('html',
                  '[comment <div id="wrapper">]',
                  '[comment <section id="introduction">]',
                  '',
                  '[header&header-1 h1. Welcome]',
                  '',
                  '[variable-2 * Item one]',
                  '[variable-2 * Item two]',
                  '',
                  '[comment <a href="http://example.com">Example</a>]',
                  '',
                  '[comment </section>]',
                  '[comment </div>]');
            
              MT('inlineHtml',
                  'I can use HTML directly in my [comment <span class="youbetcha">Textile</span>].');
            
              /*
               * No-Textile
               */
            
              MT('notextile',
                '[string-2 notextile. *No* formatting]');
            
              MT('notextileInline',
                  'Use [string-2 ==*asterisks*==] for [strong *strong*] text.');
            
              MT('notextileWithPre',
                  '[operator pre. *No* formatting]');
            
              MT('notextileWithSpanningPre',
                  '[operator pre.. *No* formatting]',
                  '',
                  '[operator *No* formatting]');
            
              /* Only toggling phrases between non-word chars. */
            
              MT('phrase-in-word',
                 'foo_bar_baz');
            
              MT('phrase-non-word',
                 '[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]');
            
              MT('phrase-lone-dash',
                 'foo - bar - baz');
            })();
            
          • textile.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") { // CommonJS
                mod(require("../../lib/codemirror"));
              } else if (typeof define == "function" && define.amd) { // AMD
                define(["../../lib/codemirror"], mod);
              } else { // Plain browser env
                mod(CodeMirror);
              }
            })(function(CodeMirror) {
              "use strict";
            
              var TOKEN_STYLES = {
                addition: "positive",
                attributes: "attribute",
                bold: "strong",
                cite: "keyword",
                code: "atom",
                definitionList: "number",
                deletion: "negative",
                div: "punctuation",
                em: "em",
                footnote: "variable",
                footCite: "qualifier",
                header: "header",
                html: "comment",
                image: "string",
                italic: "em",
                link: "link",
                linkDefinition: "link",
                list1: "variable-2",
                list2: "variable-3",
                list3: "keyword",
                notextile: "string-2",
                pre: "operator",
                p: "property",
                quote: "bracket",
                span: "quote",
                specialChar: "tag",
                strong: "strong",
                sub: "builtin",
                sup: "builtin",
                table: "variable-3",
                tableHeading: "operator"
              };
            
              function startNewLine(stream, state) {
                state.mode = Modes.newLayout;
                state.tableHeading = false;
            
                if (state.layoutType === "definitionList" && state.spanningLayout &&
                    stream.match(RE("definitionListEnd"), false))
                  state.spanningLayout = false;
              }
            
              function handlePhraseModifier(stream, state, ch) {
                if (ch === "_") {
                  if (stream.eat("_"))
                    return togglePhraseModifier(stream, state, "italic", /__/, 2);
                  else
                    return togglePhraseModifier(stream, state, "em", /_/, 1);
                }
            
                if (ch === "*") {
                  if (stream.eat("*")) {
                    return togglePhraseModifier(stream, state, "bold", /\*\*/, 2);
                  }
                  return togglePhraseModifier(stream, state, "strong", /\*/, 1);
                }
            
                if (ch === "[") {
                  if (stream.match(/\d+\]/)) state.footCite = true;
                  return tokenStyles(state);
                }
            
                if (ch === "(") {
                  var spec = stream.match(/^(r|tm|c)\)/);
                  if (spec)
                    return tokenStylesWith(state, TOKEN_STYLES.specialChar);
                }
            
                if (ch === "<" && stream.match(/(\w+)[^>]+>[^<]+<\/\1>/))
                  return tokenStylesWith(state, TOKEN_STYLES.html);
            
                if (ch === "?" && stream.eat("?"))
                  return togglePhraseModifier(stream, state, "cite", /\?\?/, 2);
            
                if (ch === "=" && stream.eat("="))
                  return togglePhraseModifier(stream, state, "notextile", /==/, 2);
            
                if (ch === "-" && !stream.eat("-"))
                  return togglePhraseModifier(stream, state, "deletion", /-/, 1);
            
                if (ch === "+")
                  return togglePhraseModifier(stream, state, "addition", /\+/, 1);
            
                if (ch === "~")
                  return togglePhraseModifier(stream, state, "sub", /~/, 1);
            
                if (ch === "^")
                  return togglePhraseModifier(stream, state, "sup", /\^/, 1);
            
                if (ch === "%")
                  return togglePhraseModifier(stream, state, "span", /%/, 1);
            
                if (ch === "@")
                  return togglePhraseModifier(stream, state, "code", /@/, 1);
            
                if (ch === "!") {
                  var type = togglePhraseModifier(stream, state, "image", /(?:\([^\)]+\))?!/, 1);
                  stream.match(/^:\S+/); // optional Url portion
                  return type;
                }
                return tokenStyles(state);
              }
            
              function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) {
                var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null;
                var charAfter = stream.peek();
                if (state[phraseModifier]) {
                  if ((!charAfter || /\W/.test(charAfter)) && charBefore && /\S/.test(charBefore)) {
                    var type = tokenStyles(state);
                    state[phraseModifier] = false;
                    return type;
                  }
                } else if ((!charBefore || /\W/.test(charBefore)) && charAfter && /\S/.test(charAfter) &&
                           stream.match(new RegExp("^.*\\S" + closeRE.source + "(?:\\W|$)"), false)) {
                  state[phraseModifier] = true;
                  state.mode = Modes.attributes;
                }
                return tokenStyles(state);
              };
            
              function tokenStyles(state) {
                var disabled = textileDisabled(state);
                if (disabled) return disabled;
            
                var styles = [];
                if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]);
            
                styles = styles.concat(activeStyles(
                  state, "addition", "bold", "cite", "code", "deletion", "em", "footCite",
                  "image", "italic", "link", "span", "strong", "sub", "sup", "table", "tableHeading"));
            
                if (state.layoutType === "header")
                  styles.push(TOKEN_STYLES.header + "-" + state.header);
            
                return styles.length ? styles.join(" ") : null;
              }
            
              function textileDisabled(state) {
                var type = state.layoutType;
            
                switch(type) {
                case "notextile":
                case "code":
                case "pre":
                  return TOKEN_STYLES[type];
                default:
                  if (state.notextile)
                    return TOKEN_STYLES.notextile + (type ? (" " + TOKEN_STYLES[type]) : "");
                  return null;
                }
              }
            
              function tokenStylesWith(state, extraStyles) {
                var disabled = textileDisabled(state);
                if (disabled) return disabled;
            
                var type = tokenStyles(state);
                if (extraStyles)
                  return type ? (type + " " + extraStyles) : extraStyles;
                else
                  return type;
              }
            
              function activeStyles(state) {
                var styles = [];
                for (var i = 1; i < arguments.length; ++i) {
                  if (state[arguments[i]])
                    styles.push(TOKEN_STYLES[arguments[i]]);
                }
                return styles;
              }
            
              function blankLine(state) {
                var spanningLayout = state.spanningLayout, type = state.layoutType;
            
                for (var key in state) if (state.hasOwnProperty(key))
                  delete state[key];
            
                state.mode = Modes.newLayout;
                if (spanningLayout) {
                  state.layoutType = type;
                  state.spanningLayout = true;
                }
              }
            
              var REs = {
                cache: {},
                single: {
                  bc: "bc",
                  bq: "bq",
                  definitionList: /- [^(?::=)]+:=+/,
                  definitionListEnd: /.*=:\s*$/,
                  div: "div",
                  drawTable: /\|.*\|/,
                  foot: /fn\d+/,
                  header: /h[1-6]/,
                  html: /\s*<(?:\/)?(\w+)(?:[^>]+)?>(?:[^<]+<\/\1>)?/,
                  link: /[^"]+":\S/,
                  linkDefinition: /\[[^\s\]]+\]\S+/,
                  list: /(?:#+|\*+)/,
                  notextile: "notextile",
                  para: "p",
                  pre: "pre",
                  table: "table",
                  tableCellAttributes: /[\/\\]\d+/,
                  tableHeading: /\|_\./,
                  tableText: /[^"_\*\[\(\?\+~\^%@|-]+/,
                  text: /[^!"_=\*\[\(<\?\+~\^%@-]+/
                },
                attributes: {
                  align: /(?:<>|<|>|=)/,
                  selector: /\([^\(][^\)]+\)/,
                  lang: /\[[^\[\]]+\]/,
                  pad: /(?:\(+|\)+){1,2}/,
                  css: /\{[^\}]+\}/
                },
                createRe: function(name) {
                  switch (name) {
                  case "drawTable":
                    return REs.makeRe("^", REs.single.drawTable, "$");
                  case "html":
                    return REs.makeRe("^", REs.single.html, "(?:", REs.single.html, ")*", "$");
                  case "linkDefinition":
                    return REs.makeRe("^", REs.single.linkDefinition, "$");
                  case "listLayout":
                    return REs.makeRe("^", REs.single.list, RE("allAttributes"), "*\\s+");
                  case "tableCellAttributes":
                    return REs.makeRe("^", REs.choiceRe(REs.single.tableCellAttributes,
                                                        RE("allAttributes")), "+\\.");
                  case "type":
                    return REs.makeRe("^", RE("allTypes"));
                  case "typeLayout":
                    return REs.makeRe("^", RE("allTypes"), RE("allAttributes"),
                                      "*\\.\\.?", "(\\s+|$)");
                  case "attributes":
                    return REs.makeRe("^", RE("allAttributes"), "+");
            
                  case "allTypes":
                    return REs.choiceRe(REs.single.div, REs.single.foot,
                                        REs.single.header, REs.single.bc, REs.single.bq,
                                        REs.single.notextile, REs.single.pre, REs.single.table,
                                        REs.single.para);
            
                  case "allAttributes":
                    return REs.choiceRe(REs.attributes.selector, REs.attributes.css,
                                        REs.attributes.lang, REs.attributes.align, REs.attributes.pad);
            
                  default:
                    return REs.makeRe("^", REs.single[name]);
                  }
                },
                makeRe: function() {
                  var pattern = "";
                  for (var i = 0; i < arguments.length; ++i) {
                    var arg = arguments[i];
                    pattern += (typeof arg === "string") ? arg : arg.source;
                  }
                  return new RegExp(pattern);
                },
                choiceRe: function() {
                  var parts = [arguments[0]];
                  for (var i = 1; i < arguments.length; ++i) {
                    parts[i * 2 - 1] = "|";
                    parts[i * 2] = arguments[i];
                  }
            
                  parts.unshift("(?:");
                  parts.push(")");
                  return REs.makeRe.apply(null, parts);
                }
              };
            
              function RE(name) {
                return (REs.cache[name] || (REs.cache[name] = REs.createRe(name)));
              }
            
              var Modes = {
                newLayout: function(stream, state) {
                  if (stream.match(RE("typeLayout"), false)) {
                    state.spanningLayout = false;
                    return (state.mode = Modes.blockType)(stream, state);
                  }
                  var newMode;
                  if (!textileDisabled(state)) {
                    if (stream.match(RE("listLayout"), false))
                      newMode = Modes.list;
                    else if (stream.match(RE("drawTable"), false))
                      newMode = Modes.table;
                    else if (stream.match(RE("linkDefinition"), false))
                      newMode = Modes.linkDefinition;
                    else if (stream.match(RE("definitionList")))
                      newMode = Modes.definitionList;
                    else if (stream.match(RE("html"), false))
                      newMode = Modes.html;
                  }
                  return (state.mode = (newMode || Modes.text))(stream, state);
                },
            
                blockType: function(stream, state) {
                  var match, type;
                  state.layoutType = null;
            
                  if (match = stream.match(RE("type")))
                    type = match[0];
                  else
                    return (state.mode = Modes.text)(stream, state);
            
                  if (match = type.match(RE("header"))) {
                    state.layoutType = "header";
                    state.header = parseInt(match[0][1]);
                  } else if (type.match(RE("bq"))) {
                    state.layoutType = "quote";
                  } else if (type.match(RE("bc"))) {
                    state.layoutType = "code";
                  } else if (type.match(RE("foot"))) {
                    state.layoutType = "footnote";
                  } else if (type.match(RE("notextile"))) {
                    state.layoutType = "notextile";
                  } else if (type.match(RE("pre"))) {
                    state.layoutType = "pre";
                  } else if (type.match(RE("div"))) {
                    state.layoutType = "div";
                  } else if (type.match(RE("table"))) {
                    state.layoutType = "table";
                  }
            
                  state.mode = Modes.attributes;
                  return tokenStyles(state);
                },
            
                text: function(stream, state) {
                  if (stream.match(RE("text"))) return tokenStyles(state);
            
                  var ch = stream.next();
                  if (ch === '"')
                    return (state.mode = Modes.link)(stream, state);
                  return handlePhraseModifier(stream, state, ch);
                },
            
                attributes: function(stream, state) {
                  state.mode = Modes.layoutLength;
            
                  if (stream.match(RE("attributes")))
                    return tokenStylesWith(state, TOKEN_STYLES.attributes);
                  else
                    return tokenStyles(state);
                },
            
                layoutLength: function(stream, state) {
                  if (stream.eat(".") && stream.eat("."))
                    state.spanningLayout = true;
            
                  state.mode = Modes.text;
                  return tokenStyles(state);
                },
            
                list: function(stream, state) {
                  var match = stream.match(RE("list"));
                  state.listDepth = match[0].length;
                  var listMod = (state.listDepth - 1) % 3;
                  if (!listMod)
                    state.layoutType = "list1";
                  else if (listMod === 1)
                    state.layoutType = "list2";
                  else
                    state.layoutType = "list3";
            
                  state.mode = Modes.attributes;
                  return tokenStyles(state);
                },
            
                link: function(stream, state) {
                  state.mode = Modes.text;
                  if (stream.match(RE("link"))) {
                    stream.match(/\S+/);
                    return tokenStylesWith(state, TOKEN_STYLES.link);
                  }
                  return tokenStyles(state);
                },
            
                linkDefinition: function(stream, state) {
                  stream.skipToEnd();
                  return tokenStylesWith(state, TOKEN_STYLES.linkDefinition);
                },
            
                definitionList: function(stream, state) {
                  stream.match(RE("definitionList"));
            
                  state.layoutType = "definitionList";
            
                  if (stream.match(/\s*$/))
                    state.spanningLayout = true;
                  else
                    state.mode = Modes.attributes;
            
                  return tokenStyles(state);
                },
            
                html: function(stream, state) {
                  stream.skipToEnd();
                  return tokenStylesWith(state, TOKEN_STYLES.html);
                },
            
                table: function(stream, state) {
                  state.layoutType = "table";
                  return (state.mode = Modes.tableCell)(stream, state);
                },
            
                tableCell: function(stream, state) {
                  if (stream.match(RE("tableHeading")))
                    state.tableHeading = true;
                  else
                    stream.eat("|");
            
                  state.mode = Modes.tableCellAttributes;
                  return tokenStyles(state);
                },
            
                tableCellAttributes: function(stream, state) {
                  state.mode = Modes.tableText;
            
                  if (stream.match(RE("tableCellAttributes")))
                    return tokenStylesWith(state, TOKEN_STYLES.attributes);
                  else
                    return tokenStyles(state);
                },
            
                tableText: function(stream, state) {
                  if (stream.match(RE("tableText")))
                    return tokenStyles(state);
            
                  if (stream.peek() === "|") { // end of cell
                    state.mode = Modes.tableCell;
                    return tokenStyles(state);
                  }
                  return handlePhraseModifier(stream, state, stream.next());
                }
              };
            
              CodeMirror.defineMode("textile", function() {
                return {
                  startState: function() {
                    return { mode: Modes.newLayout };
                  },
                  token: function(stream, state) {
                    if (stream.sol()) startNewLine(stream, state);
                    return state.mode(stream, state);
                  },
                  blankLine: blankLine
                };
              });
            
              CodeMirror.defineMIME("text/x-textile", "textile");
            });
            
        • tiddlywiki
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TiddlyWiki mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="tiddlywiki.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="tiddlywiki.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TiddlyWiki</a>
              </ul>
            </div>
            
            <article>
            <h2>TiddlyWiki mode</h2>
            
            
            <div><textarea id="code" name="code">
            !TiddlyWiki Formatting
            * Rendered versions can be found at: http://www.tiddlywiki.com/#Reference
            
            |!Option            | !Syntax            |
            |bold font          | ''bold''           |
            |italic type        | //italic//         |
            |underlined text    | __underlined__     |
            |strikethrough text | --strikethrough--  |
            |superscript text   | super^^script^^    |
            |subscript text     | sub~~script~~      |
            |highlighted text   | @@highlighted@@    |
            |preformatted text  | {{{preformatted}}} |
            
            !Block Elements
            <<<
            !Heading 1
            
            !!Heading 2
            
            !!!Heading 3
            
            !!!!Heading 4
            
            !!!!!Heading 5
            <<<
            
            !!Lists
            <<<
            * unordered list, level 1
            ** unordered list, level 2
            *** unordered list, level 3
            
            # ordered list, level 1
            ## ordered list, level 2
            ### unordered list, level 3
            
            ; definition list, term
            : definition list, description
            <<<
            
            !!Blockquotes
            <<<
            > blockquote, level 1
            >> blockquote, level 2
            >>> blockquote, level 3
            
            > blockquote
            <<<
            
            !!Preformatted Text
            <<<
            {{{
            preformatted (e.g. code)
            }}}
            <<<
            
            !!Code Sections
            <<<
            {{{
            Text style code
            }}}
            
            //{{{
            JS styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
            //}}}
            
            <!--{{{-->
            XML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
            <!--}}}-->
            <<<
            
            !!Tables
            <<<
            |CssClass|k
            |!heading column 1|!heading column 2|
            |row 1, column 1|row 1, column 2|
            |row 2, column 1|row 2, column 2|
            |>|COLSPAN|
            |ROWSPAN| ... |
            |~| ... |
            |CssProperty:value;...| ... |
            |caption|c
            
            ''Annotation:''
            * The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
            * The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
            <<<
            !!Images /% TODO %/
            cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
            
            !Hyperlinks
            * [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler
            ** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}
            * [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}
            ** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).
            
            !Custom Styling
            * {{{@@CssProperty:value;CssProperty:value;...@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.
            * <html><code>{{customCssClass{...}}}</code></html>
            * raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> ... </html>}}}
            
            !Special Markers
            * {{{<br>}}} forces a manual line break
            * {{{----}}} creates a horizontal ruler
            * [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]
            * [[HTML entities local|HtmlEntities]]
            * {{{<<macroName>>}}} calls the respective [[macro|Macros]]
            * To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.
            * To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{"""WikiWord"""}}}.
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'tiddlywiki',      
                    lineNumbers: true,
                    matchBrackets: true
                  });
                </script>
            
                <p>TiddlyWiki mode supports a single configuration.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tiddlywiki</code>.</p>
              </article>
            
          • tiddlywiki.css
            span.cm-underlined {
              text-decoration: underline;
            }
            span.cm-strikethrough {
              text-decoration: line-through;
            }
            span.cm-brace {
              color: #170;
              font-weight: bold;
            }
            span.cm-table {
              color: blue;
              font-weight: bold;
            }
            
          • tiddlywiki.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /***
                |''Name''|tiddlywiki.js|
                |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
                |''Author''|PMario|
                |''Version''|0.1.7|
                |''Status''|''stable''|
                |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
                |''Documentation''|http://codemirror.tiddlyspace.com/|
                |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
                |''CoreVersion''|2.5.0|
                |''Requires''|codemirror.js|
                |''Keywords''|syntax highlighting color code mirror codemirror|
                ! Info
                CoreVersion parameter is needed for TiddlyWiki only!
            ***/
            //{{{
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("tiddlywiki", function () {
              // Tokenizer
              var textwords = {};
            
              var keywords = function () {
                function kw(type) {
                  return { type: type, style: "macro"};
                }
                return {
                  "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
                  "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
                  "permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
                  "search": kw('search'), "slider": kw('slider'),   "tabs": kw('tabs'),
                  "tag": kw('tag'), "tagging": kw('tagging'),       "tags": kw('tags'),
                  "tiddler": kw('tiddler'), "timeline": kw('timeline'),
                  "today": kw('today'), "version": kw('version'),   "option": kw('option'),
            
                  "with": kw('with'),
                  "filter": kw('filter')
                };
              }();
            
              var isSpaceName = /[\w_\-]/i,
              reHR = /^\-\-\-\-+$/,                                 // <hr>
              reWikiCommentStart = /^\/\*\*\*$/,            // /***
              reWikiCommentStop = /^\*\*\*\/$/,             // ***/
              reBlockQuote = /^<<<$/,
            
              reJsCodeStart = /^\/\/\{\{\{$/,                       // //{{{ js block start
              reJsCodeStop = /^\/\/\}\}\}$/,                        // //}}} js stop
              reXmlCodeStart = /^<!--\{\{\{-->$/,           // xml block start
              reXmlCodeStop = /^<!--\}\}\}-->$/,            // xml stop
            
              reCodeBlockStart = /^\{\{\{$/,                        // {{{ TW text div block start
              reCodeBlockStop = /^\}\}\}$/,                 // }}} TW text stop
            
              reUntilCodeStop = /.*?\}\}\}/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
            
              function ret(tp, style, cont) {
                type = tp;
                content = cont;
                return style;
              }
            
              function jsTokenBase(stream, state) {
                var sol = stream.sol(), ch;
            
                state.block = false;        // indicates the start of a code block.
            
                ch = stream.peek();         // don't eat, to make matching simpler
            
                // check start of  blocks
                if (sol && /[<\/\*{}\-]/.test(ch)) {
                  if (stream.match(reCodeBlockStart)) {
                    state.block = true;
                    return chain(stream, state, twTokenCode);
                  }
                  if (stream.match(reBlockQuote)) {
                    return ret('quote', 'quote');
                  }
                  if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
                    return ret('code', 'comment');
                  }
                  if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
                    return ret('code', 'comment');
                  }
                  if (stream.match(reHR)) {
                    return ret('hr', 'hr');
                  }
                } // sol
                ch = stream.next();
            
                if (sol && /[\/\*!#;:>|]/.test(ch)) {
                  if (ch == "!") { // tw header
                    stream.skipToEnd();
                    return ret("header", "header");
                  }
                  if (ch == "*") { // tw list
                    stream.eatWhile('*');
                    return ret("list", "comment");
                  }
                  if (ch == "#") { // tw numbered list
                    stream.eatWhile('#');
                    return ret("list", "comment");
                  }
                  if (ch == ";") { // definition list, term
                    stream.eatWhile(';');
                    return ret("list", "comment");
                  }
                  if (ch == ":") { // definition list, description
                    stream.eatWhile(':');
                    return ret("list", "comment");
                  }
                  if (ch == ">") { // single line quote
                    stream.eatWhile(">");
                    return ret("quote", "quote");
                  }
                  if (ch == '|') {
                    return ret('table', 'header');
                  }
                }
            
                if (ch == '{' && stream.match(/\{\{/)) {
                  return chain(stream, state, twTokenCode);
                }
            
                // rudimentary html:// file:// link matching. TW knows much more ...
                if (/[hf]/i.test(ch)) {
                  if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
                    return ret("link", "link");
                  }
                }
                // just a little string indicator, don't want to have the whole string covered
                if (ch == '"') {
                  return ret('string', 'string');
                }
                if (ch == '~') {    // _no_ CamelCase indicator should be bold
                  return ret('text', 'brace');
                }
                if (/[\[\]]/.test(ch)) { // check for [[..]]
                  if (stream.peek() == ch) {
                    stream.next();
                    return ret('brace', 'brace');
                  }
                }
                if (ch == "@") {    // check for space link. TODO fix @@...@@ highlighting
                  stream.eatWhile(isSpaceName);
                  return ret("link", "link");
                }
                if (/\d/.test(ch)) {        // numbers
                  stream.eatWhile(/\d/);
                  return ret("number", "number");
                }
                if (ch == "/") { // tw invisible comment
                  if (stream.eat("%")) {
                    return chain(stream, state, twTokenComment);
                  }
                  else if (stream.eat("/")) { //
                    return chain(stream, state, twTokenEm);
                  }
                }
                if (ch == "_") { // tw underline
                  if (stream.eat("_")) {
                    return chain(stream, state, twTokenUnderline);
                  }
                }
                // strikethrough and mdash handling
                if (ch == "-") {
                  if (stream.eat("-")) {
                    // if strikethrough looks ugly, change CSS.
                    if (stream.peek() != ' ')
                      return chain(stream, state, twTokenStrike);
                    // mdash
                    if (stream.peek() == ' ')
                      return ret('text', 'brace');
                  }
                }
                if (ch == "'") { // tw bold
                  if (stream.eat("'")) {
                    return chain(stream, state, twTokenStrong);
                  }
                }
                if (ch == "<") { // tw macro
                  if (stream.eat("<")) {
                    return chain(stream, state, twTokenMacro);
                  }
                }
                else {
                  return ret(ch);
                }
            
                // core macro handling
                stream.eatWhile(/[\w\$_]/);
                var word = stream.current(),
                known = textwords.propertyIsEnumerable(word) && textwords[word];
            
                return known ? ret(known.type, known.style, word) : ret("text", null, word);
            
              } // jsTokenBase()
            
              // tw invisible comment
              function twTokenComment(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "%");
                }
                return ret("comment", "comment");
              }
            
              // tw strong / bold
              function twTokenStrong(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "'" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "'");
                }
                return ret("text", "strong");
              }
            
              // tw code
              function twTokenCode(stream, state) {
                var ch, sb = state.block;
            
                if (sb && stream.current()) {
                  return ret("code", "comment");
                }
            
                if (!sb && stream.match(reUntilCodeStop)) {
                  state.tokenize = jsTokenBase;
                  return ret("code", "comment");
                }
            
                if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
                  state.tokenize = jsTokenBase;
                  return ret("code", "comment");
                }
            
                ch = stream.next();
                return (sb) ? ret("code", "comment") : ret("code", "comment");
              }
            
              // tw em / italic
              function twTokenEm(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "/");
                }
                return ret("text", "em");
              }
            
              // tw underlined text
              function twTokenUnderline(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "_" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "_");
                }
                return ret("text", "underlined");
              }
            
              // tw strike through text looks ugly
              // change CSS if needed
              function twTokenStrike(stream, state) {
                var maybeEnd = false, ch;
            
                while (ch = stream.next()) {
                  if (ch == "-" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "-");
                }
                return ret("text", "strikethrough");
              }
            
              // macro
              function twTokenMacro(stream, state) {
                var ch, word, known;
            
                if (stream.current() == '<<') {
                  return ret('brace', 'macro');
                }
            
                ch = stream.next();
                if (!ch) {
                  state.tokenize = jsTokenBase;
                  return ret(ch);
                }
                if (ch == ">") {
                  if (stream.peek() == '>') {
                    stream.next();
                    state.tokenize = jsTokenBase;
                    return ret("brace", "macro");
                  }
                }
            
                stream.eatWhile(/[\w\$_]/);
                word = stream.current();
                known = keywords.propertyIsEnumerable(word) && keywords[word];
            
                if (known) {
                  return ret(known.type, known.style, word);
                }
                else {
                  return ret("macro", null, word);
                }
              }
            
              // Interface
              return {
                startState: function () {
                  return {
                    tokenize: jsTokenBase,
                    indented: 0,
                    level: 0
                  };
                },
            
                token: function (stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
            
                electricChars: ""
              };
            });
            
            CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
            });
            
            //}}}
            
        • tiki
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tiki wiki mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="tiki.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="tiki.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tiki wiki</a>
              </ul>
            </div>
            
            <article>
            <h2>Tiki wiki mode</h2>
            
            
            <div><textarea id="code" name="code">
            Headings
            !Header 1
            !!Header 2
            !!!Header 3
            !!!!Header 4
            !!!!!Header 5
            !!!!!!Header 6
            
            Styling
            -=titlebar=-
            ^^ Box on multi
            lines
            of content^^
            __bold__
            ''italic''
            ===underline===
            ::center::
            --Line Through--
            
            Operators
            ~np~No parse~/np~
            
            Link
            [link|desc|nocache]
            
            Wiki
            ((Wiki))
            ((Wiki|desc))
            ((Wiki|desc|timeout))
            
            Table
            ||row1 col1|row1 col2|row1 col3
            row2 col1|row2 col2|row2 col3
            row3 col1|row3 col2|row3 col3||
            
            Lists:
            *bla
            **bla-1
            ++continue-bla-1
            ***bla-2
            ++continue-bla-1
            *bla
            +continue-bla
            #bla
            ** tra-la-la
            +continue-bla
            #bla
            
            Plugin (standard):
            {PLUGIN(attr="my attr")}
            Plugin Body
            {PLUGIN}
            
            Plugin (inline):
            {plugin attr="my attr"}
            </textarea></div>
            
            <script type="text/javascript">
            	var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'tiki',      
                    lineNumbers: true
                });
            </script>
            
            </article>
            
          • tiki.css
            .cm-tw-syntaxerror {
            	color: #FFF;
            	background-color: #900;
            }
            
            .cm-tw-deleted {
            	text-decoration: line-through;
            }
            
            .cm-tw-header5 {
            	font-weight: bold;
            }
            .cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/
            	padding-left: 10px;
            }
            
            .cm-tw-box {
            	border-top-width: 0px ! important;
            	border-style: solid;
            	border-width: 1px;
            	border-color: inherit;
            }
            
            .cm-tw-underline {
            	text-decoration: underline;
            }
          • tiki.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('tiki', function(config) {
              function inBlock(style, terminator, returnTokenizer) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = inText;
                      break;
                    }
                    stream.next();
                  }
            
                  if (returnTokenizer) state.tokenize = returnTokenizer;
            
                  return style;
                };
              }
            
              function inLine(style) {
                return function(stream, state) {
                  while(!stream.eol()) {
                    stream.next();
                  }
                  state.tokenize = inText;
                  return style;
                };
              }
            
              function inText(stream, state) {
                function chain(parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
            
                var sol = stream.sol();
                var ch = stream.next();
            
                //non start of line
                switch (ch) { //switch is generally much faster than if, so it is used here
                case "{": //plugin
                  stream.eat("/");
                  stream.eatSpace();
                  var tagName = "";
                  var c;
                  while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c;
                  state.tokenize = inPlugin;
                  return "tag";
                  break;
                case "_": //bold
                  if (stream.eat("_")) {
                    return chain(inBlock("strong", "__", inText));
                  }
                  break;
                case "'": //italics
                  if (stream.eat("'")) {
                    // Italic text
                    return chain(inBlock("em", "''", inText));
                  }
                  break;
                case "(":// Wiki Link
                  if (stream.eat("(")) {
                    return chain(inBlock("variable-2", "))", inText));
                  }
                  break;
                case "[":// Weblink
                  return chain(inBlock("variable-3", "]", inText));
                  break;
                case "|": //table
                  if (stream.eat("|")) {
                    return chain(inBlock("comment", "||"));
                  }
                  break;
                case "-":
                  if (stream.eat("=")) {//titleBar
                    return chain(inBlock("header string", "=-", inText));
                  } else if (stream.eat("-")) {//deleted
                    return chain(inBlock("error tw-deleted", "--", inText));
                  }
                  break;
                case "=": //underline
                  if (stream.match("==")) {
                    return chain(inBlock("tw-underline", "===", inText));
                  }
                  break;
                case ":":
                  if (stream.eat(":")) {
                    return chain(inBlock("comment", "::"));
                  }
                  break;
                case "^": //box
                  return chain(inBlock("tw-box", "^"));
                  break;
                case "~": //np
                  if (stream.match("np~")) {
                    return chain(inBlock("meta", "~/np~"));
                  }
                  break;
                }
            
                //start of line types
                if (sol) {
                  switch (ch) {
                  case "!": //header at start of line
                    if (stream.match('!!!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!')) {
                      return chain(inLine("header string"));
                    } else {
                      return chain(inLine("header string"));
                    }
                    break;
                  case "*": //unordered list line item, or <li /> at start of line
                  case "#": //ordered list line item, or <li /> at start of line
                  case "+": //ordered list line item, or <li /> at start of line
                    return chain(inLine("tw-listitem bracket"));
                    break;
                  }
                }
            
                //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
                return null;
              }
            
              var indentUnit = config.indentUnit;
            
              // Return variables for tokenizers
              var pluginName, type;
              function inPlugin(stream, state) {
                var ch = stream.next();
                var peek = stream.peek();
            
                if (ch == "}") {
                  state.tokenize = inText;
                  //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
                  return "tag";
                } else if (ch == "(" || ch == ")") {
                  return "bracket";
                } else if (ch == "=") {
                  type = "equals";
            
                  if (peek == ">") {
                    ch = stream.next();
                    peek = stream.peek();
                  }
            
                  //here we detect values directly after equal character with no quotes
                  if (!/[\'\"]/.test(peek)) {
                    state.tokenize = inAttributeNoQuote();
                  }
                  //end detect values
            
                  return "operator";
                } else if (/[\'\"]/.test(ch)) {
                  state.tokenize = inAttribute(ch);
                  return state.tokenize(stream, state);
                } else {
                  stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
                  return "keyword";
                }
              }
            
              function inAttribute(quote) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.next() == quote) {
                      state.tokenize = inPlugin;
                      break;
                    }
                  }
                  return "string";
                };
              }
            
              function inAttributeNoQuote() {
                return function(stream, state) {
                  while (!stream.eol()) {
                    var ch = stream.next();
                    var peek = stream.peek();
                    if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
                  state.tokenize = inPlugin;
                  break;
                }
              }
              return "string";
            };
                                 }
            
            var curState, setStyle;
            function pass() {
              for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
            }
            
            function cont() {
              pass.apply(null, arguments);
              return true;
            }
            
            function pushContext(pluginName, startOfLine) {
              var noIndent = curState.context && curState.context.noIndent;
              curState.context = {
                prev: curState.context,
                pluginName: pluginName,
                indent: curState.indented,
                startOfLine: startOfLine,
                noIndent: noIndent
              };
            }
            
            function popContext() {
              if (curState.context) curState.context = curState.context.prev;
            }
            
            function element(type) {
              if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
              else if (type == "closePlugin") {
                var err = false;
                if (curState.context) {
                  err = curState.context.pluginName != pluginName;
                  popContext();
                } else {
                  err = true;
                }
                if (err) setStyle = "error";
                return cont(endcloseplugin(err));
              }
              else if (type == "string") {
                if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
                if (curState.tokenize == inText) popContext();
                return cont();
              }
              else return cont();
            }
            
            function endplugin(startOfLine) {
              return function(type) {
                if (
                  type == "selfclosePlugin" ||
                    type == "endPlugin"
                )
                  return cont();
                if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
                return cont();
              };
            }
            
            function endcloseplugin(err) {
              return function(type) {
                if (err) setStyle = "error";
                if (type == "endPlugin") return cont();
                return pass();
              };
            }
            
            function attributes(type) {
              if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
              if (type == "equals") return cont(attvalue, attributes);
              return pass();
            }
            function attvalue(type) {
              if (type == "keyword") {setStyle = "string"; return cont();}
              if (type == "string") return cont(attvaluemaybe);
              return pass();
            }
            function attvaluemaybe(type) {
              if (type == "string") return cont(attvaluemaybe);
              else return pass();
            }
            return {
              startState: function() {
                return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
              },
              token: function(stream, state) {
                if (stream.sol()) {
                  state.startOfLine = true;
                  state.indented = stream.indentation();
                }
                if (stream.eatSpace()) return null;
            
                setStyle = type = pluginName = null;
                var style = state.tokenize(stream, state);
                if ((style || type) && style != "comment") {
                  curState = state;
                  while (true) {
                    var comb = state.cc.pop() || element;
                    if (comb(type || style)) break;
                  }
                }
                state.startOfLine = false;
                return setStyle || style;
              },
              indent: function(state, textAfter) {
                var context = state.context;
                if (context && context.noIndent) return 0;
                if (context && /^{\//.test(textAfter))
                    context = context.prev;
                    while (context && !context.startOfLine)
                      context = context.prev;
                    if (context) return context.indent + indentUnit;
                    else return 0;
                   },
                electricChars: "/"
              };
            });
            
            CodeMirror.defineMIME("text/tiki", "tiki");
            
            });
            
        • toml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TOML Mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="toml.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TOML Mode</a>
              </ul>
            </div>
            
            <article>
            <h2>TOML Mode</h2>
            <form><textarea id="code" name="code">
            # This is a TOML document. Boom.
            
            title = "TOML Example"
            
            [owner]
            name = "Tom Preston-Werner"
            organization = "GitHub"
            bio = "GitHub Cofounder &amp; CEO\nLikes tater tots and beer."
            dob = 1979-05-27T07:32:00Z # First class dates? Why not?
            
            [database]
            server = "192.168.1.1"
            ports = [ 8001, 8001, 8002 ]
            connection_max = 5000
            enabled = true
            
            [servers]
            
              # You can indent as you please. Tabs or spaces. TOML don't care.
              [servers.alpha]
              ip = "10.0.0.1"
              dc = "eqdc10"
              
              [servers.beta]
              ip = "10.0.0.2"
              dc = "eqdc10"
              
            [clients]
            data = [ ["gamma", "delta"], [1, 2] ]
            
            # Line breaks are OK when inside arrays
            hosts = [
              "alpha",
              "omega"
            ]
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "toml"},
                    lineNumbers: true
                  });
                </script>
                <h3>The TOML Mode</h3>
                  <p> Created by Forbes Lindesay.</p>
                <p><strong>MIME type defined:</strong> <code>text/x-toml</code>.</p>
              </article>
            
          • toml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("toml", function () {
              return {
                startState: function () {
                  return {
                    inString: false,
                    stringType: "",
                    lhs: true,
                    inArray: 0
                  };
                },
                token: function (stream, state) {
                  //check for state changes
                  if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) {
                    state.stringType = stream.peek();
                    stream.next(); // Skip quote
                    state.inString = true; // Update state
                  }
                  if (stream.sol() && state.inArray === 0) {
                    state.lhs = true;
                  }
                  //return state
                  if (state.inString) {
                    while (state.inString && !stream.eol()) {
                      if (stream.peek() === state.stringType) {
                        stream.next(); // Skip quote
                        state.inString = false; // Clear flag
                      } else if (stream.peek() === '\\') {
                        stream.next();
                        stream.next();
                      } else {
                        stream.match(/^.[^\\\"\']*/);
                      }
                    }
                    return state.lhs ? "property string" : "string"; // Token style
                  } else if (state.inArray && stream.peek() === ']') {
                    stream.next();
                    state.inArray--;
                    return 'bracket';
                  } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) {
                    stream.next();//skip closing ]
                    // array of objects has an extra open & close []
                    if (stream.peek() === ']') stream.next();
                    return "atom";
                  } else if (stream.peek() === "#") {
                    stream.skipToEnd();
                    return "comment";
                  } else if (stream.eatSpace()) {
                    return null;
                  } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) {
                    return "property";
                  } else if (state.lhs && stream.peek() === "=") {
                    stream.next();
                    state.lhs = false;
                    return null;
                  } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) {
                    return 'atom'; //date
                  } else if (!state.lhs && (stream.match('true') || stream.match('false'))) {
                    return 'atom';
                  } else if (!state.lhs && stream.peek() === '[') {
                    state.inArray++;
                    stream.next();
                    return 'bracket';
                  } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) {
                    return 'number';
                  } else if (!stream.eatSpace()) {
                    stream.next();
                  }
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME('text/x-toml', 'toml');
            
            });
            
        • tornado
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tornado template mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="tornado.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/marijnh/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tornado</a>
              </ul>
            </div>
            
            <article>
            <h2>Tornado template mode</h2>
            <form><textarea id="code" name="code">
            <!doctype html>
            <html>
                <head>
                    <title>My Tornado web application</title>
                </head>
                <body>
                    <h1>
                        {{ title }}
                    </h1>
                    <ul class="my-list">
                        {% for item in items %}
                            <li>{% item.name %}</li>
                        {% empty %}
                            <li>You have no items in your list.</li>
                        {% end %}
                    </ul>
                </body>
            </html>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "tornado",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Mode for HTML with embedded Tornado template markup.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tornado</code></p>
              </article>
            
          • tornado.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
                    require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
                        "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("tornado:inner", function() {
                var keywords = ["and","as","assert","autoescape","block","break","class","comment","context",
                                "continue","datetime","def","del","elif","else","end","escape","except",
                                "exec","extends","false","finally","for","from","global","if","import","in",
                                "include","is","json_encode","lambda","length","linkify","load","module",
                                "none","not","or","pass","print","put","raise","raw","return","self","set",
                                "squeeze","super","true","try","url_escape","while","with","without","xhtml_escape","yield"];
                keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
            
                function tokenBase (stream, state) {
                  stream.eatWhile(/[^\{]/);
                  var ch = stream.next();
                  if (ch == "{") {
                    if (ch = stream.eat(/\{|%|#/)) {
                      state.tokenize = inTag(ch);
                      return "tag";
                    }
                  }
                }
                function inTag (close) {
                  if (close == "{") {
                    close = "}";
                  }
                  return function (stream, state) {
                    var ch = stream.next();
                    if ((ch == close) && stream.eat("}")) {
                      state.tokenize = tokenBase;
                      return "tag";
                    }
                    if (stream.match(keywords)) {
                      return "keyword";
                    }
                    return close == "#" ? "comment" : "string";
                  };
                }
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  }
                };
              });
            
              CodeMirror.defineMode("tornado", function(config) {
                var htmlBase = CodeMirror.getMode(config, "text/html");
                var tornadoInner = CodeMirror.getMode(config, "tornado:inner");
                return CodeMirror.overlayMode(htmlBase, tornadoInner);
              });
            
              CodeMirror.defineMIME("text/x-tornado", "tornado");
            });
            
        • turtle
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Turtle mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="turtle.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Turtle</a>
              </ul>
            </div>
            
            <article>
            <h2>Turtle mode</h2>
            <form><textarea id="code" name="code">
            @prefix foaf: <http://xmlns.com/foaf/0.1/> .
            @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
            @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
            
            <http://purl.org/net/bsletten> 
                a foaf:Person;
                foaf:interest <http://www.w3.org/2000/01/sw/>;
                foaf:based_near [
                    geo:lat "34.0736111" ;
                    geo:lon "-118.3994444"
               ]
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/turtle",
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/turtle</code>.</p>
            
              </article>
            
          • turtle.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("turtle", function(config) {
              var indentUnit = config.indentUnit;
              var curPunc;
            
              function wordRegexp(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var ops = wordRegexp([]);
              var keywords = wordRegexp(["@prefix", "@base", "a"]);
              var operatorChars = /[*+\-<>=&|]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                curPunc = null;
                if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
                  stream.match(/^[^\s\u00a0>]*>?/);
                  return "atom";
                }
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                }
                else if (/[{}\(\),\.;\[\]]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (operatorChars.test(ch)) {
                  stream.eatWhile(operatorChars);
                  return null;
                }
                else if (ch == ":") {
                      return "operator";
                    } else {
                  stream.eatWhile(/[_\w\d]/);
                  if(stream.peek() == ":") {
                    return "variable-3";
                  } else {
                         var word = stream.current();
            
                         if(keywords.test(word)) {
                                    return "meta";
                         }
            
                         if(ch >= "A" && ch <= "Z") {
                                return "comment";
                             } else {
                                    return "keyword";
                             }
                  }
                  var word = stream.current();
                  if (ops.test(word))
                    return null;
                  else if (keywords.test(word))
                    return "meta";
                  else
                    return "variable";
                }
              }
            
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
            
              function pushContext(state, type, col) {
                state.context = {prev: state.context, indent: state.indent, col: col, type: type};
              }
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          context: null,
                          indent: 0,
                          col: 0};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null) state.context.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
                    state.context.align = true;
                  }
            
                  if (curPunc == "(") pushContext(state, ")", stream.column());
                  else if (curPunc == "[") pushContext(state, "]", stream.column());
                  else if (curPunc == "{") pushContext(state, "}", stream.column());
                  else if (/[\]\}\)]/.test(curPunc)) {
                    while (state.context && state.context.type == "pattern") popContext(state);
                    if (state.context && curPunc == state.context.type) popContext(state);
                  }
                  else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
                  else if (/atom|string|variable/.test(style) && state.context) {
                    if (/[\}\]]/.test(state.context.type))
                      pushContext(state, "pattern", stream.column());
                    else if (state.context.type == "pattern" && !state.context.align) {
                      state.context.align = true;
                      state.context.col = stream.column();
                    }
                  }
            
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var firstChar = textAfter && textAfter.charAt(0);
                  var context = state.context;
                  if (/[\]\}]/.test(firstChar))
                    while (context && context.type == "pattern") context = context.prev;
            
                  var closing = context && firstChar == context.type;
                  if (!context)
                    return 0;
                  else if (context.type == "pattern")
                    return context.col;
                  else if (context.align)
                    return context.col + (closing ? 0 : 1);
                  else
                    return context.indent + (closing ? 0 : indentUnit);
                },
            
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/turtle", "turtle");
            
            });
            
        • vb
          • index.html
            <!doctype html>
            
            <title>CodeMirror: VB.NET mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link href="http://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet" type="text/css">
            <script src="../../lib/codemirror.js"></script>
            <script src="vb.js"></script>
            <script type="text/javascript" src="../../addon/runmode/runmode.js"></script>
            <style>
                  .CodeMirror {border: 1px solid #aaa; height:210px; height: auto;}
                  .CodeMirror-scroll { overflow-x: auto; overflow-y: hidden;}
                  .CodeMirror pre { font-family: Inconsolata; font-size: 14px}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">VB.NET</a>
              </ul>
            </div>
            
            <article>
            <h2>VB.NET mode</h2>
            
            <script type="text/javascript">
            function test(golden, text) {
              var ok = true;
              var i = 0;
              function callback(token, style, lineNo, pos){
            		//console.log(String(token) + " " + String(style) + " " + String(lineNo) + " " + String(pos));
                var result = [String(token), String(style)];
                if (golden[i][0] != result[0] || golden[i][1] != result[1]){
                  return "Error, expected: " + String(golden[i]) + ", got: " + String(result);
                  ok = false;
                }
                i++;
              }
              CodeMirror.runMode(text, "text/x-vb",callback); 
            
              if (ok) return "Tests OK";
            }
            function testTypes() {
              var golden = [['Integer','keyword'],[' ','null'],['Float','keyword']]
              var text =  "Integer Float";
              return test(golden,text);
            }
            function testIf(){
              var golden = [['If','keyword'],[' ','null'],['True','keyword'],[' ','null'],['End','keyword'],[' ','null'],['If','keyword']];
              var text = 'If True End If';
              return test(golden, text);
            }
            function testDecl(){
               var golden = [['Dim','keyword'],[' ','null'],['x','variable'],[' ','null'],['as','keyword'],[' ','null'],['Integer','keyword']];
               var text = 'Dim x as Integer';
               return test(golden, text);
            }
            function testAll(){
              var result = "";
            
              result += testTypes() + "\n";
              result += testIf() + "\n";
              result += testDecl() + "\n";
              return result;
            
            }
            function initText(editor) {
              var content = 'Class rocket\nPrivate quality as Double\nPublic Sub launch() as String\nif quality > 0.8\nlaunch = "Successful"\nElse\nlaunch = "Failed"\nEnd If\nEnd sub\nEnd class\n';
              editor.setValue(content);
              for (var i =0; i< editor.lineCount(); i++) editor.indentLine(i);
            }
            function init() {
                editor = CodeMirror.fromTextArea(document.getElementById("solution"), {
                    lineNumbers: true,
                    mode: "text/x-vb",
                    readOnly: false
                });
                runTest();
            }
            function runTest() {
            	document.getElementById('testresult').innerHTML = testAll();
              initText(editor);
            	
            }
            document.body.onload = init;
            </script>
            
              <div id="edit">
              <textarea style="width:95%;height:200px;padding:5px;" name="solution" id="solution" ></textarea>
              </div>
              <pre id="testresult"></pre>
              <p>MIME type defined: <code>text/x-vb</code>.</p>
            
            </article>
            
          • vb.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("vb", function(conf, parserConf) {
                var ERRORCLASS = 'error';
            
                function wordRegexp(words) {
                    return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
                }
            
                var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]");
                var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
                var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
                var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
                var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
                var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
            
                var openingKeywords = ['class','module', 'sub','enum','select','while','if','function',  'get','set','property', 'try'];
                var middleKeywords = ['else','elseif','case', 'catch'];
                var endKeywords = ['next','loop'];
            
                var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'in']);
                var commonkeywords = ['as', 'dim', 'break',  'continue','optional', 'then',  'until',
                                      'goto', 'byval','byref','new','handles','property', 'return',
                                      'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false'];
                var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single'];
            
                var keywords = wordRegexp(commonkeywords);
                var types = wordRegexp(commontypes);
                var stringPrefixes = '"';
            
                var opening = wordRegexp(openingKeywords);
                var middle = wordRegexp(middleKeywords);
                var closing = wordRegexp(endKeywords);
                var doubleClosing = wordRegexp(['end']);
                var doOpening = wordRegexp(['do']);
            
                var indentInfo = null;
            
            
            
            
                function indent(_stream, state) {
                  state.currentIndent++;
                }
            
                function dedent(_stream, state) {
                  state.currentIndent--;
                }
                // tokenizers
                function tokenBase(stream, state) {
                    if (stream.eatSpace()) {
                        return null;
                    }
            
                    var ch = stream.peek();
            
                    // Handle Comments
                    if (ch === "'") {
                        stream.skipToEnd();
                        return 'comment';
                    }
            
            
                    // Handle Number Literals
                    if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) {
                        var floatLiteral = false;
                        // Floats
                        if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; }
                        else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; }
                        else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; }
            
                        if (floatLiteral) {
                            // Float literals may be "imaginary"
                            stream.eat(/J/i);
                            return 'number';
                        }
                        // Integers
                        var intLiteral = false;
                        // Hex
                        if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
                        // Octal
                        else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
                        // Decimal
                        else if (stream.match(/^[1-9]\d*F?/)) {
                            // Decimal literals may be "imaginary"
                            stream.eat(/J/i);
                            // TODO - Can you have imaginary longs?
                            intLiteral = true;
                        }
                        // Zero by itself with no other piece of number.
                        else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                        if (intLiteral) {
                            // Integer literals may be "long"
                            stream.eat(/L/i);
                            return 'number';
                        }
                    }
            
                    // Handle Strings
                    if (stream.match(stringPrefixes)) {
                        state.tokenize = tokenStringFactory(stream.current());
                        return state.tokenize(stream, state);
                    }
            
                    // Handle operators and Delimiters
                    if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
                        return null;
                    }
                    if (stream.match(doubleOperators)
                        || stream.match(singleOperators)
                        || stream.match(wordOperators)) {
                        return 'operator';
                    }
                    if (stream.match(singleDelimiters)) {
                        return null;
                    }
                    if (stream.match(doOpening)) {
                        indent(stream,state);
                        state.doInCurrentLine = true;
                        return 'keyword';
                    }
                    if (stream.match(opening)) {
                        if (! state.doInCurrentLine)
                          indent(stream,state);
                        else
                          state.doInCurrentLine = false;
                        return 'keyword';
                    }
                    if (stream.match(middle)) {
                        return 'keyword';
                    }
            
                    if (stream.match(doubleClosing)) {
                        dedent(stream,state);
                        dedent(stream,state);
                        return 'keyword';
                    }
                    if (stream.match(closing)) {
                        dedent(stream,state);
                        return 'keyword';
                    }
            
                    if (stream.match(types)) {
                        return 'keyword';
                    }
            
                    if (stream.match(keywords)) {
                        return 'keyword';
                    }
            
                    if (stream.match(identifiers)) {
                        return 'variable';
                    }
            
                    // Handle non-detected items
                    stream.next();
                    return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                    var singleline = delimiter.length == 1;
                    var OUTCLASS = 'string';
            
                    return function(stream, state) {
                        while (!stream.eol()) {
                            stream.eatWhile(/[^'"]/);
                            if (stream.match(delimiter)) {
                                state.tokenize = tokenBase;
                                return OUTCLASS;
                            } else {
                                stream.eat(/['"]/);
                            }
                        }
                        if (singleline) {
                            if (parserConf.singleLineStringErrors) {
                                return ERRORCLASS;
                            } else {
                                state.tokenize = tokenBase;
                            }
                        }
                        return OUTCLASS;
                    };
                }
            
            
                function tokenLexer(stream, state) {
                    var style = state.tokenize(stream, state);
                    var current = stream.current();
            
                    // Handle '.' connected identifiers
                    if (current === '.') {
                        style = state.tokenize(stream, state);
                        current = stream.current();
                        if (style === 'variable') {
                            return 'variable';
                        } else {
                            return ERRORCLASS;
                        }
                    }
            
            
                    var delimiter_index = '[({'.indexOf(current);
                    if (delimiter_index !== -1) {
                        indent(stream, state );
                    }
                    if (indentInfo === 'dedent') {
                        if (dedent(stream, state)) {
                            return ERRORCLASS;
                        }
                    }
                    delimiter_index = '])}'.indexOf(current);
                    if (delimiter_index !== -1) {
                        if (dedent(stream, state)) {
                            return ERRORCLASS;
                        }
                    }
            
                    return style;
                }
            
                var external = {
                    electricChars:"dDpPtTfFeE ",
                    startState: function() {
                        return {
                          tokenize: tokenBase,
                          lastToken: null,
                          currentIndent: 0,
                          nextLineIndent: 0,
                          doInCurrentLine: false
            
            
                      };
                    },
            
                    token: function(stream, state) {
                        if (stream.sol()) {
                          state.currentIndent += state.nextLineIndent;
                          state.nextLineIndent = 0;
                          state.doInCurrentLine = 0;
                        }
                        var style = tokenLexer(stream, state);
            
                        state.lastToken = {style:style, content: stream.current()};
            
            
            
                        return style;
                    },
            
                    indent: function(state, textAfter) {
                        var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
                        if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
                        if(state.currentIndent < 0) return 0;
                        return state.currentIndent * conf.indentUnit;
                    }
            
                };
                return external;
            });
            
            CodeMirror.defineMIME("text/x-vb", "vb");
            
            });
            
        • vbscript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: VBScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="vbscript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">VBScript</a>
              </ul>
            </div>
            
            <article>
            <h2>VBScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            ' Pete Guhl
            ' 03-04-2012
            '
            ' Basic VBScript support for codemirror2
            
            Const ForReading = 1, ForWriting = 2, ForAppending = 8
            
            Call Sub020_PostBroadcastToUrbanAirship(strUserName, strPassword, intTransmitID, strResponse)
            
            If Not IsNull(strResponse) AND Len(strResponse) = 0 Then
            	boolTransmitOkYN = False
            Else
            	' WScript.Echo "Oh Happy Day! Oh Happy DAY!"
            	boolTransmitOkYN = True
            End If
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/vbscript</code>.</p>
              </article>
            
          • vbscript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
            For extra ASP classic objects, initialize CodeMirror instance with this option:
                isASP: true
            
            E.G.:
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    isASP: true
                  });
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("vbscript", function(conf, parserConf) {
                var ERRORCLASS = 'error';
            
                function wordRegexp(words) {
                    return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
                }
            
                var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]");
                var doubleOperators = new RegExp("^((<>)|(<=)|(>=))");
                var singleDelimiters = new RegExp('^[\\.,]');
                var brakets = new RegExp('^[\\(\\)]');
                var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*");
            
                var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for'];
                var middleKeywords = ['else','elseif','case'];
                var endKeywords = ['next','loop','wend'];
            
                var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']);
                var commonkeywords = ['dim', 'redim', 'then',  'until', 'randomize',
                                      'byval','byref','new','property', 'exit', 'in',
                                      'const','private', 'public',
                                      'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me'];
            
                //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx
                var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];
                //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx
                var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart',
                                    'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject',
                                    'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left',
                                    'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round',
                                    'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp',
                                    'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year'];
            
                //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx
                var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare',
                                     'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek',
                                     'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError',
                                     'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2',
                                     'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo',
                                     'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse',
                                     'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray'];
                //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx
                var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp'];
                var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count'];
                var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit'];
            
                var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application'];
                var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response
                                          'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request
                                          'contents', 'staticobjects', //application
                                          'codepage', 'lcid', 'sessionid', 'timeout', //session
                                          'scripttimeout']; //server
                var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response
                                       'binaryread', //request
                                       'remove', 'removeall', 'lock', 'unlock', //application
                                       'abandon', //session
                                       'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server
            
                var knownWords = knownMethods.concat(knownProperties);
            
                builtinObjsWords = builtinObjsWords.concat(builtinConsts);
            
                if (conf.isASP){
                    builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords);
                    knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties);
                };
            
                var keywords = wordRegexp(commonkeywords);
                var atoms = wordRegexp(atomWords);
                var builtinFuncs = wordRegexp(builtinFuncsWords);
                var builtinObjs = wordRegexp(builtinObjsWords);
                var known = wordRegexp(knownWords);
                var stringPrefixes = '"';
            
                var opening = wordRegexp(openingKeywords);
                var middle = wordRegexp(middleKeywords);
                var closing = wordRegexp(endKeywords);
                var doubleClosing = wordRegexp(['end']);
                var doOpening = wordRegexp(['do']);
                var noIndentWords = wordRegexp(['on error resume next', 'exit']);
                var comment = wordRegexp(['rem']);
            
            
                function indent(_stream, state) {
                  state.currentIndent++;
                }
            
                function dedent(_stream, state) {
                  state.currentIndent--;
                }
                // tokenizers
                function tokenBase(stream, state) {
                    if (stream.eatSpace()) {
                        return 'space';
                        //return null;
                    }
            
                    var ch = stream.peek();
            
                    // Handle Comments
                    if (ch === "'") {
                        stream.skipToEnd();
                        return 'comment';
                    }
                    if (stream.match(comment)){
                        stream.skipToEnd();
                        return 'comment';
                    }
            
            
                    // Handle Number Literals
                    if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) {
                        var floatLiteral = false;
                        // Floats
                        if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; }
                        else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
                        else if (stream.match(/^\.\d+/)) { floatLiteral = true; }
            
                        if (floatLiteral) {
                            // Float literals may be "imaginary"
                            stream.eat(/J/i);
                            return 'number';
                        }
                        // Integers
                        var intLiteral = false;
                        // Hex
                        if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
                        // Octal
                        else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
                        // Decimal
                        else if (stream.match(/^[1-9]\d*F?/)) {
                            // Decimal literals may be "imaginary"
                            stream.eat(/J/i);
                            // TODO - Can you have imaginary longs?
                            intLiteral = true;
                        }
                        // Zero by itself with no other piece of number.
                        else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                        if (intLiteral) {
                            // Integer literals may be "long"
                            stream.eat(/L/i);
                            return 'number';
                        }
                    }
            
                    // Handle Strings
                    if (stream.match(stringPrefixes)) {
                        state.tokenize = tokenStringFactory(stream.current());
                        return state.tokenize(stream, state);
                    }
            
                    // Handle operators and Delimiters
                    if (stream.match(doubleOperators)
                        || stream.match(singleOperators)
                        || stream.match(wordOperators)) {
                        return 'operator';
                    }
                    if (stream.match(singleDelimiters)) {
                        return null;
                    }
            
                    if (stream.match(brakets)) {
                        return "bracket";
                    }
            
                    if (stream.match(noIndentWords)) {
                        state.doInCurrentLine = true;
            
                        return 'keyword';
                    }
            
                    if (stream.match(doOpening)) {
                        indent(stream,state);
                        state.doInCurrentLine = true;
            
                        return 'keyword';
                    }
                    if (stream.match(opening)) {
                        if (! state.doInCurrentLine)
                          indent(stream,state);
                        else
                          state.doInCurrentLine = false;
            
                        return 'keyword';
                    }
                    if (stream.match(middle)) {
                        return 'keyword';
                    }
            
            
                    if (stream.match(doubleClosing)) {
                        dedent(stream,state);
                        dedent(stream,state);
            
                        return 'keyword';
                    }
                    if (stream.match(closing)) {
                        if (! state.doInCurrentLine)
                          dedent(stream,state);
                        else
                          state.doInCurrentLine = false;
            
                        return 'keyword';
                    }
            
                    if (stream.match(keywords)) {
                        return 'keyword';
                    }
            
                    if (stream.match(atoms)) {
                        return 'atom';
                    }
            
                    if (stream.match(known)) {
                        return 'variable-2';
                    }
            
                    if (stream.match(builtinFuncs)) {
                        return 'builtin';
                    }
            
                    if (stream.match(builtinObjs)){
                        return 'variable-2';
                    }
            
                    if (stream.match(identifiers)) {
                        return 'variable';
                    }
            
                    // Handle non-detected items
                    stream.next();
                    return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                    var singleline = delimiter.length == 1;
                    var OUTCLASS = 'string';
            
                    return function(stream, state) {
                        while (!stream.eol()) {
                            stream.eatWhile(/[^'"]/);
                            if (stream.match(delimiter)) {
                                state.tokenize = tokenBase;
                                return OUTCLASS;
                            } else {
                                stream.eat(/['"]/);
                            }
                        }
                        if (singleline) {
                            if (parserConf.singleLineStringErrors) {
                                return ERRORCLASS;
                            } else {
                                state.tokenize = tokenBase;
                            }
                        }
                        return OUTCLASS;
                    };
                }
            
            
                function tokenLexer(stream, state) {
                    var style = state.tokenize(stream, state);
                    var current = stream.current();
            
                    // Handle '.' connected identifiers
                    if (current === '.') {
                        style = state.tokenize(stream, state);
            
                        current = stream.current();
                        if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) {
                            if (style === 'builtin' || style === 'keyword') style='variable';
                            if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2';
            
                            return style;
                        } else {
                            return ERRORCLASS;
                        }
                    }
            
                    return style;
                }
            
                var external = {
                    electricChars:"dDpPtTfFeE ",
                    startState: function() {
                        return {
                          tokenize: tokenBase,
                          lastToken: null,
                          currentIndent: 0,
                          nextLineIndent: 0,
                          doInCurrentLine: false,
                          ignoreKeyword: false
            
            
                      };
                    },
            
                    token: function(stream, state) {
                        if (stream.sol()) {
                          state.currentIndent += state.nextLineIndent;
                          state.nextLineIndent = 0;
                          state.doInCurrentLine = 0;
                        }
                        var style = tokenLexer(stream, state);
            
                        state.lastToken = {style:style, content: stream.current()};
            
                        if (style==='space') style=null;
            
                        return style;
                    },
            
                    indent: function(state, textAfter) {
                        var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
                        if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
                        if(state.currentIndent < 0) return 0;
                        return state.currentIndent * conf.indentUnit;
                    }
            
                };
                return external;
            });
            
            CodeMirror.defineMIME("text/vbscript", "vbscript");
            
            });
            
        • velocity
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Velocity mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="velocity.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Velocity</a>
              </ul>
            </div>
            
            <article>
            <h2>Velocity mode</h2>
            <form><textarea id="code" name="code">
            ## Velocity Code Demo
            #*
               based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )
               August 2011
            *#
            
            #*
               This is a multiline comment.
               This is the second line
            *#
            
            #[[ hello steve
               This has invalid syntax that would normally need "poor man's escaping" like:
            
               #define()
            
               ${blah
            ]]#
            
            #include( "disclaimer.txt" "opinion.txt" )
            #include( $foo $bar )
            
            #parse( "lecorbusier.vm" )
            #parse( $foo )
            
            #evaluate( 'string with VTL #if(true)will be displayed#end' )
            
            #define( $hello ) Hello $who #end #set( $who = "World!") $hello ## displays Hello World!
            
            #foreach( $customer in $customerList )
            
                $foreach.count $customer.Name
            
                #if( $foo == ${bar})
                    it's true!
                    #break
                #{else}
                    it's not!
                    #stop
                #end
            
                #if ($foreach.parent.hasNext)
                    $velocityCount
                #end
            #end
            
            $someObject.getValues("this is a string split
                    across lines")
            
            $someObject("This plus $something in the middle").method(7567).property
            
            #macro( tablerows $color $somelist )
                #foreach( $something in $somelist )
                    <tr><td bgcolor=$color>$something</td></tr>
                    <tr><td bgcolor=$color>$bodyContent</td></tr>
                #end
            #end
            
            #tablerows("red" ["dadsdf","dsa"])
            #@tablerows("red" ["dadsdf","dsa"]) some body content #end
            
               Variable reference: #set( $monkey = $bill )
               String literal: #set( $monkey.Friend = 'monica' )
               Property reference: #set( $monkey.Blame = $whitehouse.Leak )
               Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )
               Number literal: #set( $monkey.Number = 123 )
               Range operator: #set( $monkey.Numbers = [1..3] )
               Object list: #set( $monkey.Say = ["Not", $my, "fault"] )
               Object map: #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"})
            
            The RHS can also be a simple arithmetic expression, such as:
            Addition: #set( $value = $foo + 1 )
               Subtraction: #set( $value = $bar - 1 )
               Multiplication: #set( $value = $foo * $bar )
               Division: #set( $value = $foo / $bar )
               Remainder: #set( $value = $foo % $bar )
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "night",
                    lineNumbers: true,
                    indentUnit: 4,
                    mode: "text/velocity"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>
            
              </article>
            
          • velocity.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("velocity", function() {
                function parseWords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var keywords = parseWords("#end #else #break #stop #[[ #]] " +
                                          "#{end} #{else} #{break} #{stop}");
                var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
                                           "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
                var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent");
                var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
            
                function chain(stream, state, f) {
                    state.tokenize = f;
                    return f(stream, state);
                }
                function tokenBase(stream, state) {
                    var beforeParams = state.beforeParams;
                    state.beforeParams = false;
                    var ch = stream.next();
                    // start of unparsed string?
                    if ((ch == "'") && state.inParams) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenString(ch));
                    }
                    // start of parsed string?
                    else if ((ch == '"')) {
                        state.lastTokenWasBuiltin = false;
                        if (state.inString) {
                            state.inString = false;
                            return "string";
                        }
                        else if (state.inParams)
                            return chain(stream, state, tokenString(ch));
                    }
                    // is it one of the special signs []{}().,;? Seperator?
                    else if (/[\[\]{}\(\),;\.]/.test(ch)) {
                        if (ch == "(" && beforeParams)
                            state.inParams = true;
                        else if (ch == ")") {
                            state.inParams = false;
                            state.lastTokenWasBuiltin = true;
                        }
                        return null;
                    }
                    // start of a number value?
                    else if (/\d/.test(ch)) {
                        state.lastTokenWasBuiltin = false;
                        stream.eatWhile(/[\w\.]/);
                        return "number";
                    }
                    // multi line comment?
                    else if (ch == "#" && stream.eat("*")) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenComment);
                    }
                    // unparsed content?
                    else if (ch == "#" && stream.match(/ *\[ *\[/)) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenUnparsed);
                    }
                    // single line comment?
                    else if (ch == "#" && stream.eat("#")) {
                        state.lastTokenWasBuiltin = false;
                        stream.skipToEnd();
                        return "comment";
                    }
                    // variable?
                    else if (ch == "$") {
                        stream.eatWhile(/[\w\d\$_\.{}]/);
                        // is it one of the specials?
                        if (specials && specials.propertyIsEnumerable(stream.current())) {
                            return "keyword";
                        }
                        else {
                            state.lastTokenWasBuiltin = true;
                            state.beforeParams = true;
                            return "builtin";
                        }
                    }
                    // is it a operator?
                    else if (isOperatorChar.test(ch)) {
                        state.lastTokenWasBuiltin = false;
                        stream.eatWhile(isOperatorChar);
                        return "operator";
                    }
                    else {
                        // get the whole word
                        stream.eatWhile(/[\w\$_{}@]/);
                        var word = stream.current();
                        // is it one of the listed keywords?
                        if (keywords && keywords.propertyIsEnumerable(word))
                            return "keyword";
                        // is it one of the listed functions?
                        if (functions && functions.propertyIsEnumerable(word) ||
                                (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") &&
                                 !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) {
                            state.beforeParams = true;
                            state.lastTokenWasBuiltin = false;
                            return "keyword";
                        }
                        if (state.inString) {
                            state.lastTokenWasBuiltin = false;
                            return "string";
                        }
                        if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin)
                            return "builtin";
                        // default: just a "word"
                        state.lastTokenWasBuiltin = false;
                        return null;
                    }
                }
            
                function tokenString(quote) {
                    return function(stream, state) {
                        var escaped = false, next, end = false;
                        while ((next = stream.next()) != null) {
                            if ((next == quote) && !escaped) {
                                end = true;
                                break;
                            }
                            if (quote=='"' && stream.peek() == '$' && !escaped) {
                                state.inString = true;
                                end = true;
                                break;
                            }
                            escaped = !escaped && next == "\\";
                        }
                        if (end) state.tokenize = tokenBase;
                        return "string";
                    };
                }
            
                function tokenComment(stream, state) {
                    var maybeEnd = false, ch;
                    while (ch = stream.next()) {
                        if (ch == "#" && maybeEnd) {
                            state.tokenize = tokenBase;
                            break;
                        }
                        maybeEnd = (ch == "*");
                    }
                    return "comment";
                }
            
                function tokenUnparsed(stream, state) {
                    var maybeEnd = 0, ch;
                    while (ch = stream.next()) {
                        if (ch == "#" && maybeEnd == 2) {
                            state.tokenize = tokenBase;
                            break;
                        }
                        if (ch == "]")
                            maybeEnd++;
                        else if (ch != " ")
                            maybeEnd = 0;
                    }
                    return "meta";
                }
                // Interface
            
                return {
                    startState: function() {
                        return {
                            tokenize: tokenBase,
                            beforeParams: false,
                            inParams: false,
                            inString: false,
                            lastTokenWasBuiltin: false
                        };
                    },
            
                    token: function(stream, state) {
                        if (stream.eatSpace()) return null;
                        return state.tokenize(stream, state);
                    },
                    blockCommentStart: "#*",
                    blockCommentEnd: "*#",
                    lineComment: "##",
                    fold: "velocity"
                };
            });
            
            CodeMirror.defineMIME("text/velocity", "velocity");
            
            });
            
        • verilog
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Verilog/SystemVerilog mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="verilog.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Verilog/SystemVerilog</a>
              </ul>
            </div>
            
            <article>
            <h2>SystemVerilog mode</h2>
            
            <div><textarea id="code" name="code">
            // Literals
            1'b0
            1'bx
            1'bz
            16'hDC78
            'hdeadbeef
            'b0011xxzz
            1234
            32'd5678
            3.4e6
            -128.7
            
            // Macro definition
            `define BUS_WIDTH = 8;
            
            // Module definition
            module block(
              input                   clk,
              input                   rst_n,
              input  [`BUS_WIDTH-1:0] data_in,
              output [`BUS_WIDTH-1:0] data_out
            );
              
              always @(posedge clk or negedge rst_n) begin
            
                if (~rst_n) begin
                  data_out <= 8'b0;
                end else begin
                  data_out <= data_in;
                end
                
                if (~rst_n)
                  data_out <= 8'b0;
                else
                  data_out <= data_in;
                
                if (~rst_n)
                  begin
                    data_out <= 8'b0;
                  end
                else
                  begin
                    data_out <= data_in;
                  end
            
              end
              
            endmodule
            
            // Class definition
            class test;
            
              /**
               * Sum two integers
               */
              function int sum(int a, int b);
                int result = a + b;
                string msg = $sformatf("%d + %d = %d", a, b, result);
                $display(msg);
                return result;
              endfunction
              
              task delay(int num_cycles);
                repeat(num_cycles) #1;
              endtask
              
            endclass
            
            </textarea></div>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                matchBrackets: true,
                mode: {
                  name: "verilog",
                  noIndentKeywords: ["package"]
                }
              });
            </script>
            
            <p>
            Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800).
            <h2>Configuration options:</h2>
              <ul>
                <li><strong>noIndentKeywords</strong> - List of keywords which should not cause identation to increase. E.g. ["package", "module"]. Default: None</li>
              </ul>
            </p>
            
            <p><strong>MIME types defined:</strong> <code>text/x-verilog</code> and <code>text/x-systemverilog</code>.</p>
            </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 4}, "verilog");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("binary_literals",
                 "[number 1'b0]",
                 "[number 1'b1]",
                 "[number 1'bx]",
                 "[number 1'bz]",
                 "[number 1'bX]",
                 "[number 1'bZ]",
                 "[number 1'B0]",
                 "[number 1'B1]",
                 "[number 1'Bx]",
                 "[number 1'Bz]",
                 "[number 1'BX]",
                 "[number 1'BZ]",
                 "[number 1'b0]",
                 "[number 1'b1]",
                 "[number 2'b01]",
                 "[number 2'bxz]",
                 "[number 2'b11]",
                 "[number 2'b10]",
                 "[number 2'b1Z]",
                 "[number 12'b0101_0101_0101]",
                 "[number 1'b 0]",
                 "[number 'b0101]"
              );
            
              MT("octal_literals",
                 "[number 3'o7]",
                 "[number 3'O7]",
                 "[number 3'so7]",
                 "[number 3'SO7]"
              );
            
              MT("decimal_literals",
                 "[number 0]",
                 "[number 1]",
                 "[number 7]",
                 "[number 123_456]",
                 "[number 'd33]",
                 "[number 8'd255]",
                 "[number 8'D255]",
                 "[number 8'sd255]",
                 "[number 8'SD255]",
                 "[number 32'd123]",
                 "[number 32 'd123]",
                 "[number 32 'd 123]"
              );
            
              MT("hex_literals",
                 "[number 4'h0]",
                 "[number 4'ha]",
                 "[number 4'hF]",
                 "[number 4'hx]",
                 "[number 4'hz]",
                 "[number 4'hX]",
                 "[number 4'hZ]",
                 "[number 32'hdc78]",
                 "[number 32'hDC78]",
                 "[number 32 'hDC78]",
                 "[number 32'h DC78]",
                 "[number 32 'h DC78]",
                 "[number 32'h44x7]",
                 "[number 32'hFFF?]"
              );
            
              MT("real_number_literals",
                 "[number 1.2]",
                 "[number 0.1]",
                 "[number 2394.26331]",
                 "[number 1.2E12]",
                 "[number 1.2e12]",
                 "[number 1.30e-2]",
                 "[number 0.1e-0]",
                 "[number 23E10]",
                 "[number 29E-2]",
                 "[number 236.123_763_e-12]"
              );
            
              MT("operators",
                 "[meta ^]"
              );
            
              MT("keywords",
                 "[keyword logic]",
                 "[keyword logic] [variable foo]",
                 "[keyword reg] [variable abc]"
              );
            
              MT("variables",
                 "[variable _leading_underscore]",
                 "[variable _if]",
                 "[number 12] [variable foo]",
                 "[variable foo] [number 14]"
              );
            
              MT("tick_defines",
                 "[def `FOO]",
                 "[def `foo]",
                 "[def `FOO_bar]"
              );
            
              MT("system_calls",
                 "[meta $display]",
                 "[meta $vpi_printf]"
              );
            
              MT("line_comment", "[comment // Hello world]");
            
              // Alignment tests
              MT("align_port_map_style1",
                 /**
                  * mod mod(.a(a),
                  *         .b(b)
                  *        );
                  */
                 "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],",
                 "        .[variable b][bracket (][variable b][bracket )]",
                 "       [bracket )];",
                 ""
              );
            
              MT("align_port_map_style2",
                 /**
                  * mod mod(
                  *     .a(a),
                  *     .b(b)
                  * );
                  */
                 "[variable mod] [variable mod][bracket (]",
                 "    .[variable a][bracket (][variable a][bracket )],",
                 "    .[variable b][bracket (][variable b][bracket )]",
                 "[bracket )];",
                 ""
              );
            
              // Indentation tests
              MT("indent_single_statement_if",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword break];",
                  ""
              );
            
              MT("no_indent_after_single_line_if",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword break];",
                  ""
              );
            
              MT("indent_after_if_begin_same_line",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end]",
                  ""
              );
            
              MT("indent_after_if_begin_next_line",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  ""
              );
            
              MT("indent_single_statement_if_else",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword break];",
                  "[keyword else]",
                  "    [keyword break];",
                  ""
              );
            
              MT("indent_if_else_begin_same_line",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end] [keyword else] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end]",
                  ""
              );
            
              MT("indent_if_else_begin_next_line",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  "[keyword else]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  ""
              );
            
              MT("indent_if_nested_without_begin",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword if] [bracket (][variable foo][bracket )]",
                  "        [keyword if] [bracket (][variable foo][bracket )]",
                  "            [keyword break];",
                  ""
              );
            
              MT("indent_case",
                  "[keyword case] [bracket (][variable state][bracket )]",
                  "    [variable FOO]:",
                  "        [keyword break];",
                  "    [variable BAR]:",
                  "        [keyword break];",
                  "[keyword endcase]",
                  ""
              );
            
              MT("unindent_after_end_with_preceding_text",
                  "[keyword begin]",
                  "    [keyword break]; [keyword end]",
                  ""
              );
            
              MT("export_function_one_line_does_not_indent",
                 "[keyword export] [string \"DPI-C\"] [keyword function] [variable helloFromSV];",
                 ""
              );
            
              MT("export_task_one_line_does_not_indent",
                 "[keyword export] [string \"DPI-C\"] [keyword task] [variable helloFromSV];",
                 ""
              );
            
              MT("export_function_two_lines_indents_properly",
                "[keyword export]",
                "    [string \"DPI-C\"] [keyword function] [variable helloFromSV];",
                ""
              );
            
              MT("export_task_two_lines_indents_properly",
                "[keyword export]",
                "    [string \"DPI-C\"] [keyword task] [variable helloFromSV];",
                ""
              );
            
              MT("import_function_one_line_does_not_indent",
                "[keyword import] [string \"DPI-C\"] [keyword function] [variable helloFromC];",
                ""
              );
            
              MT("import_task_one_line_does_not_indent",
                "[keyword import] [string \"DPI-C\"] [keyword task] [variable helloFromC];",
                ""
              );
            
              MT("import_package_single_line_does_not_indent",
                "[keyword import] [variable p]::[variable x];",
                "[keyword import] [variable p]::[variable y];",
                ""
              );
            
              MT("covergoup_with_function_indents_properly",
                "[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];",
                "    [variable c] : [keyword coverpoint] [variable c];",
                "[keyword endgroup]: [variable cg]",
                ""
              );
            
            })();
            
          • verilog.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("verilog", function(config, parserConfig) {
            
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  dontAlignCalls = parserConfig.dontAlignCalls,
                  noIndentKeywords = parserConfig.noIndentKeywords || [],
                  multiLineStrings = parserConfig.multiLineStrings,
                  hooks = parserConfig.hooks || {};
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              /**
               * Keywords from IEEE 1800-2012
               */
              var keywords = words(
                "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " +
                "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " +
                "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " +
                "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " +
                "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " +
                "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " +
                "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " +
                "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " +
                "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " +
                "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " +
                "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " +
                "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " +
                "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " +
                "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " +
                "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " +
                "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " +
                "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " +
                "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor");
            
              /** Operators from IEEE 1800-2012
                 unary_operator ::=
                   + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
                 binary_operator ::=
                   + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **
                   | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
                   | -> | <->
                 inc_or_dec_operator ::= ++ | --
                 unary_module_path_operator ::=
                   ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
                 binary_module_path_operator ::=
                   == | != | && | || | & | | | ^ | ^~ | ~^
              */
              var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/;
              var isBracketChar = /[\[\]{}()]/;
            
              var unsignedNumber = /\d[0-9_]*/;
              var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i;
              var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i;
              var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i;
              var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i;
              var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i;
            
              var closingBracketOrWord = /^((\w+)|[)}\]])/;
              var closingBracket = /[)}\]]/;
            
              var curPunc;
              var curKeyword;
            
              // Block openings which are closed by a matching keyword in the form of ("end" + keyword)
              // E.g. "task" => "endtask"
              var blockKeywords = words(
                "case checker class clocking config function generate interface module package" +
                "primitive program property specify sequence table task"
              );
            
              // Opening/closing pairs
              var openClose = {};
              for (var keyword in blockKeywords) {
                openClose[keyword] = "end" + keyword;
              }
              openClose["begin"] = "end";
              openClose["casex"] = "endcase";
              openClose["casez"] = "endcase";
              openClose["do"   ] = "while";
              openClose["fork" ] = "join;join_any;join_none";
              openClose["covergroup"] = "endgroup";
            
              for (var i in noIndentKeywords) {
                var keyword = noIndentKeywords[i];
                if (openClose[keyword]) {
                  openClose[keyword] = undefined;
                }
              }
            
              // Keywords which open statements that are ended with a semi-colon
              var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while");
            
              function tokenBase(stream, state) {
                var ch = stream.peek(), style;
                if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style;
                if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false)
                  return style;
            
                if (/[,;:\.]/.test(ch)) {
                  curPunc = stream.next();
                  return null;
                }
                if (isBracketChar.test(ch)) {
                  curPunc = stream.next();
                  return "bracket";
                }
                // Macros (tick-defines)
                if (ch == '`') {
                  stream.next();
                  if (stream.eatWhile(/[\w\$_]/)) {
                    return "def";
                  } else {
                    return null;
                  }
                }
                // System calls
                if (ch == '$') {
                  stream.next();
                  if (stream.eatWhile(/[\w\$_]/)) {
                    return "meta";
                  } else {
                    return null;
                  }
                }
                // Time literals
                if (ch == '#') {
                  stream.next();
                  stream.eatWhile(/[\d_.]/);
                  return "def";
                }
                // Strings
                if (ch == '"') {
                  stream.next();
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                // Comments
                if (ch == "/") {
                  stream.next();
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  stream.backUp(1);
                }
            
                // Numeric literals
                if (stream.match(realLiteral) ||
                    stream.match(decimalLiteral) ||
                    stream.match(binaryLiteral) ||
                    stream.match(octLiteral) ||
                    stream.match(hexLiteral) ||
                    stream.match(unsignedNumber) ||
                    stream.match(realLiteral)) {
                  return "number";
                }
            
                // Operators
                if (stream.eatWhile(isOperatorChar)) {
                  return "meta";
                }
            
                // Keywords / plain variables
                if (stream.eatWhile(/[\w\$_]/)) {
                  var cur = stream.current();
                  if (keywords[cur]) {
                    if (openClose[cur]) {
                      curPunc = "newblock";
                    }
                    if (statementKeywords[cur]) {
                      curPunc = "newstatement";
                    }
                    curKeyword = cur;
                    return "keyword";
                  }
                  return "variable";
                }
            
                stream.next();
                return null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                var c = new Context(indent, col, type, null, state.context);
                return state.context = c;
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}") {
                  state.indented = state.context.indented;
                }
                return state.context = state.context.prev;
              }
            
              function isClosing(text, contextClosing) {
                if (text == contextClosing) {
                  return true;
                } else {
                  // contextClosing may be mulitple keywords separated by ;
                  var closingKeywords = contextClosing.split(";");
                  for (var i in closingKeywords) {
                    if (text == closingKeywords[i]) {
                      return true;
                    }
                  }
                  return false;
                }
              }
            
              function buildElectricInputRegEx() {
                // Reindentation should occur on any bracket char: {}()[]
                // or on a match of any of the block closing keywords, at
                // the end of a line
                var allClosings = [];
                for (var i in openClose) {
                  if (openClose[i]) {
                    var closings = openClose[i].split(";");
                    for (var j in closings) {
                      allClosings.push(closings[j]);
                    }
                  }
                }
                var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$");
                return re;
              }
            
              // Interface
              return {
            
                // Regex to force current line to reindent
                electricInput: buildElectricInputRegEx(),
            
                startState: function(basecolumn) {
                  var state = {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                  if (hooks.startState) hooks.startState(state);
                  return state;
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (hooks.token) hooks.token(stream, state);
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  curKeyword = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta" || style == "variable") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if (curPunc == ctx.type) {
                    popContext(state);
                  } else if ((curPunc == ";" && ctx.type == "statement") ||
                           (ctx.type && isClosing(curKeyword, ctx.type))) {
                    ctx = popContext(state);
                    while (ctx && ctx.type == "statement") ctx = popContext(state);
                  } else if (curPunc == "{") {
                    pushContext(state, stream.column(), "}");
                  } else if (curPunc == "[") {
                    pushContext(state, stream.column(), "]");
                  } else if (curPunc == "(") {
                    pushContext(state, stream.column(), ")");
                  } else if (ctx && ctx.type == "endcase" && curPunc == ":") {
                    pushContext(state, stream.column(), "statement");
                  } else if (curPunc == "newstatement") {
                    pushContext(state, stream.column(), "statement");
                  } else if (curPunc == "newblock") {
                    if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) {
                      // The 'function' keyword can appear in some other contexts where it actually does not
                      // indicate a function (import/export DPI and covergroup definitions).
                      // Do nothing in this case
                    } else if (curKeyword == "task" && ctx && ctx.type == "statement") {
                      // Same thing for task
                    } else {
                      var close = openClose[curKeyword];
                      pushContext(state, stream.column(), close);
                    }
                  }
            
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  if (hooks.indent) {
                    var fromHook = hooks.indent(state);
                    if (fromHook >= 0) return fromHook;
                  }
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = false;
                  var possibleClosing = textAfter.match(closingBracketOrWord);
                  if (possibleClosing)
                    closing = isClosing(possibleClosing[0], ctx.type);
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);
                  else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
              CodeMirror.defineMIME("text/x-verilog", {
                name: "verilog"
              });
            
              CodeMirror.defineMIME("text/x-systemverilog", {
                name: "verilog"
              });
            
              // SVXVerilog mode
            
              var svxchScopePrefixes = {
                ">": "property", "->": "property", "-": "hr", "|": "link", "?$": "qualifier", "?*": "qualifier",
                "@-": "variable-3", "@": "variable-3", "?": "qualifier"
              };
            
              function svxGenIndent(stream, state) {
                var svxindentUnit = 2;
                var rtnIndent = -1, indentUnitRq = 0, curIndent = stream.indentation();
                switch (state.svxCurCtlFlowChar) {
                case "\\":
                  curIndent = 0;
                  break;
                case "|":
                  if (state.svxPrevPrevCtlFlowChar == "@") {
                    indentUnitRq = -2; //-2 new pipe rq after cur pipe
                    break;
                  }
                  if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                case "M":  // m4
                  if (state.svxPrevPrevCtlFlowChar == "@") {
                    indentUnitRq = -2; //-2 new inst rq after  pipe
                    break;
                  }
                  if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                case "@":
                  if (state.svxPrevCtlFlowChar == "S")
                    indentUnitRq = -1; // new pipe stage after stmts
                  if (state.svxPrevCtlFlowChar == "|")
                    indentUnitRq = 1; // 1st pipe stage
                  break;
                case "S":
                  if (state.svxPrevCtlFlowChar == "@")
                    indentUnitRq = 1; // flow in pipe stage
                  if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                }
                var statementIndentUnit = svxindentUnit;
                rtnIndent = curIndent + (indentUnitRq*statementIndentUnit);
                return rtnIndent >= 0 ? rtnIndent : curIndent;
              }
            
              CodeMirror.defineMIME("text/x-svx", {
                name: "verilog",
                hooks: {
                  "\\": function(stream, state) {
                    var vxIndent = 0, style = false;
                    var curPunc  = stream.string;
                    if ((stream.sol()) && (/\\SV/.test(stream.string))) {
                      curPunc = (/\\SVX_version/.test(stream.string))
                        ? "\\SVX_version" : stream.string;
                      stream.skipToEnd();
                      if (curPunc == "\\SV" && state.vxCodeActive) {state.vxCodeActive = false;};
                      if ((/\\SVX/.test(curPunc) && !state.vxCodeActive)
                        || (curPunc=="\\SVX_version" && state.vxCodeActive)) {state.vxCodeActive = true;};
                      style = "keyword";
                      state.svxCurCtlFlowChar  = state.svxPrevPrevCtlFlowChar
                        = state.svxPrevCtlFlowChar = "";
                      if (state.vxCodeActive == true) {
                        state.svxCurCtlFlowChar  = "\\";
                        vxIndent = svxGenIndent(stream, state);
                      }
                      state.vxIndentRq = vxIndent;
                    }
                    return style;
                  },
                  tokenBase: function(stream, state) {
                    var vxIndent = 0, style = false;
                    var svxisOperatorChar = /[\[\]=:]/;
                    var svxkpScopePrefixs = {
                      "**":"variable-2", "*":"variable-2", "$$":"variable", "$":"variable",
                      "^^":"attribute", "^":"attribute"};
                    var ch = stream.peek();
                    var vxCurCtlFlowCharValueAtStart = state.svxCurCtlFlowChar;
                    if (state.vxCodeActive == true) {
                      if (/[\[\]{}\(\);\:]/.test(ch)) {
                        // bypass nesting and 1 char punc
                        style = "meta";
                        stream.next();
                      } else if (ch == "/") {
                        stream.next();
                        if (stream.eat("/")) {
                          stream.skipToEnd();
                          style = "comment";
                          state.svxCurCtlFlowChar = "S";
                        } else {
                          stream.backUp(1);
                        }
                      } else if (ch == "@") {
                        // pipeline stage
                        style = svxchScopePrefixes[ch];
                        state.svxCurCtlFlowChar = "@";
                        stream.next();
                        stream.eatWhile(/[\w\$_]/);
                      } else if (stream.match(/\b[mM]4+/, true)) { // match: function(pattern, consume, caseInsensitive)
                        // m4 pre proc
                        stream.skipTo("(");
                        style = "def";
                        state.svxCurCtlFlowChar = "M";
                      } else if (ch == "!" && stream.sol()) {
                        // v stmt in svx region
                        // state.svxCurCtlFlowChar  = "S";
                        style = "comment";
                        stream.next();
                      } else if (svxisOperatorChar.test(ch)) {
                        // operators
                        stream.eatWhile(svxisOperatorChar);
                        style = "operator";
                      } else if (ch == "#") {
                        // phy hier
                        state.svxCurCtlFlowChar  = (state.svxCurCtlFlowChar == "")
                          ? ch : state.svxCurCtlFlowChar;
                        stream.next();
                        stream.eatWhile(/[+-]\d/);
                        style = "tag";
                      } else if (svxkpScopePrefixs.propertyIsEnumerable(ch)) {
                        // special SVX operators
                        style = svxkpScopePrefixs[ch];
                        state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? "S" : state.svxCurCtlFlowChar;  // stmt
                        stream.next();
                        stream.match(/[a-zA-Z_0-9]+/);
                      } else if (style = svxchScopePrefixes[ch] || false) {
                        // special SVX operators
                        state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? ch : state.svxCurCtlFlowChar;
                        stream.next();
                        stream.match(/[a-zA-Z_0-9]+/);
                      }
                      if (state.svxCurCtlFlowChar != vxCurCtlFlowCharValueAtStart) { // flow change
                        vxIndent = svxGenIndent(stream, state);
                        state.vxIndentRq = vxIndent;
                      }
                    }
                    return style;
                  },
                  token: function(stream, state) {
                    if (state.vxCodeActive == true && stream.sol() && state.svxCurCtlFlowChar != "") {
                      state.svxPrevPrevCtlFlowChar = state.svxPrevCtlFlowChar;
                      state.svxPrevCtlFlowChar = state.svxCurCtlFlowChar;
                      state.svxCurCtlFlowChar = "";
                    }
                  },
                  indent: function(state) {
                    return (state.vxCodeActive == true) ? state.vxIndentRq : -1;
                  },
                  startState: function(state) {
                    state.svxCurCtlFlowChar = "";
                    state.svxPrevCtlFlowChar = "";
                    state.svxPrevPrevCtlFlowChar = "";
                    state.vxCodeActive = true;
                    state.vxIndentRq = 0;
                  }
                }
              });
            });
            
        • xml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: XML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="xml.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">XML</a>
              </ul>
            </div>
            
            <article>
            <h2>XML mode</h2>
            <form><textarea id="code" name="code">
            &lt;html style="color: green"&gt;
              &lt;!-- this is a comment --&gt;
              &lt;head&gt;
                &lt;title&gt;HTML Example&lt;/title&gt;
              &lt;/head&gt;
              &lt;body&gt;
                The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
                I mean&amp;quot;&lt;/em&gt;... but might not match your style.
              &lt;/body&gt;
            &lt;/html&gt;
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/html",
                    lineNumbers: true
                  });
                </script>
                <p>The XML mode supports two configuration parameters:</p>
                <dl>
                  <dt><code>htmlMode (boolean)</code></dt>
                  <dd>This switches the mode to parse HTML instead of XML. This
                  means attributes do not have to be quoted, and some elements
                  (such as <code>br</code>) do not require a closing tag.</dd>
                  <dt><code>alignCDATA (boolean)</code></dt>
                  <dd>Setting this to true will force the opening tag of CDATA
                  blocks to not be indented.</dd>
                </dl>
            
                <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }
            
              MT("matching",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  text",
                 "  [tag&bracket <][tag inner][tag&bracket />]",
                 "[tag&bracket </][tag top][tag&bracket >]");
            
              MT("nonmatching",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  [tag&bracket <][tag inner][tag&bracket />]",
                 "  [tag&bracket </][tag&error tip][tag&bracket&error >]");
            
              MT("doctype",
                 "[meta <!doctype foobar>]",
                 "[tag&bracket <][tag top][tag&bracket />]");
            
              MT("cdata",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  [atom <![CDATA[foo]",
                 "[atom barbazguh]]]]>]",
                 "[tag&bracket </][tag top][tag&bracket >]");
            
              // HTML tests
              mode = CodeMirror.getMode({indentUnit: 2}, "text/html");
            
              MT("selfclose",
                 "[tag&bracket <][tag html][tag&bracket >]",
                 "  [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]",
                 "[tag&bracket </][tag html][tag&bracket >]");
            
              MT("list",
                 "[tag&bracket <][tag ol][tag&bracket >]",
                 "  [tag&bracket <][tag li][tag&bracket >]one",
                 "  [tag&bracket <][tag li][tag&bracket >]two",
                 "[tag&bracket </][tag ol][tag&bracket >]");
            
              MT("valueless",
                 "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]");
            
              MT("pThenArticle",
                 "[tag&bracket <][tag p][tag&bracket >]",
                 "  foo",
                 "[tag&bracket <][tag article][tag&bracket >]bar");
            
            })();
            
          • xml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("xml", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
              var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
              var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
              if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
            
              var Kludges = parserConfig.htmlMode ? {
                autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
                                  'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
                                  'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
                                  'track': true, 'wbr': true, 'menuitem': true},
                implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
                                   'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
                                   'th': true, 'tr': true},
                contextGrabbers: {
                  'dd': {'dd': true, 'dt': true},
                  'dt': {'dd': true, 'dt': true},
                  'li': {'li': true},
                  'option': {'option': true, 'optgroup': true},
                  'optgroup': {'optgroup': true},
                  'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
                        'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
                        'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
                        'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
                        'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
                  'rp': {'rp': true, 'rt': true},
                  'rt': {'rp': true, 'rt': true},
                  'tbody': {'tbody': true, 'tfoot': true},
                  'td': {'td': true, 'th': true},
                  'tfoot': {'tbody': true},
                  'th': {'td': true, 'th': true},
                  'thead': {'tbody': true, 'tfoot': true},
                  'tr': {'tr': true}
                },
                doNotIndent: {"pre": true},
                allowUnquoted: true,
                allowMissing: true,
                caseFold: true
              } : {
                autoSelfClosers: {},
                implicitlyClosed: {},
                contextGrabbers: {},
                doNotIndent: {},
                allowUnquoted: false,
                allowMissing: false,
                caseFold: false
              };
              var alignCDATA = parserConfig.alignCDATA;
            
              // Return variables for tokenizers
              var type, setStyle;
            
              function inText(stream, state) {
                function chain(parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
            
                var ch = stream.next();
                if (ch == "<") {
                  if (stream.eat("!")) {
                    if (stream.eat("[")) {
                      if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
                      else return null;
                    } else if (stream.match("--")) {
                      return chain(inBlock("comment", "-->"));
                    } else if (stream.match("DOCTYPE", true, true)) {
                      stream.eatWhile(/[\w\._\-]/);
                      return chain(doctype(1));
                    } else {
                      return null;
                    }
                  } else if (stream.eat("?")) {
                    stream.eatWhile(/[\w\._\-]/);
                    state.tokenize = inBlock("meta", "?>");
                    return "meta";
                  } else {
                    type = stream.eat("/") ? "closeTag" : "openTag";
                    state.tokenize = inTag;
                    return "tag bracket";
                  }
                } else if (ch == "&") {
                  var ok;
                  if (stream.eat("#")) {
                    if (stream.eat("x")) {
                      ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
                    } else {
                      ok = stream.eatWhile(/[\d]/) && stream.eat(";");
                    }
                  } else {
                    ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
                  }
                  return ok ? "atom" : "error";
                } else {
                  stream.eatWhile(/[^&<]/);
                  return null;
                }
              }
            
              function inTag(stream, state) {
                var ch = stream.next();
                if (ch == ">" || (ch == "/" && stream.eat(">"))) {
                  state.tokenize = inText;
                  type = ch == ">" ? "endTag" : "selfcloseTag";
                  return "tag bracket";
                } else if (ch == "=") {
                  type = "equals";
                  return null;
                } else if (ch == "<") {
                  state.tokenize = inText;
                  state.state = baseState;
                  state.tagName = state.tagStart = null;
                  var next = state.tokenize(stream, state);
                  return next ? next + " tag error" : "tag error";
                } else if (/[\'\"]/.test(ch)) {
                  state.tokenize = inAttribute(ch);
                  state.stringStartCol = stream.column();
                  return state.tokenize(stream, state);
                } else {
                  stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
                  return "word";
                }
              }
            
              function inAttribute(quote) {
                var closure = function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.next() == quote) {
                      state.tokenize = inTag;
                      break;
                    }
                  }
                  return "string";
                };
                closure.isInAttribute = true;
                return closure;
              }
            
              function inBlock(style, terminator) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = inText;
                      break;
                    }
                    stream.next();
                  }
                  return style;
                };
              }
              function doctype(depth) {
                return function(stream, state) {
                  var ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == "<") {
                      state.tokenize = doctype(depth + 1);
                      return state.tokenize(stream, state);
                    } else if (ch == ">") {
                      if (depth == 1) {
                        state.tokenize = inText;
                        break;
                      } else {
                        state.tokenize = doctype(depth - 1);
                        return state.tokenize(stream, state);
                      }
                    }
                  }
                  return "meta";
                };
              }
            
              function Context(state, tagName, startOfLine) {
                this.prev = state.context;
                this.tagName = tagName;
                this.indent = state.indented;
                this.startOfLine = startOfLine;
                if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
                  this.noIndent = true;
              }
              function popContext(state) {
                if (state.context) state.context = state.context.prev;
              }
              function maybePopContext(state, nextTagName) {
                var parentTagName;
                while (true) {
                  if (!state.context) {
                    return;
                  }
                  parentTagName = state.context.tagName;
                  if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
                      !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
                    return;
                  }
                  popContext(state);
                }
              }
            
              function baseState(type, stream, state) {
                if (type == "openTag") {
                  state.tagStart = stream.column();
                  return tagNameState;
                } else if (type == "closeTag") {
                  return closeTagNameState;
                } else {
                  return baseState;
                }
              }
              function tagNameState(type, stream, state) {
                if (type == "word") {
                  state.tagName = stream.current();
                  setStyle = "tag";
                  return attrState;
                } else {
                  setStyle = "error";
                  return tagNameState;
                }
              }
              function closeTagNameState(type, stream, state) {
                if (type == "word") {
                  var tagName = stream.current();
                  if (state.context && state.context.tagName != tagName &&
                      Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
                    popContext(state);
                  if (state.context && state.context.tagName == tagName) {
                    setStyle = "tag";
                    return closeState;
                  } else {
                    setStyle = "tag error";
                    return closeStateErr;
                  }
                } else {
                  setStyle = "error";
                  return closeStateErr;
                }
              }
            
              function closeState(type, _stream, state) {
                if (type != "endTag") {
                  setStyle = "error";
                  return closeState;
                }
                popContext(state);
                return baseState;
              }
              function closeStateErr(type, stream, state) {
                setStyle = "error";
                return closeState(type, stream, state);
              }
            
              function attrState(type, _stream, state) {
                if (type == "word") {
                  setStyle = "attribute";
                  return attrEqState;
                } else if (type == "endTag" || type == "selfcloseTag") {
                  var tagName = state.tagName, tagStart = state.tagStart;
                  state.tagName = state.tagStart = null;
                  if (type == "selfcloseTag" ||
                      Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
                    maybePopContext(state, tagName);
                  } else {
                    maybePopContext(state, tagName);
                    state.context = new Context(state, tagName, tagStart == state.indented);
                  }
                  return baseState;
                }
                setStyle = "error";
                return attrState;
              }
              function attrEqState(type, stream, state) {
                if (type == "equals") return attrValueState;
                if (!Kludges.allowMissing) setStyle = "error";
                return attrState(type, stream, state);
              }
              function attrValueState(type, stream, state) {
                if (type == "string") return attrContinuedState;
                if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
                setStyle = "error";
                return attrState(type, stream, state);
              }
              function attrContinuedState(type, stream, state) {
                if (type == "string") return attrContinuedState;
                return attrState(type, stream, state);
              }
            
              return {
                startState: function() {
                  return {tokenize: inText,
                          state: baseState,
                          indented: 0,
                          tagName: null, tagStart: null,
                          context: null};
                },
            
                token: function(stream, state) {
                  if (!state.tagName && stream.sol())
                    state.indented = stream.indentation();
            
                  if (stream.eatSpace()) return null;
                  type = null;
                  var style = state.tokenize(stream, state);
                  if ((style || type) && style != "comment") {
                    setStyle = null;
                    state.state = state.state(type || style, stream, state);
                    if (setStyle)
                      style = setStyle == "error" ? style + " error" : setStyle;
                  }
                  return style;
                },
            
                indent: function(state, textAfter, fullLine) {
                  var context = state.context;
                  // Indent multi-line strings (e.g. css).
                  if (state.tokenize.isInAttribute) {
                    if (state.tagStart == state.indented)
                      return state.stringStartCol + 1;
                    else
                      return state.indented + indentUnit;
                  }
                  if (context && context.noIndent) return CodeMirror.Pass;
                  if (state.tokenize != inTag && state.tokenize != inText)
                    return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
                  // Indent the starts of attribute names.
                  if (state.tagName) {
                    if (multilineTagIndentPastTag)
                      return state.tagStart + state.tagName.length + 2;
                    else
                      return state.tagStart + indentUnit * multilineTagIndentFactor;
                  }
                  if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
                  var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
                  if (tagAfter && tagAfter[1]) { // Closing tag spotted
                    while (context) {
                      if (context.tagName == tagAfter[2]) {
                        context = context.prev;
                        break;
                      } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
                        context = context.prev;
                      } else {
                        break;
                      }
                    }
                  } else if (tagAfter) { // Opening tag spotted
                    while (context) {
                      var grabbers = Kludges.contextGrabbers[context.tagName];
                      if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
                        context = context.prev;
                      else
                        break;
                    }
                  }
                  while (context && !context.startOfLine)
                    context = context.prev;
                  if (context) return context.indent + indentUnit;
                  else return 0;
                },
            
                electricInput: /<\/[\s\w:]+>$/,
                blockCommentStart: "<!--",
                blockCommentEnd: "-->",
            
                configuration: parserConfig.htmlMode ? "html" : "xml",
                helperType: parserConfig.htmlMode ? "html" : "xml"
              };
            });
            
            CodeMirror.defineMIME("text/xml", "xml");
            CodeMirror.defineMIME("application/xml", "xml");
            if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
              CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
            
            });
            
        • xquery
          • index.html
            <!doctype html>
            
            <title>CodeMirror: XQuery mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/xq-dark.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="xquery.js"></script>
            <style type="text/css">
            	.CodeMirror {
            	  border-top: 1px solid black; border-bottom: 1px solid black;
            	  height:400px;
            	}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">XQuery</a>
              </ul>
            </div>
            
            <article>
            <h2>XQuery mode</h2>
             
             
            <div class="cm-s-default"> 
            	<textarea id="code" name="code"> 
            xquery version &quot;1.0-ml&quot;;
            (: this is
             : a 
               "comment" :)
            let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;
            let $joe:=1
            return element element {
            	attribute attribute { 1 },
            	element test { &#39;a&#39; }, 
            	attribute foo { &quot;bar&quot; },
            	fn:doc()[ foo/@bar eq $let ],
            	//x }    
             
            (: a more 'evil' test :)
            (: Modified Blakeley example (: with nested comment :) ... :)
            declare private function local:declare() {()};
            declare private function local:private() {()};
            declare private function local:function() {()};
            declare private function local:local() {()};
            let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;
            return element element {
            	attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },
            	attribute fn:doc { &quot;bar&quot; castable as xs:string },
            	element text { text { &quot;text&quot; } },
            	fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],
            	//fn:doc
            }
            
            
            
            xquery version &quot;1.0-ml&quot;;
            
            (: Copyright 2006-2010 Mark Logic Corporation. :)
            
            (:
             : Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
             : you may not use this file except in compliance with the License.
             : You may obtain a copy of the License at
             :
             :     http://www.apache.org/licenses/LICENSE-2.0
             :
             : Unless required by applicable law or agreed to in writing, software
             : distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             : See the License for the specific language governing permissions and
             : limitations under the License.
             :)
            
            module namespace json = &quot;http://marklogic.com/json&quot;;
            declare default function namespace &quot;http://www.w3.org/2005/xpath-functions&quot;;
            
            (: Need to backslash escape any double quotes, backslashes, and newlines :)
            declare function json:escape($s as xs:string) as xs:string {
              let $s := replace($s, &quot;\\&quot;, &quot;\\\\&quot;)
              let $s := replace($s, &quot;&quot;&quot;&quot;, &quot;\\&quot;&quot;&quot;)
              let $s := replace($s, codepoints-to-string((13, 10)), &quot;\\n&quot;)
              let $s := replace($s, codepoints-to-string(13), &quot;\\n&quot;)
              let $s := replace($s, codepoints-to-string(10), &quot;\\n&quot;)
              return $s
            };
            
            declare function json:atomize($x as element()) as xs:string {
              if (count($x/node()) = 0) then 'null'
              else if ($x/@type = &quot;number&quot;) then
                let $castable := $x castable as xs:float or
                                 $x castable as xs:double or
                                 $x castable as xs:decimal
                return
                if ($castable) then xs:string($x)
                else error(concat(&quot;Not a number: &quot;, xdmp:describe($x)))
              else if ($x/@type = &quot;boolean&quot;) then
                let $castable := $x castable as xs:boolean
                return
                if ($castable) then xs:string(xs:boolean($x))
                else error(concat(&quot;Not a boolean: &quot;, xdmp:describe($x)))
              else concat('&quot;', json:escape($x), '&quot;')
            };
            
            (: Print the thing that comes after the colon :)
            declare function json:print-value($x as element()) as xs:string {
              if (count($x/*) = 0) then
                json:atomize($x)
              else if ($x/@quote = &quot;true&quot;) then
                concat('&quot;', json:escape(xdmp:quote($x/node())), '&quot;')
              else
                string-join(('{',
                  string-join(for $i in $x/* return json:print-name-value($i), &quot;,&quot;),
                '}'), &quot;&quot;)
            };
            
            (: Print the name and value both :)
            declare function json:print-name-value($x as element()) as xs:string? {
              let $name := name($x)
              let $first-in-array :=
                count($x/preceding-sibling::*[name(.) = $name]) = 0 and
                (count($x/following-sibling::*[name(.) = $name]) &gt; 0 or $x/@array = &quot;true&quot;)
              let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) &gt; 0
              return
            
              if ($later-in-array) then
                ()  (: I was handled previously :)
              else if ($first-in-array) then
                string-join(('&quot;', json:escape($name), '&quot;:[',
                  string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), &quot;,&quot;),
                ']'), &quot;&quot;)
               else
                 string-join(('&quot;', json:escape($name), '&quot;:', json:print-value($x)), &quot;&quot;)
            };
            
            (:~
              Transforms an XML element into a JSON string representation.  See http://json.org.
              &lt;p/&gt;
              Sample usage:
              &lt;pre&gt;
                xquery version &quot;1.0-ml&quot;;
                import module namespace json=&quot;http://marklogic.com/json&quot; at &quot;json.xqy&quot;;
                json:serialize(&amp;lt;foo&amp;gt;&amp;lt;bar&amp;gt;kid&amp;lt;/bar&amp;gt;&amp;lt;/foo&amp;gt;)
              &lt;/pre&gt;
              Sample transformations:
              &lt;pre&gt;
              &amp;lt;e/&amp;gt; becomes {&quot;e&quot;:null}
              &amp;lt;e&amp;gt;text&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;text&quot;}
              &amp;lt;e&amp;gt;quote &quot; escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;quote \&quot; escaping&quot;}
              &amp;lt;e&amp;gt;backslash \ escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;backslash \\ escaping&quot;}
              &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;text2&amp;lt;/b&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:&quot;text1&quot;,&quot;b&quot;:&quot;text2&quot;}}
              &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;a&amp;gt;text2&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;,&quot;text2&quot;]}}
              &amp;lt;e&amp;gt;&amp;lt;a array=&quot;true&quot;&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;]}}
              &amp;lt;e&amp;gt;&amp;lt;a type=&quot;boolean&quot;&amp;gt;false&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:false}}
              &amp;lt;e&amp;gt;&amp;lt;a type=&quot;number&quot;&amp;gt;123.5&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:123.5}}
              &amp;lt;e quote=&quot;true&quot;&amp;gt;&amp;lt;div attrib=&quot;value&quot;/&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;&amp;lt;div attrib=\&quot;value\&quot;/&amp;gt;&quot;}
              &lt;/pre&gt;
              &lt;p/&gt;
              Namespace URIs are ignored.  Namespace prefixes are included in the JSON name.
              &lt;p/&gt;
              Attributes are ignored, except for the special attribute @array=&quot;true&quot; that
              indicates the JSON serialization should write the node, even if single, as an
              array, and the attribute @type that can be set to &quot;boolean&quot; or &quot;number&quot; to
              dictate the value should be written as that type (unquoted).  There's also
              an @quote attribute that when set to true writes the inner content as text
              rather than as structured JSON, useful for sending some XHTML over the
              wire.
              &lt;p/&gt;
              Text nodes within mixed content are ignored.
            
              @param $x Element node to convert
              @return String holding JSON serialized representation of $x
            
              @author Jason Hunter
              @version 1.0.1
              
              Ported to xquery 1.0-ml; double escaped backslashes in json:escape
            :)
            declare function json:serialize($x as element())  as xs:string {
              string-join(('{', json:print-name-value($x), '}'), &quot;&quot;)
            };
              </textarea> 
            </div> 
             
                <script> 
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "xq-dark"
                  });
                </script> 
             
                <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p> 
             
                <p>Development of the CodeMirror XQuery mode was sponsored by 
                  <a href="http://marklogic.com">MarkLogic</a> and developed by 
                  <a href="https://twitter.com/mbrevoort">Mike Brevoort</a>.
                </p>
             
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Don't take these too seriously -- the expected results appear to be
            // based on the results of actual runs without any serious manual
            // verification. If a change you made causes them to fail, the test is
            // as likely to wrong as the code.
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "xquery");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("eviltest",
                 "[keyword xquery] [keyword version] [variable &quot;1][keyword .][atom 0][keyword -][variable ml&quot;][def&variable ;]      [comment (: this is       : a          \"comment\" :)]",
                 "      [keyword let] [variable $let] [keyword :=] [variable &lt;x] [variable attr][keyword =][variable &quot;value&quot;&gt;&quot;test&quot;&lt;func&gt][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable &lt;][keyword /][variable func&gt;&lt;][keyword /][variable x&gt;]",
                 "      [keyword let] [variable $joe][keyword :=][atom 1]",
                 "      [keyword return] [keyword element] [variable element] {",
                 "          [keyword attribute] [variable attribute] { [atom 1] },",
                 "          [keyword element] [variable test] { [variable &#39;a&#39;] },           [keyword attribute] [variable foo] { [variable &quot;bar&quot;] },",
                 "          [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],",
                 "          [keyword //][variable x] }                 [comment (: a more 'evil' test :)]",
                 "      [comment (: Modified Blakeley example (: with nested comment :) ... :)]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]",
                 "      [keyword let] [variable $let] [keyword :=] [variable &lt;let&gt;let] [variable $let] [keyword :=] [variable &quot;let&quot;&lt;][keyword /let][variable &gt;]",
                 "      [keyword return] [keyword element] [variable element] {",
                 "          [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },",
                 "          [keyword attribute] [variable fn:doc] { [variable &quot;bar&quot;] [variable castable] [keyword as] [atom xs:string] },",
                 "          [keyword element] [variable text] { [keyword text] { [variable &quot;text&quot;] } },",
                 "          [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],",
                 "          [keyword //][variable fn:doc]",
                 "      }");
            
              MT("testEmptySequenceKeyword",
                 "[string \"foo\"] [keyword instance] [keyword of] [keyword empty-sequence]()");
            
              MT("testMultiAttr",
                 "[tag <p ][attribute a1]=[string \"foo\"] [attribute a2]=[string \"bar\"][tag >][variable hello] [variable world][tag </p>]");
            
              MT("test namespaced variable",
                 "[keyword declare] [keyword namespace] [variable e] [keyword =] [string \"http://example.com/ANamespace\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]");
            
              MT("test EQName variable",
                 "[keyword declare] [keyword variable] [variable $\"http://www.example.com/ns/my\":var] [keyword :=] [atom 12][variable ;]",
                 "[tag <out>]{[variable $\"http://www.example.com/ns/my\":var]}[tag </out>]");
            
              MT("test EQName function",
                 "[keyword declare] [keyword function] [def&variable \"http://www.example.com/ns/my\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
                 "   [variable $a] [keyword +] [atom 2]",
                 "}[variable ;]",
                 "[tag <out>]{[def&variable \"http://www.example.com/ns/my\":fn]([atom 12])}[tag </out>]");
            
              MT("test EQName function with single quotes",
                 "[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
                 "   [variable $a] [keyword +] [atom 2]",
                 "}[variable ;]",
                 "[tag <out>]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag </out>]");
            
              MT("testProcessingInstructions",
                 "[def&variable data]([comment&meta <?target content?>]) [keyword instance] [keyword of] [atom xs:string]");
            
              MT("testQuoteEscapeDouble",
                 "[keyword let] [variable $rootfolder] [keyword :=] [string \"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"]",
                 "[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \"keys\\\"])");
            })();
            
          • xquery.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("xquery", function() {
            
              // The keywords object is set to the result of this self executing
              // function. Each keyword is a property of the keywords object whose
              // value is {type: atype, style: astyle}
              var keywords = function(){
                // conveinence functions used to build keywords object
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a")
                  , B = kw("keyword b")
                  , C = kw("keyword c")
                  , operator = kw("operator")
                  , atom = {type: "atom", style: "atom"}
                  , punctuation = {type: "punctuation", style: null}
                  , qualifier = {type: "axis_specifier", style: "qualifier"};
            
                // kwObj is what is return from this function at the end
                var kwObj = {
                  'if': A, 'switch': A, 'while': A, 'for': A,
                  'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,
                  'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C,
                  'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,
                  ',': punctuation,
                  'null': atom, 'fn:false()': atom, 'fn:true()': atom
                };
            
                // a list of 'basic' keywords. For each add a property to kwObj with the value of
                // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"}
                var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',
                'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',
                'descending','document','document-node','element','else','eq','every','except','external','following',
                'following-sibling','follows','for','function','if','import','in','instance','intersect','item',
                'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',
                'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',
                'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',
                'xquery', 'empty-sequence'];
                for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i]);};
            
                // a list of types. For each add a property to kwObj with the value of
                // {type: "atom", style: "atom"}
                var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime',
                'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary',
                'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];
                for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};
            
                // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"}
                var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];
                for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};
            
                // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"}
                var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::",
                "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"];
                for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };
            
                return kwObj;
              }();
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
            
              function ret(tp, style, cont) {
                type = tp; content = cont;
                return style;
              }
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              // the primary mode tokenizer
              function tokenBase(stream, state) {
                var ch = stream.next(),
                    mightBeFunction = false,
                    isEQName = isEQNameAhead(stream);
            
                // an XML tag (if not in some sub, chained tokenizer)
                if (ch == "<") {
                  if(stream.match("!--", true))
                    return chain(stream, state, tokenXMLComment);
            
                  if(stream.match("![CDATA", false)) {
                    state.tokenize = tokenCDATA;
                    return ret("tag", "tag");
                  }
            
                  if(stream.match("?", false)) {
                    return chain(stream, state, tokenPreProcessing);
                  }
            
                  var isclose = stream.eat("/");
                  stream.eatSpace();
                  var tagName = "", c;
                  while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
            
                  return chain(stream, state, tokenTag(tagName, isclose));
                }
                // start code block
                else if(ch == "{") {
                  pushStateStack(state,{ type: "codeblock"});
                  return ret("", null);
                }
                // end code block
                else if(ch == "}") {
                  popStateStack(state);
                  return ret("", null);
                }
                // if we're in an XML block
                else if(isInXmlBlock(state)) {
                  if(ch == ">")
                    return ret("tag", "tag");
                  else if(ch == "/" && stream.eat(">")) {
                    popStateStack(state);
                    return ret("tag", "tag");
                  }
                  else
                    return ret("word", "variable");
                }
                // if a number
                else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/);
                  return ret("number", "atom");
                }
                // comment start
                else if (ch === "(" && stream.eat(":")) {
                  pushStateStack(state, { type: "comment"});
                  return chain(stream, state, tokenComment);
                }
                // quoted string
                else if (  !isEQName && (ch === '"' || ch === "'"))
                  return chain(stream, state, tokenString(ch));
                // variable
                else if(ch === "$") {
                  return chain(stream, state, tokenVariable);
                }
                // assignment
                else if(ch ===":" && stream.eat("=")) {
                  return ret("operator", "keyword");
                }
                // open paren
                else if(ch === "(") {
                  pushStateStack(state, { type: "paren"});
                  return ret("", null);
                }
                // close paren
                else if(ch === ")") {
                  popStateStack(state);
                  return ret("", null);
                }
                // open paren
                else if(ch === "[") {
                  pushStateStack(state, { type: "bracket"});
                  return ret("", null);
                }
                // close paren
                else if(ch === "]") {
                  popStateStack(state);
                  return ret("", null);
                }
                else {
                  var known = keywords.propertyIsEnumerable(ch) && keywords[ch];
            
                  // if there's a EQName ahead, consume the rest of the string portion, it's likely a function
                  if(isEQName && ch === '\"') while(stream.next() !== '"'){}
                  if(isEQName && ch === '\'') while(stream.next() !== '\''){}
            
                  // gobble up a word if the character is not known
                  if(!known) stream.eatWhile(/[\w\$_-]/);
            
                  // gobble a colon in the case that is a lib func type call fn:doc
                  var foundColon = stream.eat(":");
            
                  // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier
                  // which should get matched as a keyword
                  if(!stream.eat(":") && foundColon) {
                    stream.eatWhile(/[\w\$_-]/);
                  }
                  // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)
                  if(stream.match(/^[ \t]*\(/, false)) {
                    mightBeFunction = true;
                  }
                  // is the word a keyword?
                  var word = stream.current();
                  known = keywords.propertyIsEnumerable(word) && keywords[word];
            
                  // if we think it's a function call but not yet known,
                  // set style to variable for now for lack of something better
                  if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"};
            
                  // if the previous word was element, attribute, axis specifier, this word should be the name of that
                  if(isInXmlConstructor(state)) {
                    popStateStack(state);
                    return ret("word", "variable", word);
                  }
                  // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and
                  // push the stack so we know to look for it on the next word
                  if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"});
            
                  // if the word is known, return the details of that else just call this a generic 'word'
                  return known ? ret(known.type, known.style, word) :
                                 ret("word", "variable", word);
                }
              }
            
              // handle comments, including nested
              function tokenComment(stream, state) {
                var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
                while (ch = stream.next()) {
                  if (ch == ")" && maybeEnd) {
                    if(nestedCount > 0)
                      nestedCount--;
                    else {
                      popStateStack(state);
                      break;
                    }
                  }
                  else if(ch == ":" && maybeNested) {
                    nestedCount++;
                  }
                  maybeEnd = (ch == ":");
                  maybeNested = (ch == "(");
                }
            
                return ret("comment", "comment");
              }
            
              // tokenizer for string literals
              // optionally pass a tokenizer function to set state.tokenize back to when finished
              function tokenString(quote, f) {
                return function(stream, state) {
                  var ch;
            
                  if(isInString(state) && stream.current() == quote) {
                    popStateStack(state);
                    if(f) state.tokenize = f;
                    return ret("string", "string");
                  }
            
                  pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) });
            
                  // if we're in a string and in an XML block, allow an embedded code block
                  if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
                    state.tokenize = tokenBase;
                    return ret("string", "string");
                  }
            
            
                  while (ch = stream.next()) {
                    if (ch ==  quote) {
                      popStateStack(state);
                      if(f) state.tokenize = f;
                      break;
                    }
                    else {
                      // if we're in a string and in an XML block, allow an embedded code block in an attribute
                      if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
                        state.tokenize = tokenBase;
                        return ret("string", "string");
                      }
            
                    }
                  }
            
                  return ret("string", "string");
                };
              }
            
              // tokenizer for variables
              function tokenVariable(stream, state) {
                var isVariableChar = /[\w\$_-]/;
            
                // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote
                if(stream.eat("\"")) {
                  while(stream.next() !== '\"'){};
                  stream.eat(":");
                } else {
                  stream.eatWhile(isVariableChar);
                  if(!stream.match(":=", false)) stream.eat(":");
                }
                stream.eatWhile(isVariableChar);
                state.tokenize = tokenBase;
                return ret("variable", "variable");
              }
            
              // tokenizer for XML tags
              function tokenTag(name, isclose) {
                return function(stream, state) {
                  stream.eatSpace();
                  if(isclose && stream.eat(">")) {
                    popStateStack(state);
                    state.tokenize = tokenBase;
                    return ret("tag", "tag");
                  }
                  // self closing tag without attributes?
                  if(!stream.eat("/"))
                    pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase});
                  if(!stream.eat(">")) {
                    state.tokenize = tokenAttribute;
                    return ret("tag", "tag");
                  }
                  else {
                    state.tokenize = tokenBase;
                  }
                  return ret("tag", "tag");
                };
              }
            
              // tokenizer for XML attributes
              function tokenAttribute(stream, state) {
                var ch = stream.next();
            
                if(ch == "/" && stream.eat(">")) {
                  if(isInXmlAttributeBlock(state)) popStateStack(state);
                  if(isInXmlBlock(state)) popStateStack(state);
                  return ret("tag", "tag");
                }
                if(ch == ">") {
                  if(isInXmlAttributeBlock(state)) popStateStack(state);
                  return ret("tag", "tag");
                }
                if(ch == "=")
                  return ret("", null);
                // quoted string
                if (ch == '"' || ch == "'")
                  return chain(stream, state, tokenString(ch, tokenAttribute));
            
                if(!isInXmlAttributeBlock(state))
                  pushStateStack(state, { type: "attribute", tokenize: tokenAttribute});
            
                stream.eat(/[a-zA-Z_:]/);
                stream.eatWhile(/[-a-zA-Z0-9_:.]/);
                stream.eatSpace();
            
                // the case where the attribute has not value and the tag was closed
                if(stream.match(">", false) || stream.match("/", false)) {
                  popStateStack(state);
                  state.tokenize = tokenBase;
                }
            
                return ret("attribute", "attribute");
              }
            
              // handle comments, including nested
              function tokenXMLComment(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "-" && stream.match("->", true)) {
                    state.tokenize = tokenBase;
                    return ret("comment", "comment");
                  }
                }
              }
            
            
              // handle CDATA
              function tokenCDATA(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "]" && stream.match("]", true)) {
                    state.tokenize = tokenBase;
                    return ret("comment", "comment");
                  }
                }
              }
            
              // handle preprocessing instructions
              function tokenPreProcessing(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "?" && stream.match(">", true)) {
                    state.tokenize = tokenBase;
                    return ret("comment", "comment meta");
                  }
                }
              }
            
            
              // functions to test the current context of the state
              function isInXmlBlock(state) { return isIn(state, "tag"); }
              function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
              function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }
              function isInString(state) { return isIn(state, "string"); }
            
              function isEQNameAhead(stream) {
                // assume we've already eaten a quote (")
                if(stream.current() === '"')
                  return stream.match(/^[^\"]+\"\:/, false);
                else if(stream.current() === '\'')
                  return stream.match(/^[^\"]+\'\:/, false);
                else
                  return false;
              }
            
              function isIn(state, type) {
                return (state.stack.length && state.stack[state.stack.length - 1].type == type);
              }
            
              function pushStateStack(state, newState) {
                state.stack.push(newState);
              }
            
              function popStateStack(state) {
                state.stack.pop();
                var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize;
                state.tokenize = reinstateTokenize || tokenBase;
              }
            
              // the interface for the mode API
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    cc: [],
                    stack: []
                  };
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
            
                blockCommentStart: "(:",
                blockCommentEnd: ":)"
            
              };
            
            });
            
            CodeMirror.defineMIME("application/xquery", "xquery");
            
            });
            
        • yaml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: YAML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="yaml.js"></script>
            <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">YAML</a>
              </ul>
            </div>
            
            <article>
            <h2>YAML mode</h2>
            <form><textarea id="code" name="code">
            --- # Favorite movies
            - Casablanca
            - North by Northwest
            - The Man Who Wasn't There
            --- # Shopping list
            [milk, pumpkin pie, eggs, juice]
            --- # Indented Blocks, common in YAML data files, use indentation and new lines to separate the key: value pairs
              name: John Smith
              age: 33
            --- # Inline Blocks, common in YAML data streams, use commas to separate the key: value pairs between braces
            {name: John Smith, age: 33}
            ---
            receipt:     Oz-Ware Purchase Invoice
            date:        2007-08-06
            customer:
                given:   Dorothy
                family:  Gale
            
            items:
                - part_no:   A4786
                  descrip:   Water Bucket (Filled)
                  price:     1.47
                  quantity:  4
            
                - part_no:   E1628
                  descrip:   High Heeled "Ruby" Slippers
                  size:       8
                  price:     100.27
                  quantity:  1
            
            bill-to:  &id001
                street: |
                        123 Tornado Alley
                        Suite 16
                city:   East Centerville
                state:  KS
            
            ship-to:  *id001
            
            specialDelivery:  >
                Follow the Yellow Brick
                Road to the Emerald City.
                Pay no attention to the
                man behind the curtain.
            ...
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-yaml</code>.</p>
            
              </article>
            
          • yaml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("yaml", function() {
            
              var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];
              var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i');
            
              return {
                token: function(stream, state) {
                  var ch = stream.peek();
                  var esc = state.escaped;
                  state.escaped = false;
                  /* comments */
                  if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))
                    return "string";
            
                  if (state.literal && stream.indentation() > state.keyCol) {
                    stream.skipToEnd(); return "string";
                  } else if (state.literal) { state.literal = false; }
                  if (stream.sol()) {
                    state.keyCol = 0;
                    state.pair = false;
                    state.pairStart = false;
                    /* document start */
                    if(stream.match(/---/)) { return "def"; }
                    /* document end */
                    if (stream.match(/\.\.\./)) { return "def"; }
                    /* array list item */
                    if (stream.match(/\s*-\s+/)) { return 'meta'; }
                  }
                  /* inline pairs/lists */
                  if (stream.match(/^(\{|\}|\[|\])/)) {
                    if (ch == '{')
                      state.inlinePairs++;
                    else if (ch == '}')
                      state.inlinePairs--;
                    else if (ch == '[')
                      state.inlineList++;
                    else
                      state.inlineList--;
                    return 'meta';
                  }
            
                  /* list seperator */
                  if (state.inlineList > 0 && !esc && ch == ',') {
                    stream.next();
                    return 'meta';
                  }
                  /* pairs seperator */
                  if (state.inlinePairs > 0 && !esc && ch == ',') {
                    state.keyCol = 0;
                    state.pair = false;
                    state.pairStart = false;
                    stream.next();
                    return 'meta';
                  }
            
                  /* start of value of a pair */
                  if (state.pairStart) {
                    /* block literals */
                    if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; };
                    /* references */
                    if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; }
                    /* numbers */
                    if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; }
                    if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; }
                    /* keywords */
                    if (stream.match(keywordRegex)) { return 'keyword'; }
                  }
            
                  /* pairs (associative arrays) -> key */
                  if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) {
                    state.pair = true;
                    state.keyCol = stream.indentation();
                    return "atom";
                  }
                  if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; }
            
                  /* nothing found, continue */
                  state.pairStart = false;
                  state.escaped = (ch == '\\');
                  stream.next();
                  return null;
                },
                startState: function() {
                  return {
                    pair: false,
                    pairStart: false,
                    keyCol: 0,
                    inlinePairs: 0,
                    inlineList: 0,
                    literal: false,
                    escaped: false
                  };
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-yaml", "yaml");
            
            });
            
        • z80
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Z80 assembly mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="z80.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Z80 assembly</a>
              </ul>
            </div>
            
            <article>
            <h2>Z80 assembly mode</h2>
            
            
            <div><textarea id="code" name="code">
            #include    "ti83plus.inc"
            #define     progStart   $9D95
            .org        progStart-2
            .db         $BB,$6D
                bcall(_ClrLCDFull)
                ld  HL, 0
                ld  (PenCol),   HL
                ld  HL, Message
                bcall(_PutS) ; Displays the string
                bcall(_NewLine)
                ret
            Message:
            .db         "Hello world!",0
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME type defined:</strong> <code>text/x-z80</code>.</p>
              </article>
            
          • z80.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('z80', function() {
              var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i;
              var keywords2 = /^(call|j[pr]|ret[in]?)\b/i;
              var keywords3 = /^b_?(call|jump)\b/i;
              var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i;
              var variables2 = /^(n?[zc]|p[oe]?|m)\b/i;
              var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\b/i;
              var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+)\b/i;
            
              return {
                startState: function() {
                  return {context: 0};
                },
                token: function(stream, state) {
                  if (!stream.column())
                    state.context = 0;
            
                  if (stream.eatSpace())
                    return null;
            
                  var w;
            
                  if (stream.eatWhile(/\w/)) {
                    w = stream.current();
            
                    if (stream.indentation()) {
                      if (state.context == 1 && variables1.test(w))
                        return 'variable-2';
            
                      if (state.context == 2 && variables2.test(w))
                        return 'variable-3';
            
                      if (keywords1.test(w)) {
                        state.context = 1;
                        return 'keyword';
                      } else if (keywords2.test(w)) {
                        state.context = 2;
                        return 'keyword';
                      } else if (keywords3.test(w)) {
                        state.context = 3;
                        return 'keyword';
                      }
            
                      if (errors.test(w))
                        return 'error';
                    } else if (numbers.test(w)) {
                      return 'number';
                    } else {
                      return null;
                    }
                  } else if (stream.eat(';')) {
                    stream.skipToEnd();
                    return 'comment';
                  } else if (stream.eat('"')) {
                    while (w = stream.next()) {
                      if (w == '"')
                        break;
            
                      if (w == '\\')
                        stream.next();
                    }
                    return 'string';
                  } else if (stream.eat('\'')) {
                    if (stream.match(/\\?.'/))
                      return 'number';
                  } else if (stream.eat('.') || stream.sol() && stream.eat('#')) {
                    state.context = 4;
            
                    if (stream.eatWhile(/\w/))
                      return 'def';
                  } else if (stream.eat('$')) {
                    if (stream.eatWhile(/[\da-f]/i))
                      return 'number';
                  } else if (stream.eat('%')) {
                    if (stream.eatWhile(/[01]/))
                      return 'number';
                  } else {
                    stream.next();
                  }
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-z80", "z80");
            
            });
            
        • index.html
          <!doctype html>
          
          <title>CodeMirror: Language Modes</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Language modes</a>
            </ul>
          </div>
          
          <article>
          
            <h2>Language modes</h2>
          
            <p>This is a list of every mode in the distribution. Each mode lives
          in a subdirectory of the <code>mode/</code> directory, and typically
          defines a single JavaScript file that implements the mode. Loading
          such file will make the language available to CodeMirror, through
          the <a href="../doc/manual.html#option_mode"><code>mode</code></a>
          option.</p>
          
            <div style="-webkit-columns: 100px 2; -moz-columns: 100px 2; columns: 100px 2;">
              <ul style="margin-top: 0">
                <li><a href="apl/index.html">APL</a></li>
                <li><a href="asterisk/index.html">Asterisk dialplan</a></li>
                <li><a href="clike/index.html">C, C++, C#</a></li>
                <li><a href="clojure/index.html">Clojure</a></li>
                <li><a href="cobol/index.html">COBOL</a></li>
                <li><a href="coffeescript/index.html">CoffeeScript</a></li>
                <li><a href="commonlisp/index.html">Common Lisp</a></li>
                <li><a href="css/index.html">CSS</a></li>
                <li><a href="cypher/index.html">Cypher</a></li>
                <li><a href="python/index.html">Cython</a></li>
                <li><a href="d/index.html">D</a></li>
                <li><a href="dart/index.html">Dart</a></li>
                <li><a href="django/index.html">Django</a> (templating language)</li>
                <li><a href="dockerfile/index.html">Dockerfile</a></li>
                <li><a href="diff/index.html">diff</a></li>
                <li><a href="dtd/index.html">DTD</a></li>
                <li><a href="dylan/index.html">Dylan</a></li>
                <li><a href="ebnf/index.html">EBNF</a></li>
                <li><a href="ecl/index.html">ECL</a></li>
                <li><a href="eiffel/index.html">Eiffel</a></li>
                <li><a href="erlang/index.html">Erlang</a></li>
                <li><a href="forth/index.html">Forth</a></li>
                <li><a href="fortran/index.html">Fortran</a></li>
                <li><a href="mllike/index.html">F#</a></li>
                <li><a href="gas/index.html">Gas</a> (AT&amp;T-style assembly)</li>
                <li><a href="gherkin/index.html">Gherkin</a></li>
                <li><a href="go/index.html">Go</a></li>
                <li><a href="groovy/index.html">Groovy</a></li>
                <li><a href="haml/index.html">HAML</a></li>
                <li><a href="haskell/index.html">Haskell</a></li>
                <li><a href="haxe/index.html">Haxe</a></li>
                <li><a href="htmlembedded/index.html">HTML embedded scripts</a></li>
                <li><a href="htmlmixed/index.html">HTML mixed-mode</a></li>
                <li><a href="http/index.html">HTTP</a></li>
                <li><a href="idl/index.html">IDL</a></li>
                <li><a href="clike/index.html">Java</a></li>
                <li><a href="jade/index.html">Jade</a></li>
                <li><a href="javascript/index.html">JavaScript</a></li>
                <li><a href="jinja2/index.html">Jinja2</a></li>
                <li><a href="julia/index.html">Julia</a></li>
                <li><a href="kotlin/index.html">Kotlin</a></li>
                <li><a href="css/less.html">LESS</a></li>
                <li><a href="livescript/index.html">LiveScript</a></li>
                <li><a href="lua/index.html">Lua</a></li>
                <li><a href="markdown/index.html">Markdown</a> (<a href="gfm/index.html">GitHub-flavour</a>)</li>
                <li><a href="mirc/index.html">mIRC</a></li>
                <li><a href="modelica/index.html">Modelica</a></li>
                <li><a href="nginx/index.html">Nginx</a></li>
                <li><a href="ntriples/index.html">NTriples</a></li>
                <li><a href="clike/index.html">Objective C</a></li>
                <li><a href="mllike/index.html">OCaml</a></li>
                <li><a href="octave/index.html">Octave</a> (MATLAB)</li>
                <li><a href="pascal/index.html">Pascal</a></li>
                <li><a href="pegjs/index.html">PEG.js</a></li>
                <li><a href="perl/index.html">Perl</a></li>
                <li><a href="php/index.html">PHP</a></li>
                <li><a href="pig/index.html">Pig Latin</a></li>
                <li><a href="properties/index.html">Properties files</a></li>
                <li><a href="puppet/index.html">Puppet</a></li>
                <li><a href="python/index.html">Python</a></li>
                <li><a href="q/index.html">Q</a></li>
                <li><a href="r/index.html">R</a></li>
                <li><a href="rpm/index.html">RPM</a></li>
                <li><a href="rst/index.html">reStructuredText</a></li>
                <li><a href="ruby/index.html">Ruby</a></li>
                <li><a href="rust/index.html">Rust</a></li>
                <li><a href="sass/index.html">Sass</a></li>
                <li><a href="spreadsheet/index.html">Spreadsheet</a></li>
                <li><a href="clike/scala.html">Scala</a></li>
                <li><a href="scheme/index.html">Scheme</a></li>
                <li><a href="css/scss.html">SCSS</a></li>
                <li><a href="shell/index.html">Shell</a></li>
                <li><a href="sieve/index.html">Sieve</a></li>
                <li><a href="slim/index.html">Slim</a></li>
                <li><a href="smalltalk/index.html">Smalltalk</a></li>
                <li><a href="smarty/index.html">Smarty</a></li>
                <li><a href="smartymixed/index.html">Smarty/HTML mixed</a></li>
                <li><a href="solr/index.html">Solr</a></li>
                <li><a href="soy/index.html">Soy</a></li>
                <li><a href="stylus/index.html">Stylus</a></li>
                <li><a href="sql/index.html">SQL</a> (several dialects)</li>
                <li><a href="sparql/index.html">SPARQL</a></li>
                <li><a href="stex/index.html">sTeX, LaTeX</a></li>
                <li><a href="tcl/index.html">Tcl</a></li>
                <li><a href="textile/index.html">Textile</a></li>
                <li><a href="tiddlywiki/index.html">Tiddlywiki</a></li>
                <li><a href="tiki/index.html">Tiki wiki</a></li>
                <li><a href="toml/index.html">TOML</a></li>
                <li><a href="tornado/index.html">Tornado</a> (templating language)</li>
                <li><a href="turtle/index.html">Turtle</a></li>
                <li><a href="vb/index.html">VB.NET</a></li>
                <li><a href="vbscript/index.html">VBScript</a></li>
                <li><a href="velocity/index.html">Velocity</a></li>
                <li><a href="verilog/index.html">Verilog/SystemVerilog</a></li>
                <li><a href="xml/index.html">XML/HTML</a></li>
                <li><a href="xquery/index.html">XQuery</a></li>
                <li><a href="yaml/index.html">YAML</a></li>
                <li><a href="z80/index.html">Z80</a></li>
              </ul>
            </div>
          
          </article>
          
        • meta.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../lib/codemirror"));
            else if (typeof define == "function" && define.amd) // AMD
              define(["../lib/codemirror"], mod);
            else // Plain browser env
              mod(CodeMirror);
          })(function(CodeMirror) {
            "use strict";
          
            CodeMirror.modeInfo = [
              {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
              {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
              {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},
              {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
              {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
              {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
              {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]},
              {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
              {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
              {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
              {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
              {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
              {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
              {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
              {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
              {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
              {name: "Django", mime: "text/x-django", mode: "django"},
              {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
              {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
              {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
              {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
              {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
              {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
              {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
              {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
              {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
              {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
              {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]},
              {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
              {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
              {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
              {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
              {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
              {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]},
              {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
              {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
              {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
              {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
              {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
              {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]},
              {name: "HTTP", mime: "message/http", mode: "http"},
              {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
              {name: "Jade", mime: "text/x-jade", mode: "jade", ext: ["jade"]},
              {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
              {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
              {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
               mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
              {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
              {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
              {name: "Jinja2", mime: "null", mode: "jinja2"},
              {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
              {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]},
              {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
              {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
              {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
              {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
              {name: "mIRC", mime: "text/mirc", mode: "mirc"},
              {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
              {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
              {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
              {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
              {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
              {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
              {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},
              {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
              {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
              {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
              {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
              {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
              {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]},
              {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
              {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
              {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
              {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
              {name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]},
              {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
              {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
              {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]},
              {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
              {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
              {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
              {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
              {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
              {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
              {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
              {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
              {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
              {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]},
              {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
              {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
              {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
              {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
              {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"},
              {name: "Solr", mime: "text/x-solr", mode: "solr"},
              {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
              {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
              {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
              {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
              {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"},
              {name: "sTeX", mime: "text/x-stex", mode: "stex"},
              {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]},
              {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]},
              {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
              {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
              {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
              {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
              {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
              {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
              {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
              {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
              {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
              {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
              {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
              {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
              {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]},
              {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
              {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml"], alias: ["yml"]},
              {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]}
            ];
            // Ensure all modes have a mime property for backwards compatibility
            for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
              var info = CodeMirror.modeInfo[i];
              if (info.mimes) info.mime = info.mimes[0];
            }
          
            CodeMirror.findModeByMIME = function(mime) {
              mime = mime.toLowerCase();
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.mime == mime) return info;
                if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
                  if (info.mimes[j] == mime) return info;
              }
            };
          
            CodeMirror.findModeByExtension = function(ext) {
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.ext) for (var j = 0; j < info.ext.length; j++)
                  if (info.ext[j] == ext) return info;
              }
            };
          
            CodeMirror.findModeByFileName = function(filename) {
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.file && info.file.test(filename)) return info;
              }
              var dot = filename.lastIndexOf(".");
              var ext = dot > -1 && filename.substring(dot + 1, filename.length);
              if (ext) return CodeMirror.findModeByExtension(ext);
            };
          
            CodeMirror.findModeByName = function(name) {
              name = name.toLowerCase();
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.name.toLowerCase() == name) return info;
                if (info.alias) for (var j = 0; j < info.alias.length; j++)
                  if (info.alias[j].toLowerCase() == name) return info;
              }
            };
          });
          
      • test
        • comment_test.js
          namespace = "comment_";
          
          (function() {
            function test(name, mode, run, before, after) {
              return testCM(name, function(cm) {
                run(cm);
                eq(cm.getValue(), after);
              }, {value: before, mode: mode});
            }
          
            var simpleProg = "function foo() {\n  return bar;\n}";
            var inlineBlock = "foo(/* bar */ true);";
            var inlineBlocks = "foo(/* bar */ true, /* baz */ false);";
            var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"];
          
            test("block", "javascript", function(cm) {
              cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"});
            }, simpleProg + "\n", "/* function foo() {\n *   return bar;\n * }\n */");
          
            test("blockToggle", "javascript", function(cm) {
              cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
              cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
            }, simpleProg, simpleProg);
          
            test("blockToggle2", "javascript", function(cm) {
              cm.setCursor({line: 0, ch: 7 /* inside the block comment */});
              cm.execCommand("toggleComment");
            }, inlineBlock, "foo(bar true);");
          
            // This test should work but currently fails.
            // test("blockToggle3", "javascript", function(cm) {
            //   cm.setCursor({line: 0, ch: 7 /* inside the first block comment */});
            //   cm.execCommand("toggleComment");
            // }, inlineBlocks, "foo(bar true, /* baz */ false);");
          
            test("line", "javascript", function(cm) {
              cm.lineComment(Pos(1, 1), Pos(1, 1));
            }, simpleProg, "function foo() {\n//   return bar;\n}");
          
            test("lineToggle", "javascript", function(cm) {
              cm.lineComment(Pos(0, 0), Pos(2, 1));
              cm.uncomment(Pos(0, 0), Pos(2, 1));
            }, simpleProg, simpleProg);
          
            test("fallbackToBlock", "css", function(cm) {
              cm.lineComment(Pos(0, 0), Pos(2, 1));
            }, "html {\n  border: none;\n}", "/* html {\n  border: none;\n} */");
          
            test("fallbackToLine", "ruby", function(cm) {
              cm.blockComment(Pos(0, 0), Pos(1));
            }, "def blah()\n  return hah\n", "# def blah()\n#   return hah\n");
          
            test("ignoreExternalBlockComments", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, inlineBlocks, "// " + inlineBlocks);
          
            test("ignoreExternalBlockComments2", "javascript", function(cm) {
              cm.setCursor({line: 0, ch: null /* eol */});
              cm.execCommand("toggleComment");
            }, inlineBlocks, "// " + inlineBlocks);
          
            test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) {
              cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1});
              cm.execCommand("toggleComment");
            }, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0],
                                                 "// " + multiLineInlineBlock[1],
                                                 multiLineInlineBlock[2]].join("\n"));
          
            test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) {
              cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1});
              cm.execCommand("toggleComment");
            }, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0],
                                                 "// " + multiLineInlineBlock[1],
                                                 "// " + multiLineInlineBlock[2]].join("\n"));
          
            test("commentRange", "javascript", function(cm) {
              cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false});
            }, simpleProg, "function foo() {\n  /*return bar;*/\n}");
          
            test("indented", "javascript", function(cm) {
              cm.lineComment(Pos(1, 0), Pos(2), {indent: true});
            }, simpleProg, "function foo() {\n  // return bar;\n  // }");
          
            test("singleEmptyLine", "javascript", function(cm) {
              cm.setCursor(1);
              cm.execCommand("toggleComment");
            }, "a;\n\nb;", "a;\n// \nb;");
          
            test("dontMessWithStrings", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");");
          
            test("dontMessWithStrings2", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "console.log(\"// string\");", "// console.log(\"// string\");");
          
            test("dontMessWithStrings3", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "// console.log(\"// string\");", "console.log(\"// string\");");
          })();
          
        • doc_test.js
          (function() {
            // A minilanguage for instantiating linked CodeMirror instances and Docs
            function instantiateSpec(spec, place, opts) {
              var names = {}, pos = 0, l = spec.length, editors = [];
              while (spec) {
                var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/);
                var name = m[1], isDoc = m[2], cur;
                if (m[3]) {
                  cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]}));
                } else {
                  var other = m[5];
                  if (!names.hasOwnProperty(other)) {
                    names[other] = editors.length;
                    editors.push(CodeMirror(place, opts));
                  }
                  var doc = editors[names[other]].linkedDoc({
                    sharedHist: !m[4],
                    from: m[6] ? Number(m[6]) : null,
                    to: m[7] ? Number(m[7]) : null
                  });
                  cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc}));
                }
                names[name] = editors.length;
                editors.push(cur);
                spec = spec.slice(m[0].length);
              }
              return editors;
            }
          
            function clone(obj, props) {
              if (!obj) return;
              clone.prototype = obj;
              var inst = new clone();
              if (props) for (var n in props) if (props.hasOwnProperty(n))
                inst[n] = props[n];
              return inst;
            }
          
            function eqAll(val) {
              var end = arguments.length, msg = null;
              if (typeof arguments[end-1] == "string")
                msg = arguments[--end];
              if (i == end) throw new Error("No editors provided to eqAll");
              for (var i = 1; i < end; ++i)
                eq(arguments[i].getValue(), val, msg)
            }
          
            function testDoc(name, spec, run, opts, expectFail) {
              if (!opts) opts = {};
          
              return test("doc_" + name, function() {
                var place = document.getElementById("testground");
                var editors = instantiateSpec(spec, place, opts);
                var successful = false;
          
                try {
                  run.apply(null, editors);
                  successful = true;
                } finally {
                  if (!successful || verbose) {
                    place.style.visibility = "visible";
                  } else {
                    for (var i = 0; i < editors.length; ++i)
                      if (editors[i] instanceof CodeMirror)
                        place.removeChild(editors[i].getWrapperElement());
                  }
                }
              }, expectFail);
            }
          
            var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
          
            function testBasic(a, b) {
              eqAll("x", a, b);
              a.setValue("hey");
              eqAll("hey", a, b);
              b.setValue("wow");
              eqAll("wow", a, b);
              a.replaceRange("u\nv\nw", Pos(0, 3));
              b.replaceRange("i", Pos(0, 4));
              b.replaceRange("j", Pos(2, 1));
              eqAll("wowui\nv\nwj", a, b);
            }
          
            testDoc("basic", "A='x' B<A", testBasic);
            testDoc("basicSeparate", "A='x' B<~A", testBasic);
          
            testDoc("sharedHist", "A='ab\ncd\nef' B<A", function(a, b) {
              a.replaceRange("x", Pos(0));
              b.replaceRange("y", Pos(1));
              a.replaceRange("z", Pos(2));
              eqAll("abx\ncdy\nefz", a, b);
              a.undo();
              a.undo();
              eqAll("abx\ncd\nef", a, b);
              a.redo();
              eqAll("abx\ncdy\nef", a, b);
              b.redo();
              eqAll("abx\ncdy\nefz", a, b);
              a.undo(); b.undo(); a.undo(); a.undo();
              eqAll("ab\ncd\nef", a, b);
            }, null, ie_lt8);
          
            testDoc("undoIntact", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(0));
              b.replaceRange("y", Pos(1));
              a.replaceRange("z", Pos(2));
              a.replaceRange("q", Pos(0));
              eqAll("abxq\ncdy\nefz", a, b);
              a.undo();
              a.undo();
              eqAll("abx\ncdy\nef", a, b);
              b.undo();
              eqAll("abx\ncd\nef", a, b);
              a.redo();
              eqAll("abx\ncd\nefz", a, b);
              a.redo();
              eqAll("abxq\ncd\nefz", a, b);
              a.undo(); a.undo(); a.undo(); a.undo();
              eqAll("ab\ncd\nef", a, b);
              b.redo();
              eqAll("ab\ncdy\nef", a, b);
            });
          
            testDoc("undoConflict", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(0));
              a.replaceRange("z", Pos(2));
              // This should clear the first undo event in a, but not the second
              b.replaceRange("y", Pos(0));
              a.undo(); a.undo();
              eqAll("abxy\ncd\nef", a, b);
              a.replaceRange("u", Pos(2));
              a.replaceRange("v", Pos(0));
              // This should clear both events in a
              b.replaceRange("w", Pos(0));
              a.undo(); a.undo();
              eqAll("abxyvw\ncd\nefu", a, b);
            });
          
            testDoc("doubleRebase", "A='ab\ncd\nef\ng' B<~A C<B", function(a, b, c) {
              c.replaceRange("u", Pos(3));
              a.replaceRange("", Pos(0, 0), Pos(1, 0));
              c.undo();
              eqAll("cd\nef\ng", a, b, c);
            });
          
            testDoc("undoUpdate", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(2));
              b.replaceRange("u\nv\nw\n", Pos(0, 0));
              a.undo();
              eqAll("u\nv\nw\nab\ncd\nef", a, b);
              a.redo();
              eqAll("u\nv\nw\nab\ncd\nefx", a, b);
              a.undo();
              eqAll("u\nv\nw\nab\ncd\nef", a, b);
              b.undo();
              a.redo();
              eqAll("ab\ncd\nefx", a, b);
              a.undo();
              eqAll("ab\ncd\nef", a, b);
            });
          
            testDoc("undoKeepRanges", "A='abcdefg' B<A", function(a, b) {
              var m = a.markText(Pos(0, 1), Pos(0, 3), {className: "foo"});
              b.replaceRange("x", Pos(0, 0));
              eqPos(m.find().from, Pos(0, 2));
              b.replaceRange("yzzy", Pos(0, 1), Pos(0));
              eq(m.find(), null);
              b.undo();
              eqPos(m.find().from, Pos(0, 2));
              b.undo();
              eqPos(m.find().from, Pos(0, 1));
            });
          
            testDoc("longChain", "A='uv' B<A C<B D<C", function(a, b, c, d) {
              a.replaceSelection("X");
              eqAll("Xuv", a, b, c, d);
              d.replaceRange("Y", Pos(0));
              eqAll("XuvY", a, b, c, d);
            });
          
            testDoc("broadCast", "B<A C<A D<A E<A", function(a, b, c, d, e) {
              b.setValue("uu");
              eqAll("uu", a, b, c, d, e);
              a.replaceRange("v", Pos(0, 1));
              eqAll("uvu", a, b, c, d, e);
            });
          
            // A and B share a history, C and D share a separate one
            testDoc("islands", "A='x\ny\nz' B<A C<~A D<C", function(a, b, c, d) {
              a.replaceRange("u", Pos(0));
              d.replaceRange("v", Pos(2));
              b.undo();
              eqAll("x\ny\nzv", a, b, c, d);
              c.undo();
              eqAll("x\ny\nz", a, b, c, d);
              a.redo();
              eqAll("xu\ny\nz", a, b, c, d);
              d.redo();
              eqAll("xu\ny\nzv", a, b, c, d);
            });
          
            testDoc("unlink", "B<A C<A D<B", function(a, b, c, d) {
              a.setValue("hi");
              b.unlinkDoc(a);
              d.setValue("aye");
              eqAll("hi", a, c);
              eqAll("aye", b, d);
              a.setValue("oo");
              eqAll("oo", a, c);
              eqAll("aye", b, d);
            });
          
            testDoc("bareDoc", "A*='foo' B*<A C<B", function(a, b, c) {
              is(a instanceof CodeMirror.Doc);
              is(b instanceof CodeMirror.Doc);
              is(c instanceof CodeMirror);
              eqAll("foo", a, b, c);
              a.replaceRange("hey", Pos(0, 0), Pos(0));
              c.replaceRange("!", Pos(0));
              eqAll("hey!", a, b, c);
              b.unlinkDoc(a);
              b.setValue("x");
              eqAll("x", b, c);
              eqAll("hey!", a);
            });
          
            testDoc("swapDoc", "A='a' B*='b' C<A", function(a, b, c) {
              var d = a.swapDoc(b);
              d.setValue("x");
              eqAll("x", c, d);
              eqAll("b", a, b);
            });
          
            testDoc("docKeepsScroll", "A='x' B*='y'", function(a, b) {
              addDoc(a, 200, 200);
              a.scrollIntoView(Pos(199, 200));
              var c = a.swapDoc(b);
              a.swapDoc(c);
              var pos = a.getScrollInfo();
              is(pos.left > 0, "not at left");
              is(pos.top > 0, "not at top");
            });
          
            testDoc("copyDoc", "A='u'", function(a) {
              var copy = a.getDoc().copy(true);
              a.setValue("foo");
              copy.setValue("bar");
              var old = a.swapDoc(copy);
              eq(a.getValue(), "bar");
              a.undo();
              eq(a.getValue(), "u");
              a.swapDoc(old);
              eq(a.getValue(), "foo");
              eq(old.historySize().undo, 1);
              eq(old.copy(false).historySize().undo, 0);
            });
          
            testDoc("docKeepsMode", "A='1+1'", function(a) {
              var other = CodeMirror.Doc("hi", "text/x-markdown");
              a.setOption("mode", "text/javascript");
              var old = a.swapDoc(other);
              eq(a.getOption("mode"), "text/x-markdown");
              eq(a.getMode().name, "markdown");
              a.swapDoc(old);
              eq(a.getOption("mode"), "text/javascript");
              eq(a.getMode().name, "javascript");
            });
          
            testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) {
              eq(b.getValue(), "2\n3");
              eq(b.firstLine(), 1);
              b.setCursor(Pos(4));
              eqPos(b.getCursor(), Pos(2, 1));
              a.replaceRange("-1\n0\n", Pos(0, 0));
              eq(b.firstLine(), 3);
              eqPos(b.getCursor(), Pos(4, 1));
              a.undo();
              eqPos(b.getCursor(), Pos(2, 1));
              b.replaceRange("oyoy\n", Pos(2, 0));
              eq(a.getValue(), "1\n2\noyoy\n3\n4\n5");
              b.undo();
              eq(a.getValue(), "1\n2\n3\n4\n5");
            });
          
            testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) {
              a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1));
              eq(b.firstLine(), 2);
              eq(b.lineCount(), 2);
              eq(b.getValue(), "z3\n44");
              a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1));
              eq(b.firstLine(), 2);
              eq(b.getValue(), "z3\n4q");
              eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5");
              a.execCommand("selectAll");
              a.replaceSelection("!");
              eqAll("!", a, b);
            });
          
          
            testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
              var mark = b.markText(Pos(0, 1), Pos(3, 1),
                                    {className: "cm-searching", shared: true});
              var found = a.findMarksAt(Pos(0, 2));
              eq(found.length, 1);
              eq(found[0], mark);
              eq(c.findMarksAt(Pos(1, 1)).length, 1);
              eqPos(mark.find().from, Pos(0, 1));
              eqPos(mark.find().to, Pos(3, 1));
              b.replaceRange("x\ny\n", Pos(0, 0));
              eqPos(mark.find().from, Pos(2, 1));
              eqPos(mark.find().to, Pos(5, 1));
              var cleared = 0;
              CodeMirror.on(mark, "clear", function() {++cleared;});
              b.operation(function(){mark.clear();});
              eq(a.findMarksAt(Pos(3, 1)).length, 0);
              eq(b.findMarksAt(Pos(3, 1)).length, 0);
              eq(c.findMarksAt(Pos(3, 1)).length, 0);
              eq(mark.find(), null);
              eq(cleared, 1);
            });
          
            testDoc("sharedMarkerCopy", "A='abcde'", function(a) {
              var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});
              var b = a.linkedDoc();
              var found = b.findMarksAt(Pos(0, 2));
              eq(found.length, 1);
              eq(found[0], shared);
              shared.clear();
              eq(b.findMarksAt(Pos(0, 2)), 0);
            });
          
            testDoc("sharedMarkerDetach", "A='abcde' B<A C<B", function(a, b, c) {
              var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});
              a.unlinkDoc(b);
              var inB = b.findMarksAt(Pos(0, 2));
              eq(inB.length, 1);
              is(inB[0] != shared);
              var inC = c.findMarksAt(Pos(0, 2));
              eq(inC.length, 1);
              is(inC[0] != shared);
              inC[0].clear();
              is(shared.find());
            });
          
            testDoc("sharedBookmark", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
              var mark = b.setBookmark(Pos(1, 1), {shared: true});
              var found = a.findMarksAt(Pos(1, 1));
              eq(found.length, 1);
              eq(found[0], mark);
              eq(c.findMarksAt(Pos(1, 1)).length, 1);
              eqPos(mark.find(), Pos(1, 1));
              b.replaceRange("x\ny\n", Pos(0, 0));
              eqPos(mark.find(), Pos(3, 1));
              var cleared = 0;
              CodeMirror.on(mark, "clear", function() {++cleared;});
              b.operation(function() {mark.clear();});
              eq(a.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(b.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(c.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(mark.find(), null);
              eq(cleared, 1);
            });
          
            testDoc("undoInSubview", "A='line 0\nline 1\nline 2\nline 3\nline 4' B<A/1-4", function(a, b) {
              b.replaceRange("x", Pos(2, 0));
              a.undo();
              eq(a.getValue(), "line 0\nline 1\nline 2\nline 3\nline 4");
              eq(b.getValue(), "line 1\nline 2\nline 3");
            });
          })();
          
        • driver.js
          var tests = [], filters = [], allNames = [];
          
          function Failure(why) {this.message = why;}
          Failure.prototype.toString = function() { return this.message; };
          
          function indexOf(collection, elt) {
            if (collection.indexOf) return collection.indexOf(elt);
            for (var i = 0, e = collection.length; i < e; ++i)
              if (collection[i] == elt) return i;
            return -1;
          }
          
          function test(name, run, expectedFail) {
            // Force unique names
            var originalName = name;
            var i = 2; // Second function would be NAME_2
            while (indexOf(allNames, name) !== -1){
              name = originalName + "_" + i;
              i++;
            }
            allNames.push(name);
            // Add test
            tests.push({name: name, func: run, expectedFail: expectedFail});
            return name;
          }
          var namespace = "";
          function testCM(name, run, opts, expectedFail) {
            return test(namespace + name, function() {
              var place = document.getElementById("testground"), cm = window.cm = CodeMirror(place, opts);
              var successful = false;
              try {
                run(cm);
                successful = true;
              } finally {
                if (!successful || verbose) {
                  place.style.visibility = "visible";
                } else {
                  place.removeChild(cm.getWrapperElement());
                }
              }
            }, expectedFail);
          }
          
          function runTests(callback) {
            var totalTime = 0;
            function step(i) {
              for (;;) {
                if (i === tests.length) {
                  running = false;
                  return callback("done");
                }
                var test = tests[i], skip = false;
                if (filters.length) {
                  skip = true;
                  for (var j = 0; j < filters.length; j++)
                    if (test.name.match(filters[j])) skip = false;
                }
                if (skip) {
                  callback("skipped", test.name, message);
                  i++;
                } else {
                  break;
                }
              }
              var expFail = test.expectedFail, startTime = +new Date, threw = false;
              try {
                var message = test.func();
              } catch(e) {
                threw = true;
                if (expFail) callback("expected", test.name);
                else if (e instanceof Failure) callback("fail", test.name, e.message);
                else {
                  var pos = /(?:\bat |@).*?([^\/:]+):(\d+)/.exec(e.stack);
                  if (pos) console["log"](e.stack);
                  callback("error", test.name, e.toString() + (pos ? " (" + pos[1] + ":" + pos[2] + ")" : ""));
                }
              }
              if (!threw) {
                if (expFail) callback("fail", test.name, message || "expected failure, but succeeded");
                else callback("ok", test.name, message);
              }
              if (!quit) { // Run next test
                var delay = 0;
                totalTime += (+new Date) - startTime;
                if (totalTime > 500){
                  totalTime = 0;
                  delay = 50;
                }
                setTimeout(function(){step(i + 1);}, delay);
              } else { // Quit tests
                running = false;
                return null;
              }
            }
            step(0);
          }
          
          function label(str, msg) {
            if (msg) return str + " (" + msg + ")";
            return str;
          }
          function eq(a, b, msg) {
            if (a != b) throw new Failure(label(a + " != " + b, msg));
          }
          function near(a, b, margin, msg) {
            if (Math.abs(a - b) > margin)
              throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg));
          }
          function eqPos(a, b, msg) {
            function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; }
            if (a == b) return;
            if (a == null) throw new Failure(label("comparing null to " + str(b), msg));
            if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg));
            if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg));
          }
          function is(a, msg) {
            if (!a) throw new Failure(label("assertion failed", msg));
          }
          
          function countTests() {
            if (!filters.length) return tests.length;
            var sum = 0;
            for (var i = 0; i < tests.length; ++i) {
              var name = tests[i].name;
              for (var j = 0; j < filters.length; j++) {
                if (name.match(filters[j])) {
                  ++sum;
                  break;
                }
              }
            }
            return sum;
          }
          
          function parseTestFilter(s) {
            if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i");
            else return new RegExp(s, "i");
          }
          
        • emacs_test.js
          (function() {
            "use strict";
          
            var Pos = CodeMirror.Pos;
            namespace = "emacs_";
          
            var eventCache = {};
            function fakeEvent(keyName) {
              var event = eventCache[key];
              if (event) return event;
          
              var ctrl, shift, alt;
              var key = keyName.replace(/\w+-/g, function(type) {
                if (type == "Ctrl-") ctrl = true;
                else if (type == "Alt-") alt = true;
                else if (type == "Shift-") shift = true;
                return "";
              });
              var code;
              for (var c in CodeMirror.keyNames)
                if (CodeMirror.keyNames[c] == key) { code = c; break; }
              if (c == null) throw new Error("Unknown key: " + key);
          
              return eventCache[keyName] = {
                type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt,
                preventDefault: function(){}, stopPropagation: function(){}
              };
            }
          
            function sim(name, start /*, actions... */) {
              var keys = Array.prototype.slice.call(arguments, 2);
              testCM(name, function(cm) {
                for (var i = 0; i < keys.length; ++i) {
                  var cur = keys[i];
                  if (cur instanceof Pos) cm.setCursor(cur);
                  else if (cur.call) cur(cm);
                  else cm.triggerOnKeyDown(fakeEvent(cur));
                }
              }, {keyMap: "emacs", value: start, mode: "javascript"});
            }
          
            function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; }
            function txt(str) { return function(cm) { eq(cm.getValue(), str); }; }
          
            sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1));
            sim("motionHMulti", "abcde",
                "Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2),
                "Ctrl-5", "Ctrl-B", at(0, 0));
          
            sim("motionHWord", "abc. def ghi",
                "Alt-F", at(0, 3), "Alt-F", at(0, 8),
                "Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0));
            sim("motionHWordMulti", "abc. def ghi ",
                "Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5),
                "Ctrl--", "Alt-B", at(0, 8));
          
            sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0));
            sim("motionVMulti", "a\nb\nc\nd\ne\n",
                "Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1),
                "Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1));
          
            sim("killYank", "abc\ndef\nghi",
                "Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y",
                txt("ahibc\ndef\ng"));
            sim("killRing", "abcdef",
                "Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W",
                "Ctrl-Y", "Alt-Y",
                txt("acdef"));
            sim("copyYank", "abcd",
                "Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y",
                txt("abcdabcd"));
          
            sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar"));
            sim("killLineEmptyLine", "foo\n  \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar"));
            sim("killLineMulti", "foo\nbar\nbaz",
                "Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y",
                txt("o\nbarfo\nbaz"));
          
            sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n",
                "Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0),
                "Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0),
                Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0));
            sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm",
                "Ctrl-U", "2", "Ctrl-Down", at(3, 0),
                "Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0));
          
            sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two",
                "Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13));
          
            sim("moveByExpr", "function foo(a, b) {}",
                "Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18),
                "Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9));
            sim("moveByExprMulti", "foo bar baz bug",
                "Ctrl-2", "Ctrl-Alt-F", at(0, 7),
                "Ctrl--", "Ctrl-Alt-F", at(0, 4),
                "Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11));
            sim("delExpr", "var x = [\n  a,\n  b\n  c\n];",
                Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/",
                Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;"));
            sim("delExprMulti", "foo bar baz",
                "Ctrl-2", "Ctrl-Alt-K", txt(" baz"),
                "Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo "));
          
            sim("justOneSpace", "hi      bye  ",
                Pos(0, 4), "Alt-Space", txt("hi bye  "),
                Pos(0, 4), "Alt-Space", txt("hi b ye  "),
                "Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye "));
          
            sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar"))
          
            sim("transposeChar", "abcd\ne",
                "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3),
                "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4),
                "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0));
          
            sim("manipWordCase", "foo BAR bAZ",
                "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),
                "Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz"));
            sim("manipWordCaseMulti", "foo Bar bAz",
                "Ctrl-2", "Alt-U", txt("FOO BAR bAz"),
                "Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz"));
          
            sim("upExpr", "foo {\n  bar[];\n  baz(blah);\n}",
                Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4));
            sim("transposeExpr", "do foo[bar] dah",
                Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah"));
          
            sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F",
                "Ctrl-G", "Ctrl-W", txt("abcde"));
          
            sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde"));
            sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde"));
          
            testCM("save", function(cm) {
              var saved = false;
              CodeMirror.commands.save = function(cm) { saved = cm.getValue(); };
              cm.triggerOnKeyDown(fakeEvent("Ctrl-X"));
              cm.triggerOnKeyDown(fakeEvent("Ctrl-S"));
              is(saved, "hi");
            }, {value: "hi", keyMap: "emacs"});
          })();
          
        • index.html
          <!doctype html>
          
          <meta charset="utf-8"/>
          <title>CodeMirror: Test Suite</title>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="mode_test.css">
          <script src="../doc/activebookmark.js"></script>
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/overlay.js"></script>
          <script src="../addon/mode/multiplex.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/hint/sql-hint.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <!-- clike must be after css or vim and sublime tests will fail -->
          <script src="../mode/gfm/gfm.js"></script>
          <script src="../mode/haml/haml.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/php/php.js"></script>
          <script src="../mode/ruby/ruby.js"></script>
          <script src="../mode/shell/shell.js"></script>
          <script src="../mode/slim/slim.js"></script>
          <script src="../mode/sql/sql.js"></script>
          <script src="../mode/stex/stex.js"></script>
          <script src="../mode/textile/textile.js"></script>
          <script src="../mode/verilog/verilog.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/xquery/xquery.js"></script>
          <script src="../keymap/emacs.js"></script>
          <script src="../keymap/sublime.js"></script>
          <script src="../keymap/vim.js"></script>
          
          <style type="text/css">
            .ok {color: #090;}
            .fail {color: #e00;}
            .error {color: #c90;}
            .done {font-weight: bold;}
            #progress {
            background: #45d;
            color: white;
            text-shadow: 0 0 1px #45d, 0 0 2px #45d, 0 0 3px #45d;
            font-weight: bold;
            white-space: pre;
            }
            #testground {
            visibility: hidden;
            }
            #testground.offscreen {
            visibility: visible;
            position: absolute;
            left: -10000px;
            top: -10000px;
            }
            .CodeMirror { border: 1px solid black; }
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Test suite</a>
            </ul>
          </div>
          
          <article>
            <h2>Test Suite</h2>
          
              <p>A limited set of programmatic sanity tests for CodeMirror.</p>
          
              <div style="border: 1px solid black; padding: 1px; max-width: 700px;">
                <div style="width: 0px;" id=progress><div style="padding: 3px;">Ran <span id="progress_ran">0</span><span id="progress_total"> of 0</span> tests</div></div>
              </div>
              <p id=status>Please enable JavaScript...</p>
              <div id=output></div>
          
              <div id=testground></div>
          
              <script src="driver.js"></script>
              <script src="test.js"></script>
              <script src="doc_test.js"></script>
              <script src="multi_test.js"></script>
              <script src="scroll_test.js"></script>
              <script src="comment_test.js"></script>
              <script src="search_test.js"></script>
              <script src="mode_test.js"></script>
          
              <script src="../mode/css/test.js"></script>
              <script src="../mode/css/scss_test.js"></script>
              <script src="../mode/css/less_test.js"></script>
              <script src="../mode/gfm/test.js"></script>
              <script src="../mode/haml/test.js"></script>
              <script src="../mode/javascript/test.js"></script>
              <script src="../mode/markdown/test.js"></script>
              <script src="../mode/php/test.js"></script>
              <script src="../mode/ruby/test.js"></script>
              <script src="../mode/shell/test.js"></script>
              <script src="../mode/slim/test.js"></script>
              <script src="../mode/stex/test.js"></script>
              <script src="../mode/textile/test.js"></script>
              <script src="../mode/verilog/test.js"></script>
              <script src="../mode/xml/test.js"></script>
              <script src="../mode/xquery/test.js"></script>
              <script src="../addon/mode/multiplex_test.js"></script>
              <script src="emacs_test.js"></script>
              <script src="sql-hint-test.js"></script>
              <script src="sublime_test.js"></script>
              <script src="vim_test.js"></script>
              <script>
                window.onload = runHarness;
                CodeMirror.on(window, 'hashchange', runHarness);
          
                function esc(str) {
                  return str.replace(/[<&]/, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
                }
          
                var output = document.getElementById("output"),
                    progress = document.getElementById("progress"),
                    progressRan = document.getElementById("progress_ran").childNodes[0],
                    progressTotal = document.getElementById("progress_total").childNodes[0];
                var count = 0,
                    failed = 0,
                    skipped = 0,
                    bad = "",
                    running = false, // Flag that states tests are running
                    quit = false, // Flag to quit tests ASAP
                    verbose = false; // Adds message for *every* test to output
          
                function runHarness(){
                  if (running) {
                    quit = true;
                    setStatus("Restarting tests...", '', true);
                    setTimeout(function(){runHarness();}, 500);
                    return;
                  }
                  filters = [];
                  verbose = false;
                  if (window.location.hash.substr(1)){
                    var strings = window.location.hash.substr(1).split(",");
                    while (strings.length) {
                      var s = strings.shift();
                      if (s === "verbose")
                        verbose = true;
                      else
                        filters.push(parseTestFilter(decodeURIComponent(s)));
                    }
                  }
                  quit = false;
                  running = true;
                  setStatus("Loading tests...");
                  count = 0;
                  failed = 0;
                  skipped = 0;
                  bad = "";
                  totalTests = countTests();
                  progressTotal.nodeValue = " of " + totalTests;
                  progressRan.nodeValue = count;
                  output.innerHTML = '';
                  document.getElementById("testground").innerHTML = "<form>" +
                    "<textarea id=\"code\" name=\"code\"></textarea>" +
                    "<input type=submit value=ok name=submit>" +
                    "</form>";
                  runTests(displayTest);
                }
          
                function setStatus(message, className, force){
                  if (quit && !force) return;
                  if (!message) throw("must provide message");
                  var status = document.getElementById("status").childNodes[0];
                  status.nodeValue = message;
                  status.parentNode.className = className;
                }
                function addOutput(name, className, code){
                  var newOutput = document.createElement("dl");
                  var newTitle = document.createElement("dt");
                  newTitle.className = className;
                  newTitle.appendChild(document.createTextNode(name));
                  newOutput.appendChild(newTitle);
                  var newMessage = document.createElement("dd");
                  newMessage.innerHTML = code;
                  newOutput.appendChild(newTitle);
                  newOutput.appendChild(newMessage);
                  output.appendChild(newOutput);
                }
                function displayTest(type, name, customMessage) {
                  var message = "???";
                  if (type != "done" && type != "skipped") ++count;
                  progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
                  progressRan.nodeValue = count;
                  if (type == "ok") {
                    message = "Test '" + name + "' succeeded";
                    if (!verbose) customMessage = false;
                  } else if (type == "skipped") {
                    message = "Test '" + name + "' skipped";
                    ++skipped;
                    if (!verbose) customMessage = false;
                  } else if (type == "expected") {
                    message = "Test '" + name + "' failed as expected";
                    if (!verbose) customMessage = false;
                  } else if (type == "error" || type == "fail") {
                    ++failed;
                    message = "Test '" + name + "' failed";
                  } else if (type == "done") {
                    if (failed) {
                      type += " fail";
                      message = failed + " failure" + (failed > 1 ? "s" : "");
                    } else if (count < totalTests) {
                      failed = totalTests - count;
                      type += " fail";
                      message = failed + " failure" + (failed > 1 ? "s" : "");
                    } else {
                      type += " ok";
                      message = "All passed";
                      if (skipped) {
                        message += " (" + skipped + " skipped)";
                      }
                    }
                    progressTotal.nodeValue = '';
                    customMessage = true; // Hack to avoid adding to output
                  }
                  if (verbose && !customMessage)  customMessage = message;
                  setStatus(message, type);
                  if (customMessage && customMessage.length > 0) {
                    addOutput(name, type, customMessage);
                  }
                }
              </script>
          
          </article>
          
        • lint.js
          var blint = require("blint");
          
          ["mode", "lib", "addon", "keymap"].forEach(function(dir) {
            blint.checkDir(dir, {
              browser: true,
              allowedGlobals: ["CodeMirror", "define", "test", "requirejs"],
              blob: "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http:\/\/codemirror.net\/LICENSE\n\n"
            });
          });
          
          module.exports = {ok: blint.success()};
          
        • mode_test.css
          .mt-output .mt-token {
            border: 1px solid #ddd;
            white-space: pre;
            font-family: "Consolas", monospace;
            text-align: center;
          }
          
          .mt-output .mt-style {
            font-size: x-small;
          }
          
          .mt-output .mt-state {
            font-size: x-small;
            vertical-align: top;
          }
          
          .mt-output .mt-state-row {
            display: none;
          }
          
          .mt-state-unhide .mt-output .mt-state-row {
            display: table-row;
          }
          
        • mode_test.js
          /**
           * Helper to test CodeMirror highlighting modes. It pretty prints output of the
           * highlighter and can check against expected styles.
           *
           * Mode tests are registered by calling test.mode(testName, mode,
           * tokens), where mode is a mode object as returned by
           * CodeMirror.getMode, and tokens is an array of lines that make up
           * the test.
           *
           * These lines are strings, in which styled stretches of code are
           * enclosed in brackets `[]`, and prefixed by their style. For
           * example, `[keyword if]`. Brackets in the code itself must be
           * duplicated to prevent them from being interpreted as token
           * boundaries. For example `a[[i]]` for `a[i]`. If a token has
           * multiple styles, the styles must be separated by ampersands, for
           * example `[tag&error </hmtl>]`.
           *
           * See the test.js files in the css, markdown, gfm, and stex mode
           * directories for examples.
           */
          (function() {
            function findSingle(str, pos, ch) {
              for (;;) {
                var found = str.indexOf(ch, pos);
                if (found == -1) return null;
                if (str.charAt(found + 1) != ch) return found;
                pos = found + 2;
              }
            }
          
            var styleName = /[\w&-_]+/g;
            function parseTokens(strs) {
              var tokens = [], plain = "";
              for (var i = 0; i < strs.length; ++i) {
                if (i) plain += "\n";
                var str = strs[i], pos = 0;
                while (pos < str.length) {
                  var style = null, text;
                  if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") {
                    styleName.lastIndex = pos + 1;
                    var m = styleName.exec(str);
                    style = m[0].replace(/&/g, " ");
                    var textStart = pos + style.length + 2;
                    var end = findSingle(str, textStart, "]");
                    if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style);
                    text = str.slice(textStart, end);
                    pos = end + 1;
                  } else {
                    var end = findSingle(str, pos, "[");
                    if (end == null) end = str.length;
                    text = str.slice(pos, end);
                    pos = end;
                  }
                  text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);});
                  tokens.push({style: style, text: text});
                  plain += text;
                }
              }
              return {tokens: tokens, plain: plain};
            }
          
            test.mode = function(name, mode, tokens, modeName) {
              var data = parseTokens(tokens);
              return test((modeName || mode.name) + "_" + name, function() {
                return compare(data.plain, data.tokens, mode);
              });
            };
          
            function esc(str) {
              return str.replace('&', '&amp;').replace('<', '&lt;').replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
          ;
            }
          
            function compare(text, expected, mode) {
          
              var expectedOutput = [];
              for (var i = 0; i < expected.length; ++i) {
                var sty = expected[i].style;
                if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
                expectedOutput.push({style: sty, text: expected[i].text});
              }
          
              var observedOutput = highlight(text, mode);
          
              var s = "";
              var diff = highlightOutputsDifferent(expectedOutput, observedOutput);
              if (diff != null) {
                s += '<div class="mt-test mt-fail">';
                s +=   '<pre>' + esc(text) + '</pre>';
                s +=   '<div class="cm-s-default">';
                s += 'expected:';
                s +=   prettyPrintOutputTable(expectedOutput, diff);
                s += 'observed: [<a onclick="this.parentElement.className+=\' mt-state-unhide\'">display states</a>]';
                s +=   prettyPrintOutputTable(observedOutput, diff);
                s +=   '</div>';
                s += '</div>';
              }
              if (observedOutput.indentFailures) {
                for (var i = 0; i < observedOutput.indentFailures.length; i++)
                  s += "<div class='mt-test mt-fail'>" + esc(observedOutput.indentFailures[i]) + "</div>";
              }
              if (s) throw new Failure(s);
            }
          
            function stringify(obj) {
              function replacer(key, obj) {
                if (typeof obj == "function") {
                  var m = obj.toString().match(/function\s*[^\s(]*/);
                  return m ? m[0] : "function";
                }
                return obj;
              }
              if (window.JSON && JSON.stringify)
                return JSON.stringify(obj, replacer, 2);
              return "[unsupported]";  // Fail safely if no native JSON.
            }
          
            function highlight(string, mode) {
              var state = mode.startState();
          
              var lines = string.replace(/\r\n/g,'\n').split('\n');
              var st = [], pos = 0;
              for (var i = 0; i < lines.length; ++i) {
                var line = lines[i], newLine = true;
                if (mode.indent) {
                  var ws = line.match(/^\s*/)[0];
                  var indent = mode.indent(state, line.slice(ws.length));
                  if (indent != CodeMirror.Pass && indent != ws.length)
                    (st.indentFailures || (st.indentFailures = [])).push(
                      "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")");
                }
                var stream = new CodeMirror.StringStream(line);
                if (line == "" && mode.blankLine) mode.blankLine(state);
                /* Start copied code from CodeMirror.highlight */
                while (!stream.eol()) {
                  for (var j = 0; j < 10 && stream.start >= stream.pos; j++)
                    var compare = mode.token(stream, state);
                  if (j == 10)
                    throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos);
                  var substr = stream.current();
                  if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
                  stream.start = stream.pos;
                  if (pos && st[pos-1].style == compare && !newLine) {
                    st[pos-1].text += substr;
                  } else if (substr) {
                    st[pos++] = {style: compare, text: substr, state: stringify(state)};
                  }
                  // Give up when line is ridiculously long
                  if (stream.pos > 5000) {
                    st[pos++] = {style: null, text: this.text.slice(stream.pos)};
                    break;
                  }
                  newLine = false;
                }
              }
          
              return st;
            }
          
            function highlightOutputsDifferent(o1, o2) {
              var minLen = Math.min(o1.length, o2.length);
              for (var i = 0; i < minLen; ++i)
                if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i;
              if (o1.length > minLen || o2.length > minLen) return minLen;
            }
          
            function prettyPrintOutputTable(output, diffAt) {
              var s = '<table class="mt-output">';
              s += '<tr>';
              for (var i = 0; i < output.length; ++i) {
                var style = output[i].style, val = output[i].text;
                s +=
                '<td class="mt-token"' + (i == diffAt * 2 ? " style='background: pink'" : "") + '>' +
                  '<span class="cm-' + esc(String(style)) + '">' +
                  esc(val.replace(/ /g,'\xb7')) +  // · MIDDLE DOT
                  '</span>' +
                  '</td>';
              }
              s += '</tr><tr>';
              for (var i = 0; i < output.length; ++i) {
                s += '<td class="mt-style"><span>' + (output[i].style || null) + '</span></td>';
              }
              if(output[0].state) {
                s += '</tr><tr class="mt-state-row" title="State AFTER each token">';
                for (var i = 0; i < output.length; ++i) {
                  s += '<td class="mt-state"><pre>' + esc(output[i].state) + '</pre></td>';
                }
              }
              s += '</tr></table>';
              return s;
            }
          })();
          
        • multi_test.js
          (function() {
            namespace = "multi_";
          
            function hasSelections(cm) {
              var sels = cm.listSelections();
              var given = (arguments.length - 1) / 4;
              if (sels.length != given)
                throw new Failure("expected " + given + " selections, found " + sels.length);
              for (var i = 0, p = 1; i < given; i++, p += 4) {
                var anchor = Pos(arguments[p], arguments[p + 1]);
                var head = Pos(arguments[p + 2], arguments[p + 3]);
                eqPos(sels[i].anchor, anchor, "anchor of selection " + i);
                eqPos(sels[i].head, head, "head of selection " + i);
              }
            }
            function hasCursors(cm) {
              var sels = cm.listSelections();
              var given = (arguments.length - 1) / 2;
              if (sels.length != given)
                throw new Failure("expected " + given + " selections, found " + sels.length);
              for (var i = 0, p = 1; i < given; i++, p += 2) {
                eqPos(sels[i].anchor, sels[i].head, "something selected for " + i);
                var head = Pos(arguments[p], arguments[p + 1]);
                eqPos(sels[i].head, head, "selection " + i);
              }
            }
          
            testCM("getSelection", function(cm) {
              select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, {anchor: Pos(2, 2), head: Pos(2, 0)});
              eq(cm.getSelection(), "1234\n56\n90");
              eq(cm.getSelection(false).join("|"), "1234|56|90");
              eq(cm.getSelections().join("|"), "1234\n56|90");
            }, {value: "1234\n5678\n90"});
          
            testCM("setSelection", function(cm) {
              select(cm, Pos(3, 0), Pos(0, 0), {anchor: Pos(2, 5), head: Pos(1, 0)});
              hasSelections(cm, 0, 0, 0, 0,
                            2, 5, 1, 0,
                            3, 0, 3, 0);
              cm.setSelection(Pos(1, 2), Pos(1, 1));
              hasSelections(cm, 1, 2, 1, 1);
              select(cm, {anchor: Pos(1, 1), head: Pos(2, 4)},
                     {anchor: Pos(0, 0), head: Pos(1, 3)},
                     Pos(3, 0), Pos(2, 2));
              hasSelections(cm, 0, 0, 2, 4,
                            3, 0, 3, 0);
              cm.setSelections([{anchor: Pos(0, 1), head: Pos(0, 2)},
                                {anchor: Pos(1, 1), head: Pos(1, 2)},
                                {anchor: Pos(2, 1), head: Pos(2, 2)}], 1);
              eqPos(cm.getCursor("head"), Pos(1, 2));
              eqPos(cm.getCursor("anchor"), Pos(1, 1));
              eqPos(cm.getCursor("from"), Pos(1, 1));
              eqPos(cm.getCursor("to"), Pos(1, 2));
              cm.setCursor(Pos(1, 1));
              hasCursors(cm, 1, 1);
            }, {value: "abcde\nabcde\nabcde\n"});
          
            testCM("somethingSelected", function(cm) {
              select(cm, Pos(0, 1), {anchor: Pos(0, 3), head: Pos(0, 5)});
              eq(cm.somethingSelected(), true);
              select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5));
              eq(cm.somethingSelected(), false);
            }, {value: "123456789"});
          
            testCM("extendSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1), Pos(2, 1));
              cm.setExtending(true);
              cm.extendSelections([Pos(0, 2), Pos(1, 0), Pos(2, 3)]);
              hasSelections(cm, 0, 1, 0, 2,
                            1, 1, 1, 0,
                            2, 1, 2, 3);
              cm.extendSelection(Pos(2, 4), Pos(2, 0));
              hasSelections(cm, 2, 4, 2, 0);
            }, {value: "1234\n1234\n1234"});
          
            testCM("addSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.addSelection(Pos(0, 0), Pos(0, 4));
              hasSelections(cm, 0, 0, 0, 4,
                            1, 1, 1, 1);
              cm.addSelection(Pos(2, 2));
              hasSelections(cm, 0, 0, 0, 4,
                            1, 1, 1, 1,
                            2, 2, 2, 2);
            }, {value: "1234\n1234\n1234"});
          
            testCM("replaceSelection", function(cm) {
              var selections = [{anchor: Pos(0, 0), head: Pos(0, 1)},
                                {anchor: Pos(0, 2), head: Pos(0, 3)},
                                {anchor: Pos(0, 4), head: Pos(0, 5)},
                                {anchor: Pos(2, 1), head: Pos(2, 4)},
                                {anchor: Pos(2, 5), head: Pos(2, 6)}];
              var val = "123456\n123456\n123456";
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("ab", "around");
              eq(cm.getValue(), "ab2ab4ab6\n123456\n1ab5ab");
              hasSelections(cm, 0, 0, 0, 2,
                            0, 3, 0, 5,
                            0, 6, 0, 8,
                            2, 1, 2, 3,
                            2, 4, 2, 6);
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("", "around");
              eq(cm.getValue(), "246\n123456\n15");
              hasSelections(cm, 0, 0, 0, 0,
                            0, 1, 0, 1,
                            0, 2, 0, 2,
                            2, 1, 2, 1,
                            2, 2, 2, 2);
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("X\nY\nZ", "around");
              hasSelections(cm, 0, 0, 2, 1,
                            2, 2, 4, 1,
                            4, 2, 6, 1,
                            8, 1, 10, 1,
                            10, 2, 12, 1);
              cm.replaceSelection("a", "around");
              hasSelections(cm, 0, 0, 0, 1,
                            0, 2, 0, 3,
                            0, 4, 0, 5,
                            2, 1, 2, 2,
                            2, 3, 2, 4);
              cm.replaceSelection("xy", "start");
              hasSelections(cm, 0, 0, 0, 0,
                            0, 3, 0, 3,
                            0, 6, 0, 6,
                            2, 1, 2, 1,
                            2, 4, 2, 4);
              cm.replaceSelection("z\nf");
              hasSelections(cm, 1, 1, 1, 1,
                            2, 1, 2, 1,
                            3, 1, 3, 1,
                            6, 1, 6, 1,
                            7, 1, 7, 1);
              eq(cm.getValue(), "z\nfxy2z\nfxy4z\nfxy6\n123456\n1z\nfxy5z\nfxy");
            });
          
            function select(cm) {
              var sels = [];
              for (var i = 1; i < arguments.length; i++) {
                var arg = arguments[i];
                if (arg.head) sels.push(arg);
                else sels.push({head: arg, anchor: arg});
              }
              cm.setSelections(sels, sels.length - 1);
            }
          
            testCM("indentSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.indentSelection(4);
              eq(cm.getValue(), "    foo\n    bar\nbaz");
          
              select(cm, Pos(0, 2), Pos(0, 3), Pos(0, 4));
              cm.indentSelection(-2);
              eq(cm.getValue(), "  foo\n    bar\nbaz");
          
              select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)},
                     {anchor: Pos(1, 3), head: Pos(2, 0)});
              cm.indentSelection(-2);
              eq(cm.getValue(), "foo\n  bar\nbaz");
            }, {value: "foo\nbar\nbaz"});
          
            testCM("killLine", function(cm) {
              select(cm, Pos(0, 1), Pos(0, 2), Pos(1, 1));
              cm.execCommand("killLine");
              eq(cm.getValue(), "f\nb\nbaz");
              cm.execCommand("killLine");
              eq(cm.getValue(), "fbbaz");
              cm.setValue("foo\nbar\nbaz");
              select(cm, Pos(0, 1), {anchor: Pos(0, 2), head: Pos(2, 1)});
              cm.execCommand("killLine");
              eq(cm.getValue(), "faz");
            }, {value: "foo\nbar\nbaz"});
          
            testCM("deleteLine", function(cm) {
              select(cm, Pos(0, 0),
                     {head: Pos(0, 1), anchor: Pos(2, 0)},
                     Pos(4, 0));
              cm.execCommand("deleteLine");
              eq(cm.getValue(), "4\n6\n7");
              select(cm, Pos(2, 1));
              cm.execCommand("deleteLine");
              eq(cm.getValue(), "4\n6\n");
            }, {value: "1\n2\n3\n4\n5\n6\n7"});
          
            testCM("deleteH", function(cm) {
              select(cm, Pos(0, 4), {anchor: Pos(1, 4), head: Pos(1, 5)});
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "foo bar baz\nabc ef ghi\n");
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "foo  baz\nabc  ghi\n");
              cm.execCommand("delCharBefore");
              cm.execCommand("delCharBefore");
              eq(cm.getValue(), "fo baz\nab ghi\n");
              select(cm, Pos(0, 3), Pos(0, 4), Pos(0, 5));
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "fo \nab ghi\n");
            }, {value: "foo bar baz\nabc def ghi\n"});
          
            testCM("goLineStart", function(cm) {
              select(cm, Pos(0, 2), Pos(0, 3), Pos(1, 1));
              cm.execCommand("goLineStart");
              hasCursors(cm, 0, 0, 1, 0);
              select(cm, Pos(1, 1), Pos(0, 1));
              cm.setExtending(true);
              cm.execCommand("goLineStart");
              hasSelections(cm, 0, 1, 0, 0,
                            1, 1, 1, 0);
            }, {value: "foo\nbar\nbaz"});
          
            testCM("moveV", function(cm) {
              select(cm, Pos(0, 2), Pos(1, 2));
              cm.execCommand("goLineDown");
              hasCursors(cm, 1, 2, 2, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 2, 1, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 0, 0, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 0);
              select(cm, Pos(0, 2), Pos(1, 2));
              cm.setExtending(true);
              cm.execCommand("goLineDown");
              hasSelections(cm, 0, 2, 2, 2);
            }, {value: "12345\n12345\n12345"});
          
            testCM("moveH", function(cm) {
              select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5), Pos(2, 3));
              cm.execCommand("goCharRight");
              hasCursors(cm, 0, 2, 0, 4, 1, 0, 2, 4);
              cm.execCommand("goCharLeft");
              hasCursors(cm, 0, 1, 0, 3, 0, 5, 2, 3);
              for (var i = 0; i < 15; i++)
                cm.execCommand("goCharRight");
              hasCursors(cm, 2, 4, 2, 5);
            }, {value: "12345\n12345\n12345"});
          
            testCM("newlineAndIndent", function(cm) {
              select(cm, Pos(0, 5), Pos(1, 5));
              cm.execCommand("newlineAndIndent");
              hasCursors(cm, 1, 2, 3, 2);
              eq(cm.getValue(), "x = [\n  1];\ny = [\n  2];");
              cm.undo();
              eq(cm.getValue(), "x = [1];\ny = [2];");
              hasCursors(cm, 0, 5, 1, 5);
              select(cm, Pos(0, 5), Pos(0, 6));
              cm.execCommand("newlineAndIndent");
              hasCursors(cm, 1, 2, 2, 0);
              eq(cm.getValue(), "x = [\n  1\n];\ny = [2];");
            }, {value: "x = [1];\ny = [2];", mode: "javascript"});
          
            testCM("goDocStartEnd", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.execCommand("goDocStart");
              hasCursors(cm, 0, 0);
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.execCommand("goDocEnd");
              hasCursors(cm, 1, 3);
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.setExtending(true);
              cm.execCommand("goDocEnd");
              hasSelections(cm, 1, 1, 1, 3);
            }, {value: "abc\ndef"});
          
            testCM("selectionHistory", function(cm) {
              for (var i = 0; i < 3; ++i)
                cm.addSelection(Pos(0, i * 2), Pos(0, i * 2 + 1));
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "1\n2");
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "1");
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "");
              eqPos(cm.getCursor(), Pos(0, 0));
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1");
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1\n2");
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1\n2\n3");
            }, {value: "1 2 3"});
          })();
          
        • phantom_driver.js
          var page = require('webpage').create();
          
          page.open("http://localhost:3000/test/index.html", function (status) {
            if (status != "success") {
              console.log("page couldn't be loaded successfully");
              phantom.exit(1);
            }
            waitFor(function () {
              return page.evaluate(function () {
                var output = document.getElementById('status');
                if (!output) { return false; }
                return (/^(\d+ failures?|all passed)/i).test(output.innerText);
              });
            }, function () {
              var failed = page.evaluate(function () { return window.failed; });
              var output = page.evaluate(function () {
                return document.getElementById('output').innerText + "\n" +
                  document.getElementById('status').innerText;
              });
              console.log(output);
              phantom.exit(failed > 0 ? 1 : 0);
            });
          });
          
          function waitFor (test, cb) {
            if (test()) {
              cb();
            } else {
              setTimeout(function () { waitFor(test, cb); }, 250);
            }
          }
          
        • run.js
          #!/usr/bin/env node
          
          var ok = require("./lint").ok;
          
          var files = new (require('node-static').Server)();
          
          var server = require('http').createServer(function (req, res) {
            req.addListener('end', function () {
              files.serve(req, res, function (err/*, result */) {
                if (err) {
                  console.error(err);
                  process.exit(1);
                }
              });
            }).resume();
          }).addListener('error', function (err) {
            throw err;
          }).listen(3000, function () {
            var childProcess = require('child_process');
            var phantomjs = require("phantomjs");
            var childArgs = [
              require("path").join(__dirname, 'phantom_driver.js')
            ];
            childProcess.execFile(phantomjs.path, childArgs, function (err, stdout, stderr) {
              server.close();
              console.log(stdout);
              if (err) console.error(err);
              if (stderr) console.error(stderr);
              process.exit(err || stderr || !ok ? 1 : 0);
            });
          });
          
        • scroll_test.js
          (function() {
            "use strict";
          
            namespace = "scroll_";
          
            testCM("bars_hidden", function(cm) {
              for (var i = 0;; i++) {
                var wrapBox = cm.getWrapperElement().getBoundingClientRect();
                var scrollBox = cm.getScrollerElement().getBoundingClientRect();
                is(wrapBox.bottom < scrollBox.bottom - 10);
                is(wrapBox.right < scrollBox.right - 10);
                if (i == 1) break;
                cm.getWrapperElement().style.height = "auto";
                cm.refresh();
              }
            });
            
            function barH(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; }
            function barV(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-vscrollbar")[0]; }
          
            function displayBottom(cm, scrollbar) {
              if (scrollbar)
                return barH(cm).getBoundingClientRect().top;
              else
                return cm.getWrapperElement().getBoundingClientRect().bottom - 1;
            }
          
            function displayRight(cm, scrollbar) {
              if (scrollbar)
                return barV(cm).getBoundingClientRect().left;
              else
                return cm.getWrapperElement().getBoundingClientRect().right - 1;
            }
          
            function testMovedownFixed(cm, hScroll) {
              cm.setSize("100px", "100px");
              if (hScroll) cm.setValue(new Array(100).join("x"));
              var bottom = displayBottom(cm, hScroll);
              for (var i = 0; i < 30; i++) {
                cm.replaceSelection("x\n");
                var cursorBottom = cm.cursorCoords(null, "window").bottom;
                is(cursorBottom <= bottom);
              }
              is(cursorBottom >= bottom - 5);
            }
          
            testCM("movedown_fixed", function(cm) {testMovedownFixed(cm, false);});
            testCM("movedown_hscroll_fixed", function(cm) {testMovedownFixed(cm, true);});
          
            function testMovedownResize(cm, hScroll) {
              cm.getWrapperElement().style.height = "auto";
              if (hScroll) cm.setValue(new Array(100).join("x"));
              cm.refresh();
              for (var i = 0; i < 30; i++) {
                cm.replaceSelection("x\n");
                var bottom = displayBottom(cm, hScroll);
                var cursorBottom = cm.cursorCoords(null, "window").bottom;
                is(cursorBottom <= bottom);
                is(cursorBottom >= bottom - 5);
              }
            }
          
            testCM("movedown_resize", function(cm) {testMovedownResize(cm, false);});
            testCM("movedown_hscroll_resize", function(cm) {testMovedownResize(cm, true);});
          
            function testMoveright(cm, wrap, scroll) {
              cm.setSize("100px", "100px");
              if (wrap) cm.setOption("lineWrapping", true);
              if (scroll) {
                cm.setValue("\n" + new Array(100).join("x\n"));
                cm.setCursor(Pos(0, 0));
              }
              var right = displayRight(cm, scroll);
              for (var i = 0; i < 10; i++) {
                cm.replaceSelection("xxxxxxxxxx");
                var cursorRight = cm.cursorCoords(null, "window").right;
                is(cursorRight < right);
              }
              if (!wrap) is(cursorRight > right - 20);
            }
          
            testCM("moveright", function(cm) {testMoveright(cm, false, false);});
            testCM("moveright_wrap", function(cm) {testMoveright(cm, true, false);});
            testCM("moveright_scroll", function(cm) {testMoveright(cm, false, true);});
            testCM("moveright_scroll_wrap", function(cm) {testMoveright(cm, true, true);});
          
            testCM("suddenly_wide", function(cm) {
              addDoc(cm, 100, 100);
              cm.replaceSelection(new Array(600).join("l ") + "\n");
              cm.execCommand("goLineUp");
              cm.execCommand("goLineEnd");
              is(barH(cm).scrollLeft > cm.getScrollerElement().scrollLeft - 1);
            });
          
            testCM("wrap_changes_height", function(cm) {
              var line = new Array(20).join("a ") + "\n";
              cm.setValue(new Array(20).join(line));
              var box = cm.getWrapperElement().getBoundingClientRect();
              cm.setSize(cm.cursorCoords(Pos(0), "window").right - box.left + 2,
                         cm.cursorCoords(Pos(19, 0), "window").bottom - box.top + 2);
              cm.setCursor(Pos(19, 0));
              cm.replaceSelection("\n");
              is(cm.cursorCoords(null, "window").bottom < displayBottom(cm, false));
            }, {lineWrapping: true});
          })();
          
        • search_test.js
          (function() {
            "use strict";
          
            function test(name) {
              var text = Array.prototype.slice.call(arguments, 1, arguments.length - 1).join("\n");
              var body = arguments[arguments.length - 1];
              return window.test("search_" + name, function() {
                body(new CodeMirror.Doc(text));
              });
            }
          
            function run(doc, query, insensitive) {
              var cursor = doc.getSearchCursor(query, null, insensitive);
              for (var i = 3; i < arguments.length; i += 4) {
                var found = cursor.findNext();
                is(found, "not enough results (forward)");
                eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, forward, " + (i - 3) / 4);
                eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, forward, " + (i - 3) / 4);
              }
              is(!cursor.findNext(), "too many matches (forward)");
              for (var i = arguments.length - 4; i >= 3; i -= 4) {
                var found = cursor.findPrevious();
                is(found, "not enough results (backwards)");
                eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, backwards, " + (i - 3) / 4);
                eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, backwards, " + (i - 3) / 4);
              }
              is(!cursor.findPrevious(), "too many matches (backwards)");
            }
          
            test("simple", "abcdefg", "abcdefg", function(doc) {
              run(doc, "cde", false, 0, 2, 0, 5, 1, 2, 1, 5);
            });
          
            test("multiline", "hallo", "goodbye", function(doc) {
              run(doc, "llo\ngoo", false, 0, 2, 1, 3);
              run(doc, "blah\nhall", false);
              run(doc, "bye\neye", false);
            });
          
            test("regexp", "abcde", "abcde", function(doc) {
              run(doc, /bcd/, false, 0, 1, 0, 4, 1, 1, 1, 4);
              run(doc, /BCD/, false);
              run(doc, /BCD/i, false, 0, 1, 0, 4, 1, 1, 1, 4);
            });
          
            test("insensitive", "hallo", "HALLO", "oink", "hAllO", function(doc) {
              run(doc, "All", false, 3, 1, 3, 4);
              run(doc, "All", true, 0, 1, 0, 4, 1, 1, 1, 4, 3, 1, 3, 4);
            });
          
            test("multilineInsensitive", "zie ginds komT", "De Stoomboot", "uit Spanje weer aan", function(doc) {
              run(doc, "komt\nde stoomboot\nuit", false);
              run(doc, "komt\nde stoomboot\nuit", true, 0, 10, 2, 3);
              run(doc, "kOMt\ndE stOOmboot\nuiT", true, 0, 10, 2, 3);
            });
          
            test("expandingCaseFold", "<b>İİ İİ</b>", "<b>uu uu</b>", function(doc) {
              if (phantom) return; // A Phantom bug makes this hang
              run(doc, "</b>", true, 0, 8, 0, 12, 1, 8, 1, 12);
              run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8);
            });
          })();
          
        • sql-hint-test.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          (function() {
            var Pos = CodeMirror.Pos;
          
            var simpleTables = {
              "users": ["name", "score", "birthDate"],
              "xcountries": ["name", "population", "size"]
            };
          
            var schemaTables = {
              "schema.users": ["name", "score", "birthDate"],
              "schema.countries": ["name", "population", "size"]
            };
          
            var displayTextTables = [{
              text: "mytable",
              displayText: "mytable | The main table",
              columns: [{text: "id", displayText: "id | Unique ID"},
                        {text: "name", displayText: "name | The name"}]
            }];
          
            namespace = "sql-hint_";
          
            function test(name, spec) {
              testCM(name, function(cm) {
                cm.setValue(spec.value);
                cm.setCursor(spec.cursor);
                var completion = CodeMirror.hint.sql(cm, {tables: spec.tables});
                if (!deepCompare(completion.list, spec.list))
                  throw new Failure("Wrong completion results " + JSON.stringify(completion.list) + " vs " + JSON.stringify(spec.list));
                eqPos(completion.from, spec.from);
                eqPos(completion.to, spec.to);
              }, {
                value: spec.value,
                mode: "text/x-mysql"
              });
            }
          
            test("keywords", {
              value: "SEL",
              cursor: Pos(0, 3),
              list: ["SELECT"],
              from: Pos(0, 0),
              to: Pos(0, 3)
            });
          
            test("from", {
              value: "SELECT * fr",
              cursor: Pos(0, 11),
              list: ["FROM"],
              from: Pos(0, 9),
              to: Pos(0, 11)
            });
          
            test("table", {
              value: "SELECT xc",
              cursor: Pos(0, 9),
              tables: simpleTables,
              list: ["xcountries"],
              from: Pos(0, 7),
              to: Pos(0, 9)
            });
          
            test("columns", {
              value: "SELECT users.",
              cursor: Pos(0, 13),
              tables: simpleTables,
              list: ["users.name", "users.score", "users.birthDate"],
              from: Pos(0, 7),
              to: Pos(0, 13)
            });
          
            test("singlecolumn", {
              value: "SELECT users.na",
              cursor: Pos(0, 15),
              tables: simpleTables,
              list: ["users.name"],
              from: Pos(0, 7),
              to: Pos(0, 15)
            });
          
            test("quoted", {
              value: "SELECT `users`.`na",
              cursor: Pos(0, 18),
              tables: simpleTables,
              list: ["`users`.`name`"],
              from: Pos(0, 7),
              to: Pos(0, 18)
            });
          
            test("quotedcolumn", {
              value: "SELECT users.`na",
              cursor: Pos(0, 16),
              tables: simpleTables,
              list: ["`users`.`name`"],
              from: Pos(0, 7),
              to: Pos(0, 16)
            });
          
            test("schema", {
              value: "SELECT schem",
              cursor: Pos(0, 12),
              tables: schemaTables,
              list: ["schema.users", "schema.countries",
                     "SCHEMA", "SCHEMA_NAME", "SCHEMAS"],
              from: Pos(0, 7),
              to: Pos(0, 12)
            });
          
            test("schemaquoted", {
              value: "SELECT `sch",
              cursor: Pos(0, 11),
              tables: schemaTables,
              list: ["`schema`.`users`", "`schema`.`countries`"],
              from: Pos(0, 7),
              to: Pos(0, 11)
            });
          
            test("schemacolumn", {
              value: "SELECT schema.users.",
              cursor: Pos(0, 20),
              tables: schemaTables,
              list: ["schema.users.name",
                     "schema.users.score",
                     "schema.users.birthDate"],
              from: Pos(0, 7),
              to: Pos(0, 20)
            });
          
            test("schemacolumnquoted", {
              value: "SELECT `schema`.`users`.",
              cursor: Pos(0, 24),
              tables: schemaTables,
              list: ["`schema`.`users`.`name`",
                     "`schema`.`users`.`score`",
                     "`schema`.`users`.`birthDate`"],
              from: Pos(0, 7),
              to: Pos(0, 24)
            });
          
            test("displayText_table", {
              value: "SELECT myt",
              cursor: Pos(0, 10),
              tables: displayTextTables,
              list: displayTextTables,
              from: Pos(0, 7),
              to: Pos(0, 10)
            });
          
            test("displayText_column", {
              value: "SELECT mytable.",
              cursor: Pos(0, 15),
              tables: displayTextTables,
              list: [{text: "mytable.id", displayText: "id | Unique ID"},
                     {text: "mytable.name", displayText: "name | The name"}],
              from: Pos(0, 7),
              to: Pos(0, 15)
            });
          
            function deepCompare(a, b) {
              if (!a || typeof a != "object")
                return a === b;
              if (!b || typeof b != "object")
                return false;
              for (var prop in a) if (!deepCompare(a[prop], b[prop])) return false;
              return true;
            }
          })();
          
        • sublime_test.js
          (function() {
            "use strict";
            
            var Pos = CodeMirror.Pos;
            namespace = "sublime_";
          
            function stTest(name) {
              var actions = Array.prototype.slice.call(arguments, 1);
              testCM(name, function(cm) {
                for (var i = 0; i < actions.length; i++) {
                  var action = actions[i];
                  if (typeof action == "string" && i == 0)
                    cm.setValue(action);
                  else if (typeof action == "string")
                    cm.execCommand(action);
                  else if (action instanceof Pos)
                    cm.setCursor(action);
                  else
                    action(cm);
                }
              });
            }
          
            function at(line, ch, msg) {
              return function(cm) {
                eq(cm.listSelections().length, 1);
                eqPos(cm.getCursor("head"), Pos(line, ch), msg);
                eqPos(cm.getCursor("anchor"), Pos(line, ch), msg);
              };
            }
          
            function val(content, msg) {
              return function(cm) { eq(cm.getValue(), content, msg); };
            }
          
            function argsToRanges(args) {
              if (args.length % 4) throw new Error("Wrong number of arguments for ranges.");
              var ranges = [];
              for (var i = 0; i < args.length; i += 4)
                ranges.push({anchor: Pos(args[i], args[i + 1]),
                             head: Pos(args[i + 2], args[i + 3])});
              return ranges;
            }
          
            function setSel() {
              var ranges = argsToRanges(arguments);
              return function(cm) { cm.setSelections(ranges, 0); };
            }
          
            function hasSel() {
              var ranges = argsToRanges(arguments);
              return function(cm) {
                var sels = cm.listSelections();
                if (sels.length != ranges.length)
                  throw new Failure("Expected " + ranges.length + " selections, but found " + sels.length);
                for (var i = 0; i < sels.length; i++) {
                  eqPos(sels[i].anchor, ranges[i].anchor, "anchor " + i);
                  eqPos(sels[i].head, ranges[i].head, "head " + i);
                }
              };
            }
          
            stTest("bySubword", "the foo_bar DooDahBah \n a",
                   "goSubwordLeft", at(0, 0),
                   "goSubwordRight", at(0, 3),
                   "goSubwordRight", at(0, 7),
                   "goSubwordRight", at(0, 11),
                   "goSubwordRight", at(0, 15),
                   "goSubwordRight", at(0, 18),
                   "goSubwordRight", at(0, 21),
                   "goSubwordRight", at(0, 22),
                   "goSubwordRight", at(1, 0),
                   "goSubwordRight", at(1, 2),
                   "goSubwordRight", at(1, 2),
                   "goSubwordLeft", at(1, 1),
                   "goSubwordLeft", at(1, 0),
                   "goSubwordLeft", at(0, 22),
                   "goSubwordLeft", at(0, 18),
                   "goSubwordLeft", at(0, 15),
                   "goSubwordLeft", at(0, 12),
                   "goSubwordLeft", at(0, 8),
                   "goSubwordLeft", at(0, 4),
                   "goSubwordLeft", at(0, 0));
          
            stTest("splitSelectionByLine", "abc\ndef\nghi",
                   setSel(0, 1, 2, 2),
                   "splitSelectionByLine",
                   hasSel(0, 1, 0, 3,
                          1, 0, 1, 3,
                          2, 0, 2, 2));
          
            stTest("splitSelectionByLineMulti", "abc\ndef\nghi\njkl",
                   setSel(0, 1, 1, 1,
                          1, 2, 3, 2,
                          3, 3, 3, 3),
                   "splitSelectionByLine",
                   hasSel(0, 1, 0, 3,
                          1, 0, 1, 1,
                          1, 2, 1, 3,
                          2, 0, 2, 3,
                          3, 0, 3, 2,
                          3, 3, 3, 3));
          
            stTest("selectLine", "abc\ndef\nghi",
                   setSel(0, 1, 0, 1,
                          2, 0, 2, 1),
                   "selectLine",
                   hasSel(0, 0, 1, 0,
                          2, 0, 2, 3),
                   setSel(0, 1, 1, 0),
                   "selectLine",
                   hasSel(0, 0, 2, 0));
          
            stTest("insertLineAfter", "abcde\nfghijkl\nmn",
                   setSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 2, 1, 2,
                          1, 3, 1, 5), "insertLineAfter",
                   hasSel(1, 0, 1, 0,
                          3, 0, 3, 0), val("abcde\n\nfghijkl\n\nmn"));
          
            stTest("insertLineBefore", "abcde\nfghijkl\nmn",
                   setSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 2, 1, 2,
                          1, 3, 1, 5), "insertLineBefore",
                   hasSel(0, 0, 0, 0,
                          2, 0, 2, 0), val("\nabcde\n\nfghijkl\nmn"));
          
            stTest("selectNextOccurrence", "a foo bar\nfoobar foo",
                   setSel(0, 2, 0, 5),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3,
                                                  1, 7, 1, 10),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3,
                                                  1, 7, 1, 10),
                   Pos(0, 3), "selectNextOccurrence", hasSel(0, 2, 0, 5),
                  "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                 1, 7, 1, 10),
                   setSel(0, 6, 0, 9),
                   "selectNextOccurrence", hasSel(0, 6, 0, 9,
                                                  1, 3, 1, 6));
          
            stTest("selectScope", "foo(a) {\n  bar[1, 2];\n}",
                   "selectScope", hasSel(0, 0, 2, 1),
                   Pos(0, 4), "selectScope", hasSel(0, 4, 0, 5),
                   Pos(0, 5), "selectScope", hasSel(0, 4, 0, 5),
                   Pos(0, 6), "selectScope", hasSel(0, 0, 2, 1),
                   Pos(0, 8), "selectScope", hasSel(0, 8, 2, 0),
                   Pos(1, 2), "selectScope", hasSel(0, 8, 2, 0),
                   Pos(1, 6), "selectScope", hasSel(1, 6, 1, 10),
                   Pos(1, 9), "selectScope", hasSel(1, 6, 1, 10));
          
            stTest("goToBracket", "foo(a) {\n  bar[1, 2];\n}",
                   Pos(0, 0), "goToBracket", at(0, 0),
                   Pos(0, 4), "goToBracket", at(0, 5), "goToBracket", at(0, 4),
                   Pos(0, 8), "goToBracket", at(2, 0), "goToBracket", at(0, 8),
                   Pos(1, 2), "goToBracket", at(2, 0),
                   Pos(1, 7), "goToBracket", at(1, 10), "goToBracket", at(1, 6));
          
            stTest("swapLine", "1\n2\n3---\n4\n5",
                   "swapLineDown", val("2\n1\n3---\n4\n5"),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   Pos(4, 1), "swapLineDown", val("1\n2\n3---\n4\n5"),
                   setSel(0, 1, 0, 1,
                          1, 0, 2, 0,
                          2, 2, 2, 2),
                   "swapLineDown", val("4\n1\n2\n3---\n5"),
                   hasSel(1, 1, 1, 1,
                          2, 0, 3, 0,
                          3, 2, 3, 2),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   hasSel(0, 1, 0, 1,
                          1, 0, 2, 0,
                          2, 2, 2, 2));
          
            stTest("swapLineEmptyBottomSel", "1\n2\n3",
                   setSel(0, 1, 1, 0),
                   "swapLineDown", val("2\n1\n3"), hasSel(1, 1, 2, 0),
                   "swapLineUp", val("1\n2\n3"), hasSel(0, 1, 1, 0),
                   "swapLineUp", val("1\n2\n3"), hasSel(0, 0, 0, 0));
          
            stTest("swapLineUpFromEnd", "a\nb\nc",
                   Pos(2, 1), "swapLineUp",
                   hasSel(1, 1, 1, 1), val("a\nc\nb"));
          
            stTest("joinLines", "abc\ndef\nghi\njkl",
                   "joinLines", val("abc def\nghi\njkl"), at(0, 4),
                   "undo",
                   setSel(0, 2, 1, 1), "joinLines",
                   val("abc def ghi\njkl"), hasSel(0, 2, 0, 8),
                   "undo",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 1,
                          3, 1, 3, 1), "joinLines",
                   val("abc def ghi\njkl"), hasSel(0, 4, 0, 4,
                                                   0, 8, 0, 8,
                                                   1, 3, 1, 3));
          
            stTest("duplicateLine", "abc\ndef\nghi",
                   Pos(1, 0), "duplicateLine", val("abc\ndef\ndef\nghi"), at(2, 0),
                   "undo",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 1,
                          2, 1, 2, 1), "duplicateLine",
                   val("abc\nabc\ndef\ndef\nghi\nghi"), hasSel(1, 1, 1, 1,
                                                               3, 1, 3, 1,
                                                               5, 1, 5, 1));
            stTest("duplicateLineSelection", "abcdef",
                   setSel(0, 1, 0, 1,
                          0, 2, 0, 4,
                          0, 5, 0, 5),
                   "duplicateLine",
                   val("abcdef\nabcdcdef\nabcdcdef"), hasSel(2, 1, 2, 1,
                                                             2, 4, 2, 6,
                                                             2, 7, 2, 7));
          
            stTest("selectLinesUpward", "123\n345\n789\n012",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0),
                   "selectLinesUpward",
                   hasSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 0, 1, 0,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0));
          
            stTest("selectLinesDownward", "123\n345\n789\n012",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0),
                   "selectLinesDownward",
                   hasSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          2, 3, 2, 3,
                          3, 0, 3, 0));
          
            stTest("sortLines", "c\nb\na\nC\nB\nA",
                   "sortLines", val("A\nB\nC\na\nb\nc"),
                   "undo",
                   setSel(0, 0, 2, 0,
                          3, 0, 5, 0),
                   "sortLines", val("a\nb\nc\nA\nB\nC"),
                   hasSel(0, 0, 2, 1,
                          3, 0, 5, 1),
                   "undo",
                   setSel(1, 0, 4, 0), "sortLinesInsensitive", val("c\na\nB\nb\nC\nA"));
          
            stTest("bookmarks", "abc\ndef\nghi\njkl",
                   Pos(0, 1), "toggleBookmark",
                   setSel(1, 1, 1, 2), "toggleBookmark",
                   setSel(2, 1, 2, 2), "toggleBookmark",
                   "nextBookmark", hasSel(0, 1, 0, 1),
                   "nextBookmark", hasSel(1, 1, 1, 2),
                   "nextBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(1, 1, 1, 2),
                   "prevBookmark", hasSel(0, 1, 0, 1),
                   "prevBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(1, 1, 1, 2),
                   "toggleBookmark",
                   "prevBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(0, 1, 0, 1),
                   "selectBookmarks", hasSel(0, 1, 0, 1,
                                             2, 1, 2, 2),
                   "clearBookmarks",
                   Pos(0, 0), "selectBookmarks", at(0, 0));
          
            stTest("upAndDowncaseAtCursor", "abc\ndef  x\nghI",
                   setSel(0, 1, 0, 3,
                          1, 1, 1, 1,
                          1, 4, 1, 4), "upcaseAtCursor",
                   val("aBC\nDEF  x\nghI"), hasSel(0, 1, 0, 3,
                                                   1, 3, 1, 3,
                                                   1, 4, 1, 4),
                   "downcaseAtCursor",
                   val("abc\ndef  x\nghI"), hasSel(0, 1, 0, 3,
                                                   1, 3, 1, 3,
                                                   1, 4, 1, 4));
          
            stTest("mark", "abc\ndef\nghi",
                   Pos(1, 1), "setSublimeMark",
                   Pos(2, 1), "selectToSublimeMark", hasSel(2, 1, 1, 1),
                   Pos(0, 1), "swapWithSublimeMark", at(1, 1), "swapWithSublimeMark", at(0, 1),
                   "deleteToSublimeMark", val("aef\nghi"),
                   "sublimeYank", val("abc\ndef\nghi"), at(1, 1));
          
            stTest("findUnder", "foo foobar  a",
                   "findUnder", hasSel(0, 4, 0, 7),
                   "findUnder", hasSel(0, 0, 0, 3),
                   "findUnderPrevious", hasSel(0, 4, 0, 7),
                   "findUnderPrevious", hasSel(0, 0, 0, 3),
                   Pos(0, 4), "findUnder", hasSel(0, 4, 0, 10),
                   Pos(0, 11), "findUnder", hasSel(0, 11, 0, 11));
          })();
          
        • test.js
          var Pos = CodeMirror.Pos;
          
          CodeMirror.defaults.rtlMoveVisually = true;
          
          function forEach(arr, f) {
            for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i);
          }
          
          function addDoc(cm, width, height) {
            var content = [], line = "";
            for (var i = 0; i < width; ++i) line += "x";
            for (var i = 0; i < height; ++i) content.push(line);
            cm.setValue(content.join("\n"));
          }
          
          function byClassName(elt, cls) {
            if (elt.getElementsByClassName) return elt.getElementsByClassName(cls);
            var found = [], re = new RegExp("\\b" + cls + "\\b");
            function search(elt) {
              if (elt.nodeType == 3) return;
              if (re.test(elt.className)) found.push(elt);
              for (var i = 0, e = elt.childNodes.length; i < e; ++i)
                search(elt.childNodes[i]);
            }
            search(elt);
            return found;
          }
          
          var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
          var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
          var mac = /Mac/.test(navigator.platform);
          var phantom = /PhantomJS/.test(navigator.userAgent);
          var opera = /Opera\/\./.test(navigator.userAgent);
          var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
          if (opera_version) opera_version = Number(opera_version);
          var opera_lt10 = opera && (!opera_version || opera_version < 10);
          
          namespace = "core_";
          
          test("core_fromTextArea", function() {
            var te = document.getElementById("code");
            te.value = "CONTENT";
            var cm = CodeMirror.fromTextArea(te);
            is(!te.offsetHeight);
            eq(cm.getValue(), "CONTENT");
            cm.setValue("foo\nbar");
            eq(cm.getValue(), "foo\nbar");
            cm.save();
            is(/^foo\r?\nbar$/.test(te.value));
            cm.setValue("xxx");
            cm.toTextArea();
            is(te.offsetHeight);
            eq(te.value, "xxx");
          });
          
          testCM("getRange", function(cm) {
            eq(cm.getLine(0), "1234");
            eq(cm.getLine(1), "5678");
            eq(cm.getLine(2), null);
            eq(cm.getLine(-1), null);
            eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123");
            eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234");
            eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56");
            eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78");
          }, {value: "1234\n5678"});
          
          testCM("replaceRange", function(cm) {
            eq(cm.getValue(), "");
            cm.replaceRange("foo\n", Pos(0, 0));
            eq(cm.getValue(), "foo\n");
            cm.replaceRange("a\nb", Pos(0, 1));
            eq(cm.getValue(), "fa\nboo\n");
            eq(cm.lineCount(), 3);
            cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1));
            eq(cm.getValue(), "xyzzyoo\n");
            cm.replaceRange("abc", Pos(0, 0), Pos(10, 0));
            eq(cm.getValue(), "abc");
            eq(cm.lineCount(), 1);
          });
          
          testCM("selection", function(cm) {
            cm.setSelection(Pos(0, 4), Pos(2, 2));
            is(cm.somethingSelected());
            eq(cm.getSelection(), "11\n222222\n33");
            eqPos(cm.getCursor(false), Pos(2, 2));
            eqPos(cm.getCursor(true), Pos(0, 4));
            cm.setSelection(Pos(1, 0));
            is(!cm.somethingSelected());
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(true), Pos(1, 0));
            cm.replaceSelection("abc", "around");
            eq(cm.getSelection(), "abc");
            eq(cm.getValue(), "111111\nabc222222\n333333");
            cm.replaceSelection("def", "end");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(true), Pos(1, 3));
            cm.setCursor(Pos(2, 1));
            eqPos(cm.getCursor(true), Pos(2, 1));
            cm.setCursor(1, 2);
            eqPos(cm.getCursor(true), Pos(1, 2));
          }, {value: "111111\n222222\n333333"});
          
          testCM("extendSelection", function(cm) {
            cm.setExtending(true);
            addDoc(cm, 10, 10);
            cm.setSelection(Pos(3, 5));
            eqPos(cm.getCursor("head"), Pos(3, 5));
            eqPos(cm.getCursor("anchor"), Pos(3, 5));
            cm.setSelection(Pos(2, 5), Pos(5, 5));
            eqPos(cm.getCursor("head"), Pos(5, 5));
            eqPos(cm.getCursor("anchor"), Pos(2, 5));
            eqPos(cm.getCursor("start"), Pos(2, 5));
            eqPos(cm.getCursor("end"), Pos(5, 5));
            cm.setSelection(Pos(5, 5), Pos(2, 5));
            eqPos(cm.getCursor("head"), Pos(2, 5));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            eqPos(cm.getCursor("start"), Pos(2, 5));
            eqPos(cm.getCursor("end"), Pos(5, 5));
            cm.extendSelection(Pos(3, 2));
            eqPos(cm.getCursor("head"), Pos(3, 2));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(6, 2));
            eqPos(cm.getCursor("head"), Pos(6, 2));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(6, 3), Pos(6, 4));
            eqPos(cm.getCursor("head"), Pos(6, 4));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(0, 3), Pos(0, 4));
            eqPos(cm.getCursor("head"), Pos(0, 3));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(4, 5), Pos(6, 5));
            eqPos(cm.getCursor("head"), Pos(6, 5));
            eqPos(cm.getCursor("anchor"), Pos(4, 5));
            cm.setExtending(false);
            cm.extendSelection(Pos(0, 3), Pos(0, 4));
            eqPos(cm.getCursor("head"), Pos(0, 3));
            eqPos(cm.getCursor("anchor"), Pos(0, 4));
          });
          
          testCM("lines", function(cm) {
            eq(cm.getLine(0), "111111");
            eq(cm.getLine(1), "222222");
            eq(cm.getLine(-1), null);
            cm.replaceRange("", Pos(1, 0), Pos(2, 0))
            cm.replaceRange("abc", Pos(1, 0), Pos(1));
            eq(cm.getValue(), "111111\nabc");
          }, {value: "111111\n222222\n333333"});
          
          testCM("indent", function(cm) {
            cm.indentLine(1);
            eq(cm.getLine(1), "   blah();");
            cm.setOption("indentUnit", 8);
            cm.indentLine(1);
            eq(cm.getLine(1), "\tblah();");
            cm.setOption("indentUnit", 10);
            cm.setOption("tabSize", 4);
            cm.indentLine(1);
            eq(cm.getLine(1), "\t\t  blah();");
          }, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8});
          
          testCM("indentByNumber", function(cm) {
            cm.indentLine(0, 2);
            eq(cm.getLine(0), "  foo");
            cm.indentLine(0, -200);
            eq(cm.getLine(0), "foo");
            cm.setSelection(Pos(0, 0), Pos(1, 2));
            cm.indentSelection(3);
            eq(cm.getValue(), "   foo\n   bar\nbaz");
          }, {value: "foo\nbar\nbaz"});
          
          test("core_defaults", function() {
            var defsCopy = {}, defs = CodeMirror.defaults;
            for (var opt in defs) defsCopy[opt] = defs[opt];
            defs.indentUnit = 5;
            defs.value = "uu";
            defs.indentWithTabs = true;
            defs.tabindex = 55;
            var place = document.getElementById("testground"), cm = CodeMirror(place);
            try {
              eq(cm.getOption("indentUnit"), 5);
              cm.setOption("indentUnit", 10);
              eq(defs.indentUnit, 5);
              eq(cm.getValue(), "uu");
              eq(cm.getOption("indentWithTabs"), true);
              eq(cm.getInputField().tabIndex, 55);
            }
            finally {
              for (var opt in defsCopy) defs[opt] = defsCopy[opt];
              place.removeChild(cm.getWrapperElement());
            }
          });
          
          testCM("lineInfo", function(cm) {
            eq(cm.lineInfo(-1), null);
            var mark = document.createElement("span");
            var lh = cm.setGutterMarker(1, "FOO", mark);
            var info = cm.lineInfo(1);
            eq(info.text, "222222");
            eq(info.gutterMarkers.FOO, mark);
            eq(info.line, 1);
            eq(cm.lineInfo(2).gutterMarkers, null);
            cm.setGutterMarker(lh, "FOO", null);
            eq(cm.lineInfo(1).gutterMarkers, null);
            cm.setGutterMarker(1, "FOO", mark);
            cm.setGutterMarker(0, "FOO", mark);
            cm.clearGutter("FOO");
            eq(cm.lineInfo(0).gutterMarkers, null);
            eq(cm.lineInfo(1).gutterMarkers, null);
          }, {value: "111111\n222222\n333333"});
          
          testCM("coords", function(cm) {
            cm.setSize(null, 100);
            addDoc(cm, 32, 200);
            var top = cm.charCoords(Pos(0, 0));
            var bot = cm.charCoords(Pos(200, 30));
            is(top.left < bot.left);
            is(top.top < bot.top);
            is(top.top < top.bottom);
            cm.scrollTo(null, 100);
            var top2 = cm.charCoords(Pos(0, 0));
            is(top.top > top2.top);
            eq(top.left, top2.left);
          });
          
          testCM("coordsChar", function(cm) {
            addDoc(cm, 35, 70);
            for (var i = 0; i < 2; ++i) {
              var sys = i ? "local" : "page";
              for (var ch = 0; ch <= 35; ch += 5) {
                for (var line = 0; line < 70; line += 5) {
                  cm.setCursor(line, ch);
                  var coords = cm.charCoords(Pos(line, ch), sys);
                  var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys);
                  eqPos(pos, Pos(line, ch));
                }
              }
            }
          }, {lineNumbers: true});
          
          testCM("posFromIndex", function(cm) {
            cm.setValue(
              "This function should\n" +
              "convert a zero based index\n" +
              "to line and ch."
            );
          
            var examples = [
              { index: -1, line: 0, ch: 0  }, // <- Tests clipping
              { index: 0,  line: 0, ch: 0  },
              { index: 10, line: 0, ch: 10 },
              { index: 39, line: 1, ch: 18 },
              { index: 55, line: 2, ch: 7  },
              { index: 63, line: 2, ch: 15 },
              { index: 64, line: 2, ch: 15 }  // <- Tests clipping
            ];
          
            for (var i = 0; i < examples.length; i++) {
              var example = examples[i];
              var pos = cm.posFromIndex(example.index);
              eq(pos.line, example.line);
              eq(pos.ch, example.ch);
              if (example.index >= 0 && example.index < 64)
                eq(cm.indexFromPos(pos), example.index);
            }
          });
          
          testCM("undo", function(cm) {
            cm.replaceRange("def", Pos(0, 0), Pos(0));
            eq(cm.historySize().undo, 1);
            cm.undo();
            eq(cm.getValue(), "abc");
            eq(cm.historySize().undo, 0);
            eq(cm.historySize().redo, 1);
            cm.redo();
            eq(cm.getValue(), "def");
            eq(cm.historySize().undo, 1);
            eq(cm.historySize().redo, 0);
            cm.setValue("1\n\n\n2");
            cm.clearHistory();
            eq(cm.historySize().undo, 0);
            for (var i = 0; i < 20; ++i) {
              cm.replaceRange("a", Pos(0, 0));
              cm.replaceRange("b", Pos(3, 0));
            }
            eq(cm.historySize().undo, 40);
            for (var i = 0; i < 40; ++i)
              cm.undo();
            eq(cm.historySize().redo, 40);
            eq(cm.getValue(), "1\n\n\n2");
          }, {value: "abc"});
          
          testCM("undoDepth", function(cm) {
            cm.replaceRange("d", Pos(0));
            cm.replaceRange("e", Pos(0));
            cm.replaceRange("f", Pos(0));
            cm.undo(); cm.undo(); cm.undo();
            eq(cm.getValue(), "abcd");
          }, {value: "abc", undoDepth: 4});
          
          testCM("undoDoesntClearValue", function(cm) {
            cm.undo();
            eq(cm.getValue(), "x");
          }, {value: "x"});
          
          testCM("undoMultiLine", function(cm) {
            cm.operation(function() {
              cm.replaceRange("x", Pos(0, 0));
              cm.replaceRange("y", Pos(1, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi");
            cm.operation(function() {
              cm.replaceRange("y", Pos(1, 0));
              cm.replaceRange("x", Pos(0, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi");
            cm.operation(function() {
              cm.replaceRange("y", Pos(2, 0));
              cm.replaceRange("x", Pos(1, 0));
              cm.replaceRange("z", Pos(2, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi", 3);
          }, {value: "abc\ndef\nghi"});
          
          testCM("undoComposite", function(cm) {
            cm.replaceRange("y", Pos(1));
            cm.operation(function() {
              cm.replaceRange("x", Pos(0));
              cm.replaceRange("z", Pos(2));
            });
            eq(cm.getValue(), "ax\nby\ncz\n");
            cm.undo();
            eq(cm.getValue(), "a\nby\nc\n");
            cm.undo();
            eq(cm.getValue(), "a\nb\nc\n");
            cm.redo(); cm.redo();
            eq(cm.getValue(), "ax\nby\ncz\n");
          }, {value: "a\nb\nc\n"});
          
          testCM("undoSelection", function(cm) {
            cm.setSelection(Pos(0, 2), Pos(0, 4));
            cm.replaceSelection("");
            cm.setCursor(Pos(1, 0));
            cm.undo();
            eqPos(cm.getCursor(true), Pos(0, 2));
            eqPos(cm.getCursor(false), Pos(0, 4));
            cm.setCursor(Pos(1, 0));
            cm.redo();
            eqPos(cm.getCursor(true), Pos(0, 2));
            eqPos(cm.getCursor(false), Pos(0, 2));
          }, {value: "abcdefgh\n"});
          
          testCM("undoSelectionAsBefore", function(cm) {
            cm.replaceSelection("abc", "around");
            cm.undo();
            cm.redo();
            eq(cm.getSelection(), "abc");
          });
          
          testCM("selectionChangeConfusesHistory", function(cm) {
            cm.replaceSelection("abc", null, "dontmerge");
            cm.operation(function() {
              cm.setCursor(Pos(0, 0));
              cm.replaceSelection("abc", null, "dontmerge");
            });
            eq(cm.historySize().undo, 2);
          });
          
          testCM("markTextSingleLine", function(cm) {
            forEach([{a: 0, b: 1, c: "", f: 2, t: 5},
                     {a: 0, b: 4, c: "", f: 0, t: 2},
                     {a: 1, b: 2, c: "x", f: 3, t: 6},
                     {a: 4, b: 5, c: "", f: 3, t: 5},
                     {a: 4, b: 5, c: "xx", f: 3, t: 7},
                     {a: 2, b: 5, c: "", f: 2, t: 3},
                     {a: 2, b: 5, c: "abcd", f: 6, t: 7},
                     {a: 2, b: 6, c: "x", f: null, t: null},
                     {a: 3, b: 6, c: "", f: null, t: null},
                     {a: 0, b: 9, c: "hallo", f: null, t: null},
                     {a: 4, b: 6, c: "x", f: 3, t: 4},
                     {a: 4, b: 8, c: "", f: 3, t: 4},
                     {a: 6, b: 6, c: "a", f: 3, t: 6},
                     {a: 8, b: 9, c: "", f: 3, t: 6}], function(test) {
              cm.setValue("1234567890");
              var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"});
              cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b));
              var f = r.find();
              eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t);
            });
          });
          
          testCM("markTextMultiLine", function(cm) {
            function p(v) { return v && Pos(v[0], v[1]); }
            forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]},
                     {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]},
                     {a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]},
                     {a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]},
                     {a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]},
                     {a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]},
                     {a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]},
                     {a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]},
                     {a: [0, 5], b: [2, 5], c: "xx", f: null, t: null},
                     {a: [0, 0], b: [2, 10], c: "x", f: null, t: null},
                     {a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]},
                     {a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]},
                     {a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]},
                     {a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]},
                     {a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) {
              cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n");
              var r = cm.markText(Pos(0, 5), Pos(2, 5),
                                  {className: "CodeMirror-matchingbracket"});
              cm.replaceRange(test.c, p(test.a), p(test.b));
              var f = r.find();
              eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t));
            });
          });
          
          testCM("markTextUndo", function(cm) {
            var marker1, marker2, bookmark;
            marker1 = cm.markText(Pos(0, 1), Pos(0, 3),
                                  {className: "CodeMirror-matchingbracket"});
            marker2 = cm.markText(Pos(0, 0), Pos(2, 1),
                                  {className: "CodeMirror-matchingbracket"});
            bookmark = cm.setBookmark(Pos(1, 5));
            cm.operation(function(){
              cm.replaceRange("foo", Pos(0, 2));
              cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0));
            });
            var v1 = cm.getValue();
            cm.setValue("");
            eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null);
            cm.undo();
            eqPos(bookmark.find(), Pos(1, 5), "still there");
            cm.undo();
            var m1Pos = marker1.find(), m2Pos = marker2.find();
            eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3));
            eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1));
            eqPos(bookmark.find(), Pos(1, 5));
            cm.redo(); cm.redo();
            eq(bookmark.find(), null);
            cm.undo();
            eqPos(bookmark.find(), Pos(1, 5));
            eq(cm.getValue(), v1);
          }, {value: "1234\n56789\n00\n"});
          
          testCM("markTextStayGone", function(cm) {
            var m1 = cm.markText(Pos(0, 0), Pos(0, 1));
            cm.replaceRange("hi", Pos(0, 2));
            m1.clear();
            cm.undo();
            eq(m1.find(), null);
          }, {value: "hello"});
          
          testCM("markTextAllowEmpty", function(cm) {
            var m1 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false});
            is(m1.find());
            cm.replaceRange("x", Pos(0, 0));
            is(m1.find());
            cm.replaceRange("y", Pos(0, 2));
            is(m1.find());
            cm.replaceRange("z", Pos(0, 3), Pos(0, 4));
            is(!m1.find());
            var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false,
                                                        inclusiveLeft: true,
                                                        inclusiveRight: true});
            cm.replaceRange("q", Pos(0, 1), Pos(0, 2));
            is(m2.find());
            cm.replaceRange("", Pos(0, 0), Pos(0, 3));
            is(!m2.find());
            var m3 = cm.markText(Pos(0, 1), Pos(0, 1), {clearWhenEmpty: false});
            cm.replaceRange("a", Pos(0, 3));
            is(m3.find());
            cm.replaceRange("b", Pos(0, 1));
            is(!m3.find());
          }, {value: "abcde"});
          
          testCM("markTextStacked", function(cm) {
            var m1 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});
            var m2 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});
            cm.replaceRange("B", Pos(0, 1));
            is(m1.find() && m2.find());
          }, {value: "A"});
          
          testCM("undoPreservesNewMarks", function(cm) {
            cm.markText(Pos(0, 3), Pos(0, 4));
            cm.markText(Pos(1, 1), Pos(1, 3));
            cm.replaceRange("", Pos(0, 3), Pos(3, 1));
            var mBefore = cm.markText(Pos(0, 0), Pos(0, 1));
            var mAfter = cm.markText(Pos(0, 5), Pos(0, 6));
            var mAround = cm.markText(Pos(0, 2), Pos(0, 4));
            cm.undo();
            eqPos(mBefore.find().from, Pos(0, 0));
            eqPos(mBefore.find().to, Pos(0, 1));
            eqPos(mAfter.find().from, Pos(3, 3));
            eqPos(mAfter.find().to, Pos(3, 4));
            eqPos(mAround.find().from, Pos(0, 2));
            eqPos(mAround.find().to, Pos(3, 2));
            var found = cm.findMarksAt(Pos(2, 2));
            eq(found.length, 1);
            eq(found[0], mAround);
          }, {value: "aaaa\nbbbb\ncccc\ndddd"});
          
          testCM("markClearBetween", function(cm) {
            cm.setValue("aaa\nbbb\nccc\nddd\n");
            cm.markText(Pos(0, 0), Pos(2));
            cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2));
            eq(cm.findMarksAt(Pos(1, 1)).length, 0);
          });
          
          testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {
            var from = Pos(1, 0), to = Pos(1, 1);
            var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true});
            // Delete collapsed span.
            cm.replaceRange("", from, to);
          }, {value: "abc\nX\ndef"});
          
          testCM("markTextCSS", function(cm) {
            function present() {
              var spans = cm.display.lineDiv.getElementsByTagName("span");
              for (var i = 0; i < spans.length; i++)
                if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true;
            }
            var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"});
            m.clear();
            is(!present());
          }, {value: "abcdefgh"});
          
          testCM("bookmark", function(cm) {
            function p(v) { return v && Pos(v[0], v[1]); }
            forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},
                     {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]},
                     {a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]},
                     {a: [1, 4], b: [1, 6], c: "", d: null},
                     {a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]},
                     {a: [1, 6], b: [1, 8], c: "", d: [1, 5]},
                     {a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]},
                     {bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) {
              cm.setValue("1234567890\n1234567890\n1234567890");
              var b = cm.setBookmark(p(test.bm) || Pos(1, 5));
              cm.replaceRange(test.c, p(test.a), p(test.b));
              eqPos(b.find(), p(test.d));
            });
          });
          
          testCM("bookmarkInsertLeft", function(cm) {
            var br = cm.setBookmark(Pos(0, 2), {insertLeft: false});
            var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true});
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi");
            eqPos(br.find(), Pos(0, 2));
            eqPos(bl.find(), Pos(0, 4));
            cm.replaceRange("", Pos(0, 4), Pos(0, 5));
            cm.replaceRange("", Pos(0, 2), Pos(0, 4));
            cm.replaceRange("", Pos(0, 1), Pos(0, 2));
            // Verify that deleting next to bookmarks doesn't kill them
            eqPos(br.find(), Pos(0, 1));
            eqPos(bl.find(), Pos(0, 1));
          }, {value: "abcdef"});
          
          testCM("bookmarkCursor", function(cm) {
            var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)),
                pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)),
                pos41 = cm.cursorCoords(Pos(4, 1));
            cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true});
            cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true});
            cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")});
            cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")});
            var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),
                new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));
            near(new01.left, pos01.left, 1);
            near(new01.top, pos01.top, 1);
            is(new11.left > pos11.left, "at right, middle of line");
            near(new11.top == pos11.top, 1);
            near(new20.left, pos20.left, 1);
            near(new20.top, pos20.top, 1);
            is(new30.left > pos30.left, "at right, empty line");
            near(new30.top, pos30, 1);
            cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")});
            is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");
          }, {value: "foo\nbar\n\n\nx\ny"});
          
          testCM("multiBookmarkCursor", function(cm) {
            if (phantom) return;
            var ms = [], m;
            function add(insertLeft) {
              for (var i = 0; i < 3; ++i) {
                var node = document.createElement("span");
                node.innerHTML = "X";
                ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft}));
              }
            }
            var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;
            add(true);
            near(base1, cm.cursorCoords(Pos(0, 1)).left, 1);
            while (m = ms.pop()) m.clear();
            add(false);
            near(base4, cm.cursorCoords(Pos(0, 1)).left, 1);
          }, {value: "abcdefg"});
          
          testCM("getAllMarks", function(cm) {
            addDoc(cm, 10, 10);
            var m1 = cm.setBookmark(Pos(0, 2));
            var m2 = cm.markText(Pos(0, 2), Pos(3, 2));
            var m3 = cm.markText(Pos(1, 2), Pos(1, 8));
            var m4 = cm.markText(Pos(8, 0), Pos(9, 0));
            eq(cm.getAllMarks().length, 4);
            m1.clear();
            m3.clear();
            eq(cm.getAllMarks().length, 2);
          });
          
          testCM("setValueClears", function(cm) {
            cm.addLineClass(0, "wrap", "foo");
            var mark = cm.markText(Pos(0, 0), Pos(1, 1), {inclusiveLeft: true, inclusiveRight: true});
            cm.setValue("foo");
            is(!cm.lineInfo(0).wrapClass);
            is(!mark.find());
          }, {value: "a\nb"});
          
          testCM("bug577", function(cm) {
            cm.setValue("a\nb");
            cm.clearHistory();
            cm.setValue("fooooo");
            cm.undo();
          });
          
          testCM("scrollSnap", function(cm) {
            cm.setSize(100, 100);
            addDoc(cm, 200, 200);
            cm.setCursor(Pos(100, 180));
            var info = cm.getScrollInfo();
            is(info.left > 0 && info.top > 0);
            cm.setCursor(Pos(0, 0));
            info = cm.getScrollInfo();
            is(info.left == 0 && info.top == 0, "scrolled clean to top");
            cm.setCursor(Pos(100, 180));
            cm.setCursor(Pos(199, 0));
            info = cm.getScrollInfo();
            is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom");
          });
          
          testCM("scrollIntoView", function(cm) {
            if (phantom) return;
            var outer = cm.getWrapperElement().getBoundingClientRect();
            function test(line, ch, msg) {
              var pos = Pos(line, ch);
              cm.scrollIntoView(pos);
              var box = cm.charCoords(pos, "window");
              is(box.left >= outer.left, msg + " (left)");
              is(box.right <= outer.right, msg + " (right)");
              is(box.top >= outer.top, msg + " (top)");
              is(box.bottom <= outer.bottom, msg + " (bottom)");
            }
            addDoc(cm, 200, 200);
            test(199, 199, "bottom right");
            test(0, 0, "top left");
            test(100, 100, "center");
            test(199, 0, "bottom left");
            test(0, 199, "top right");
            test(100, 100, "center again");
          });
          
          testCM("scrollBackAndForth", function(cm) {
            addDoc(cm, 1, 200);
            cm.operation(function() {
              cm.scrollIntoView(Pos(199, 0));
              cm.scrollIntoView(Pos(4, 0));
            });
            is(cm.getScrollInfo().top > 0);
          });
          
          testCM("selectAllNoScroll", function(cm) {
            addDoc(cm, 1, 200);
            cm.execCommand("selectAll");
            eq(cm.getScrollInfo().top, 0);
            cm.setCursor(199);
            cm.execCommand("selectAll");
            is(cm.getScrollInfo().top > 0);
          });
          
          testCM("selectionPos", function(cm) {
            if (phantom || cm.getOption("inputStyle") != "textarea") return;
            cm.setSize(100, 100);
            addDoc(cm, 200, 100);
            cm.setSelection(Pos(1, 100), Pos(98, 100));
            var lineWidth = cm.charCoords(Pos(0, 200), "local").left;
            var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100;
            cm.scrollTo(0, 0);
            var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected");
            var outer = cm.getWrapperElement().getBoundingClientRect();
            var sawMiddle, sawTop, sawBottom;
            for (var i = 0, e = selElt.length; i < e; ++i) {
              var box = selElt[i].getBoundingClientRect();
              var atLeft = box.left - outer.left < 30;
              var width = box.right - box.left;
              var atRight = box.right - outer.left > .8 * lineWidth;
              if (atLeft && atRight) {
                sawMiddle = true;
                is(box.bottom - box.top > 90 * lineHeight, "middle high");
                is(width > .9 * lineWidth, "middle wide");
              } else {
                is(width > .4 * lineWidth, "top/bot wide enough");
                is(width < .6 * lineWidth, "top/bot slim enough");
                if (atLeft) {
                  sawBottom = true;
                  is(box.top - outer.top > 96 * lineHeight, "bot below");
                } else if (atRight) {
                  sawTop = true;
                  is(box.top - outer.top < 2.1 * lineHeight, "top above");
                }
              }
            }
            is(sawTop && sawBottom && sawMiddle, "all parts");
          }, null);
          
          testCM("restoreHistory", function(cm) {
            cm.setValue("abc\ndef");
            cm.replaceRange("hello", Pos(1, 0), Pos(1));
            cm.replaceRange("goop", Pos(0, 0), Pos(0));
            cm.undo();
            var storedVal = cm.getValue(), storedHist = cm.getHistory();
            if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist));
            eq(storedVal, "abc\nhello");
            cm.setValue("");
            cm.clearHistory();
            eq(cm.historySize().undo, 0);
            cm.setValue(storedVal);
            cm.setHistory(storedHist);
            cm.redo();
            eq(cm.getValue(), "goop\nhello");
            cm.undo(); cm.undo();
            eq(cm.getValue(), "abc\ndef");
          });
          
          testCM("doubleScrollbar", function(cm) {
            var dummy = document.body.appendChild(document.createElement("p"));
            dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px";
            var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth;
            document.body.removeChild(dummy);
            if (scrollbarWidth < 2) return;
            cm.setSize(null, 100);
            addDoc(cm, 1, 300);
            var wrap = cm.getWrapperElement();
            is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5);
          });
          
          testCM("weirdLinebreaks", function(cm) {
            cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop");
            is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop");
            is(cm.lineCount(), 6);
            cm.setValue("\n\n");
            is(cm.lineCount(), 3);
          });
          
          testCM("setSize", function(cm) {
            cm.setSize(100, 100);
            var wrap = cm.getWrapperElement();
            is(wrap.offsetWidth, 100);
            is(wrap.offsetHeight, 100);
            cm.setSize("100%", "3em");
            is(wrap.style.width, "100%");
            is(wrap.style.height, "3em");
            cm.setSize(null, 40);
            is(wrap.style.width, "100%");
            is(wrap.style.height, "40px");
          });
          
          function foldLines(cm, start, end, autoClear) {
            return cm.markText(Pos(start, 0), Pos(end - 1), {
              inclusiveLeft: true,
              inclusiveRight: true,
              collapsed: true,
              clearOnEnter: autoClear
            });
          }
          
          testCM("collapsedLines", function(cm) {
            addDoc(cm, 4, 10);
            var range = foldLines(cm, 4, 5), cleared = 0;
            CodeMirror.on(range, "clear", function() {cleared++;});
            cm.setCursor(Pos(3, 0));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.replaceRange("abcdefg", Pos(3, 0), Pos(3));
            cm.setCursor(Pos(3, 6));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 4));
            cm.replaceRange("ab", Pos(3, 0), Pos(3));
            cm.setCursor(Pos(3, 2));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 2));
            cm.operation(function() {range.clear(); range.clear();});
            eq(cleared, 1);
          });
          
          testCM("collapsedRangeCoordsChar", function(cm) {
            var pos_1_3 = cm.charCoords(Pos(1, 3));
            pos_1_3.left += 2; pos_1_3.top += 2;
            var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};
            var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts);
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
            m1.clear();
            var m1 = cm.markText(Pos(0, 0), Pos(1, 1), {collapsed: true, inclusiveLeft: true});
            var m2 = cm.markText(Pos(1, 1), Pos(2, 0), {collapsed: true, inclusiveRight: true});
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
            m1.clear(); m2.clear();
            var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts);
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
          }, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});
          
          testCM("collapsedRangeBetweenLinesSelected", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            var widget = document.createElement("span");
            widget.textContent = "\u2194";
            cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget});
            cm.setSelection(Pos(0, 3), Pos(1, 0));
            var selElts = byClassName(cm.getWrapperElement(), "CodeMirror-selected");
            for (var i = 0, w = 0; i < selElts.length; i++)
              w += selElts[i].offsetWidth;
            is(w > 0);
          }, {value: "one\ntwo"});
          
          testCM("randomCollapsedRanges", function(cm) {
            addDoc(cm, 20, 500);
            cm.operation(function() {
              for (var i = 0; i < 200; i++) {
                var start = Pos(Math.floor(Math.random() * 500), Math.floor(Math.random() * 20));
                if (i % 4)
                  try { cm.markText(start, Pos(start.line + 2, 1), {collapsed: true}); }
                  catch(e) { if (!/overlapping/.test(String(e))) throw e; }
                else
                  cm.markText(start, Pos(start.line, start.ch + 4), {"className": "foo"});
              }
            });
          });
          
          testCM("hiddenLinesAutoUnfold", function(cm) {
            var range = foldLines(cm, 1, 3, true), cleared = 0;
            CodeMirror.on(range, "clear", function() {cleared++;});
            cm.setCursor(Pos(3, 0));
            eq(cleared, 0);
            cm.execCommand("goCharLeft");
            eq(cleared, 1);
            range = foldLines(cm, 1, 3, true);
            CodeMirror.on(range, "clear", function() {cleared++;});
            eqPos(cm.getCursor(), Pos(3, 0));
            cm.setCursor(Pos(0, 3));
            cm.execCommand("goCharRight");
            eq(cleared, 2);
          }, {value: "abc\ndef\nghi\njkl"});
          
          testCM("hiddenLinesSelectAll", function(cm) {  // Issue #484
            addDoc(cm, 4, 20);
            foldLines(cm, 0, 10);
            foldLines(cm, 11, 20);
            CodeMirror.commands.selectAll(cm);
            eqPos(cm.getCursor(true), Pos(10, 0));
            eqPos(cm.getCursor(false), Pos(10, 4));
          });
          
          
          testCM("everythingFolded", function(cm) {
            addDoc(cm, 2, 2);
            function enterPress() {
              cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}});
            }
            var fold = foldLines(cm, 0, 2);
            enterPress();
            eq(cm.getValue(), "xx\nxx");
            fold.clear();
            fold = foldLines(cm, 0, 2, true);
            eq(fold.find(), null);
            enterPress();
            eq(cm.getValue(), "\nxx\nxx");
          });
          
          testCM("structuredFold", function(cm) {
            if (phantom) return;
            addDoc(cm, 4, 8);
            var range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("Q")
            });
            cm.setCursor(0, 3);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(6, 2));
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(1, 2));
            CodeMirror.commands.delCharAfter(cm);
            eq(cm.getValue(), "xxxx\nxxxx\nxxxx");
            addDoc(cm, 4, 8);
            range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("M"),
              clearOnEnter: true
            });
            var cleared = 0;
            CodeMirror.on(range, "clear", function(){++cleared;});
            cm.setCursor(0, 3);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(6, 2));
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(6, 1));
            eq(cleared, 1);
            range.clear();
            eq(cleared, 1);
            range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("Q"),
              clearOnEnter: true
            });
            range.clear();
            cm.setCursor(1, 2);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 3));
            range = cm.markText(Pos(2, 0), Pos(4, 4), {
              replacedWith: document.createTextNode("M")
            });
            cm.setCursor(1, 0);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(2, 0));
          }, null);
          
          testCM("nestedFold", function(cm) {
            addDoc(cm, 10, 3);
            function fold(ll, cl, lr, cr) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true});
            }
            var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6);
            cm.setCursor(0, 1);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(2, 3));
            inner0.clear();
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(0, 1));
            outer.clear();
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(0, 2));
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 8));
            inner2.clear();
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(1, 7));
            cm.setCursor(0, 5);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(0, 6));
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 3));
          });
          
          testCM("badNestedFold", function(cm) {
            addDoc(cm, 4, 4);
            cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true});
            var caught;
            try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});}
            catch(e) {caught = e;}
            is(caught instanceof Error, "no error");
            is(/overlap/i.test(caught.message), "wrong error");
          });
          
          testCM("nestedFoldOnSide", function(cm) {
            var m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true, inclusiveRight: true});
            var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true});
            cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}).clear();
            try { cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true, inclusiveLeft: true}); }
            catch(e) { var caught = e; }
            is(caught && /overlap/i.test(caught.message));
            var m3 = cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true});
            var m4 = cm.markText(Pos(2, 0), Pos(2, 1), {collapse: true, inclusiveRight: true});
            m1.clear(); m4.clear();
            m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true});
            cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}).clear();
            try { cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true, inclusiveRight: true}); }
            catch(e) { var caught = e; }
            is(caught && /overlap/i.test(caught.message));
          }, {value: "ab\ncd\ef"});
          
          testCM("editInFold", function(cm) {
            addDoc(cm, 4, 6);
            var m = cm.markText(Pos(1, 2), Pos(3, 2), {collapsed: true});
            cm.replaceRange("", Pos(0, 0), Pos(1, 3));
            cm.replaceRange("", Pos(2, 1), Pos(3, 3));
            cm.replaceRange("a\nb\nc\nd", Pos(0, 1), Pos(1, 0));
            cm.cursorCoords(Pos(0, 0));
          });
          
          testCM("wrappingInlineWidget", function(cm) {
            cm.setSize("11em");
            var w = document.createElement("span");
            w.style.color = "red";
            w.innerHTML = "one two three four";
            cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w});
            var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10));
            is(cur0.top < cur1.top);
            is(cur0.bottom < cur1.bottom);
            var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9));
            eq(curL.top, cur0.top);
            eq(curL.bottom, cur0.bottom);
            eq(curR.top, cur1.top);
            eq(curR.bottom, cur1.bottom);
            cm.replaceRange("", Pos(0, 9), Pos(0));
            curR = cm.cursorCoords(Pos(0, 9));
            if (phantom) return;
            eq(curR.top, cur1.top);
            eq(curR.bottom, cur1.bottom);
          }, {value: "1 2 3 xxx 4", lineWrapping: true});
          
          testCM("changedInlineWidget", function(cm) {
            cm.setSize("10em");
            var w = document.createElement("span");
            w.innerHTML = "x";
            var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w});
            w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
            m.changed();
            var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
            is(hScroll.scrollWidth > hScroll.clientWidth);
          }, {value: "hello there"});
          
          testCM("changedBookmark", function(cm) {
            cm.setSize("10em");
            var w = document.createElement("span");
            w.innerHTML = "x";
            var m = cm.setBookmark(Pos(0, 4), {widget: w});
            w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
            m.changed();
            var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
            is(hScroll.scrollWidth > hScroll.clientWidth);
          }, {value: "abcdefg"});
          
          testCM("inlineWidget", function(cm) {
            var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
            cm.setCursor(0, 2);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(1, 4));
            cm.setCursor(0, 2);
            cm.replaceSelection("hi");
            eqPos(w.find(), Pos(0, 2));
            cm.setCursor(0, 1);
            cm.replaceSelection("ay");
            eqPos(w.find(), Pos(0, 4));
            eq(cm.getLine(0), "uayuhiuu");
          }, {value: "uuuu\nuuuuuu"});
          
          testCM("wrappingAndResizing", function(cm) {
            cm.setSize(null, "auto");
            cm.setOption("lineWrapping", true);
            var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight;
            var doc = "xxx xxx xxx xxx xxx";
            cm.setValue(doc);
            for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) {
              cm.setSize(w);
              if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) {
                if (step == 10) { w -= 10; step = 1; }
                else break;
              }
            }
            // Ensure that putting the cursor at the end of the maximally long
            // line doesn't cause wrapping to happen.
            cm.setCursor(Pos(0, doc.length));
            eq(wrap.offsetHeight, h0);
            cm.replaceSelection("x");
            is(wrap.offsetHeight > h0, "wrapping happens");
            // Now add a max-height and, in a document consisting of
            // almost-wrapped lines, go over it so that a scrollbar appears.
            cm.setValue(doc + "\n" + doc + "\n");
            cm.getScrollerElement().style.maxHeight = "100px";
            cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0));
            forEach([Pos(0, doc.length), Pos(0, doc.length - 1),
                     Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)],
                    function(pos) {
              var coords = cm.charCoords(pos);
              eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5}));
            });
          }, null, ie_lt8);
          
          testCM("measureEndOfLine", function(cm) {
            cm.setSize(null, "auto");
            var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild;
            var lh = inner.offsetHeight;
            for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) {
              cm.setSize(w);
              if (inner.offsetHeight < 2.5 * lh) {
                if (step == 10) { w -= 10; step = 1; }
                else break;
              }
            }
            cm.setValue(cm.getValue() + "\n\n");
            var endPos = cm.charCoords(Pos(0, 18), "local");
            is(endPos.top > lh * .8, "not at top");
            is(endPos.left > w - 20, "not at right");
            endPos = cm.charCoords(Pos(0, 18));
            eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18));
          }, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);
          
          testCM("scrollVerticallyAndHorizontally", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            cm.setSize(100, 100);
            addDoc(cm, 40, 40);
            cm.setCursor(39);
            var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0];
            is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one");
            var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect();
            var editorBox = wrap.getBoundingClientRect();
            is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight,
               "bottom line visible");
          }, {lineNumbers: true});
          
          testCM("moveVstuck", function(cm) {
            var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight;
            var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n";
            cm.setValue(val);
            for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) {
              cm.setSize(w);
              if (lines.offsetHeight <= 3.5 * h0) break;
            }
            cm.setCursor(Pos(0, val.length - 1));
            cm.moveV(-1, "line");
            eqPos(cm.getCursor(), Pos(0, 26));
          }, {lineWrapping: true}, ie_lt8 || opera_lt10);
          
          testCM("collapseOnMove", function(cm) {
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goLineUp");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goPageDown");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(2, 4));
            cm.execCommand("goLineUp");
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goCharLeft");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(0, 1));
          }, {value: "aaaaa\nb\nccccc"});
          
          testCM("clickTab", function(cm) {
            var p0 = cm.charCoords(Pos(0, 0));
            eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0));
            eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1));
          }, {value: "\t\n\n", lineWrapping: true, tabSize: 8});
          
          testCM("verticalScroll", function(cm) {
            cm.setSize(100, 200);
            cm.setValue("foo\nbar\nbaz\n");
            var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth;
            cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));
            is(sc.scrollWidth > baseWidth, "scrollbar present");
            cm.replaceRange("foo", Pos(0, 0), Pos(0));
            if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone");
            cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));
            cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1));
            is(sc.scrollWidth > baseWidth, "present again");
            var curWidth = sc.scrollWidth;
            cm.replaceRange("foo", Pos(0, 0), Pos(0));
            is(sc.scrollWidth < curWidth, "scrollbar smaller");
            is(sc.scrollWidth > baseWidth, "but still present");
          });
          
          testCM("extraKeys", function(cm) {
            var outcome;
            function fakeKey(expected, code, props) {
              if (typeof code == "string") code = code.charCodeAt(0);
              var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}};
              if (props) for (var n in props) e[n] = props[n];
              outcome = null;
              cm.triggerOnKeyDown(e);
              eq(outcome, expected);
            }
            CodeMirror.commands.testCommand = function() {outcome = "tc";};
            CodeMirror.commands.goTestCommand = function() {outcome = "gtc";};
            cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";},
                                       "X": function() {outcome = "x";},
                                       "Ctrl-Alt-U": function() {outcome = "cau";},
                                       "End": "testCommand",
                                       "Home": "goTestCommand",
                                       "Tab": false});
            fakeKey(null, "U");
            fakeKey("cau", "U", {ctrlKey: true, altKey: true});
            fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true});
            fakeKey("x", "X");
            fakeKey("sx", "X", {shiftKey: true});
            fakeKey("tc", 35);
            fakeKey(null, 35, {shiftKey: true});
            fakeKey("gtc", 36);
            fakeKey("gtc", 36, {shiftKey: true});
            fakeKey(null, 9);
          }, null, window.opera && mac);
          
          testCM("wordMovementCommands", function(cm) {
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 12));
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 9));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 24));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(1, 9));
            cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(1, 13));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(2, 0));
          }, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"});
          
          testCM("groupMovementCommands", function(cm) {
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 10));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 15));
            cm.setCursor(Pos(0, 17));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 16));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 14));
            cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 20));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 2));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 5));
            cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 20));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 16));
          }, {value: "booo ba---quux. ffff\n  abc d"});
          
          testCM("groupsAndWhitespace", function(cm) {
            var positions = [Pos(0, 0), Pos(0, 2), Pos(0, 5), Pos(0, 9), Pos(0, 11),
                             Pos(1, 0), Pos(1, 2), Pos(1, 5)];
            for (var i = 1; i < positions.length; i++) {
              cm.execCommand("goGroupRight");
              eqPos(cm.getCursor(), positions[i]);
            }
            for (var i = positions.length - 2; i >= 0; i--) {
              cm.execCommand("goGroupLeft");
              eqPos(cm.getCursor(), i == 2 ? Pos(0, 6) : positions[i]);
            }
          }, {value: "  foo +++  \n  bar"});
          
          testCM("charMovementCommands", function(cm) {
            cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goCharRight"); cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.setCursor(Pos(1, 0));
            cm.execCommand("goColumnLeft");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goColumnRight");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(1, 5));
            cm.execCommand("goLineStartSmart");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineStartSmart");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.setCursor(Pos(2, 0));
            cm.execCommand("goCharRight"); cm.execCommand("goColumnRight");
            eqPos(cm.getCursor(), Pos(2, 0));
          }, {value: "line1\n ine2\n"});
          
          testCM("verticalMovementCommands", function(cm) {
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goLineDown");
            if (!phantom) // This fails in PhantomJS, though not in a real Webkit
              eqPos(cm.getCursor(), Pos(1, 0));
            cm.setCursor(Pos(1, 12));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 5));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(3, 0));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(2, 5));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 12));
            cm.execCommand("goPageDown");
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.execCommand("goPageDown"); cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.execCommand("goPageUp");
            eqPos(cm.getCursor(), Pos(0, 0));
          }, {value: "line1\nlong long line2\nline3\n\nline5\n"});
          
          testCM("verticalMovementCommandsWrapping", function(cm) {
            cm.setSize(120);
            cm.setCursor(Pos(0, 5));
            cm.execCommand("goLineDown");
            eq(cm.getCursor().line, 0);
            is(cm.getCursor().ch > 5, "moved beyond wrap");
            for (var i = 0; ; ++i) {
              is(i < 20, "no endless loop");
              cm.execCommand("goLineDown");
              var cur = cm.getCursor();
              if (cur.line == 1) eq(cur.ch, 5);
              if (cur.line == 2) { eq(cur.ch, 1); break; }
            }
          }, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk",
              lineWrapping: true});
          
          testCM("rtlMovement", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
                     "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق",
                     "<img src=\"/בדיקה3.jpg\">"], function(line) {
              var inv = line.charAt(0) == "خ";
              cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
              var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0];
              var cursor = cursors.firstChild;
              var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;
              for (var i = 0; i <= line.length; ++i) {
                cm.execCommand("goCharRight");
                cursor = cursors.firstChild;
                if (i == line.length) is(cursor.offsetTop > prevY, "next line");
                else is(cursor.offsetLeft > prevX, "moved right");
                prevX = cursor.offsetLeft; prevY = cursor.offsetTop;
              }
              cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");
              prevX = cursors.firstChild.offsetLeft;
              for (var i = 0; i < line.length; ++i) {
                cm.execCommand("goCharLeft");
                cursor = cursors.firstChild;
                is(cursor.offsetLeft < prevX, "moved left");
                prevX = cursor.offsetLeft;
              }
            });
          }, null, ie_lt9);
          
          // Verify that updating a line clears its bidi ordering
          testCM("bidiUpdate", function(cm) {
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("خحج", "start");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 4));
          }, {value: "abcd\n"});
          
          testCM("movebyTextUnit", function(cm) {
            cm.setValue("בְּרֵאשִ\nééé́\n");
            cm.execCommand("goLineEnd");
            for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goCharRight");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 4));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 7));
          });
          
          testCM("lineChangeEvents", function(cm) {
            addDoc(cm, 3, 5);
            var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"];
            for (var i = 0; i < 5; ++i) {
              CodeMirror.on(cm.getLineHandle(i), "delete", function(i) {
                return function() {log.push("del " + i);};
              }(i));
              CodeMirror.on(cm.getLineHandle(i), "change", function(i) {
                return function() {log.push("ch " + i);};
              }(i));
            }
            cm.replaceRange("x", Pos(0, 1));
            cm.replaceRange("xy", Pos(1, 1), Pos(2));
            cm.replaceRange("foo\nbar", Pos(0, 1));
            cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount()));
            eq(log.length, want.length, "same length");
            for (var i = 0; i < log.length; ++i)
              eq(log[i], want[i]);
          });
          
          testCM("scrollEntirelyToRight", function(cm) {
            if (phantom || cm.getOption("inputStyle") != "textarea") return;
            addDoc(cm, 500, 2);
            cm.setCursor(Pos(0, 500));
            var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];
            is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left);
          });
          
          testCM("lineWidgets", function(cm) {
            addDoc(cm, 500, 3);
            var last = cm.charCoords(Pos(2, 0));
            var node = document.createElement("div");
            node.innerHTML = "hi";
            var widget = cm.addLineWidget(1, node);
            is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space");
            cm.setCursor(Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
          });
          
          testCM("lineWidgetFocus", function(cm) {
            var place = document.getElementById("testground");
            place.className = "offscreen";
            try {
              addDoc(cm, 500, 10);
              var node = document.createElement("input");
              var widget = cm.addLineWidget(1, node);
              node.focus();
              eq(document.activeElement, node);
              cm.replaceRange("new stuff", Pos(1, 0));
              eq(document.activeElement, node);
            } finally {
              place.className = "";
            }
          });
          
          testCM("lineWidgetCautiousRedraw", function(cm) {
            var node = document.createElement("div");
            node.innerHTML = "hahah";
            var w = cm.addLineWidget(0, node);
            var redrawn = false;
            w.on("redraw", function() { redrawn = true; });
            cm.replaceSelection("0");
            is(!redrawn);
          }, {value: "123\n456"});
          
          
          var knownScrollbarWidth;
          function scrollbarWidth(measure) {
            if (knownScrollbarWidth != null) return knownScrollbarWidth;
            var div = document.createElement('div');
            div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll";
            document.body.appendChild(div);
            knownScrollbarWidth = div.offsetHeight - div.clientHeight;
            document.body.removeChild(div);
            return knownScrollbarWidth || 0;
          }
          
          testCM("lineWidgetChanged", function(cm) {
            addDoc(cm, 2, 300);
            var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2;
            cm.setOption('lineNumbers', true);
            cm.setSize(600, cm.defaultTextHeight() * 50);
            cm.scrollTo(null, cm.heightAtLine(125, "local"));
          
            var expectedWidgetHeight = 60;
            var expectedLinesInWidget = 3;
            function w() {
              var node = document.createElement("div");
              // we use these children with just under half width of the line to check measurements are made with correct width
              // when placed in the measure div.
              // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test.
              // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test.
              // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right.
              // It may also be worthwhile to check this for non-coverGutter widgets.
              // Visually:
              // Good:
              // | ------------- display width ------------- |
              // | ------- widget-width when measured ------ |
              // | | -- under-half -- | | -- under-half -- | | 
              // | | --- over-half --- |                     |
              // | | --- over-half --- |                     |
              // Height: measured as 3 lines, same as it will be when actually displayed
          
              // Bad (too narrow):
              // | ------------- display width ------------- |
              // | ------ widget-width when measured ----- |  < -- uh oh
              // | | -- under-half -- |                    |
              // | | -- under-half -- |                    |  < -- when measured, shoved to next line
              // | | --- over-half --- |                   |
              // | | --- over-half --- |                   |
              // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines!
          
              // Bad (too wide):
              // | ------------- display width ------------- |
              // | -------- widget-width when measured ------- | < -- uh oh
              // | | -- under-half -- | | -- under-half -- |   | 
              // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line
              // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines!
          
              var barelyUnderHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(285 - halfScrollbarWidth)+'px;"></div>';
              var barelyOverHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(305 - halfScrollbarWidth)+'px;"></div>';
              node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml);
              node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;";
              return node;
            }
            var info0 = cm.getScrollInfo();
            var w0 = cm.addLineWidget(0, w(), { coverGutter: true });
            var w150 = cm.addLineWidget(150, w(), { coverGutter: true });
            var w300 = cm.addLineWidget(300, w(), { coverGutter: true });
            var info1 = cm.getScrollInfo();
            eq(info0.height + (3 * expectedWidgetHeight), info1.height);
            eq(info0.top + expectedWidgetHeight, info1.top);
            expectedWidgetHeight = 12;
            w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px";
            w0.changed(); w150.changed(); w300.changed();
            var info2 = cm.getScrollInfo();
            eq(info0.height + (3 * expectedWidgetHeight), info2.height);
            eq(info0.top + expectedWidgetHeight, info2.top);
          });
          
          testCM("getLineNumber", function(cm) {
            addDoc(cm, 2, 20);
            var h1 = cm.getLineHandle(1);
            eq(cm.getLineNumber(h1), 1);
            cm.replaceRange("hi\nbye\n", Pos(0, 0));
            eq(cm.getLineNumber(h1), 3);
            cm.setValue("");
            eq(cm.getLineNumber(h1), null);
          });
          
          testCM("jumpTheGap", function(cm) {
            if (phantom) return;
            var longLine = "abcdef ghiklmnop qrstuvw xyz ";
            longLine += longLine; longLine += longLine; longLine += longLine;
            cm.replaceRange(longLine, Pos(2, 0), Pos(2));
            cm.setSize("200px", null);
            cm.getWrapperElement().style.lineHeight = 2;
            cm.refresh();
            cm.setCursor(Pos(0, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineDown");
            eq(cm.getCursor().line, 2);
            is(cm.getCursor().ch > 1);
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
            var node = document.createElement("div");
            node.innerHTML = "hi"; node.style.height = "30px";
            cm.addLineWidget(0, node);
            cm.addLineWidget(1, node.cloneNode(true), {above: true});
            cm.setCursor(Pos(0, 2));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(1, 2));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 2));
          }, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});
          
          testCM("addLineClass", function(cm) {
            function cls(line, text, bg, wrap, gutter) {
              var i = cm.lineInfo(line);
              eq(i.textClass, text);
              eq(i.bgClass, bg);
              eq(i.wrapClass, wrap);
              if (typeof i.handle.gutterClass !== 'undefined') {
                  eq(i.handle.gutterClass, gutter);
              }
            }
            cm.addLineClass(0, "text", "foo");
            cm.addLineClass(0, "text", "bar");
            cm.addLineClass(1, "background", "baz");
            cm.addLineClass(1, "wrap", "foo");
            cm.addLineClass(1, "gutter", "gutter-class");
            cls(0, "foo bar", null, null, null);
            cls(1, null, "baz", "foo", "gutter-class");
            var lines = cm.display.lineDiv;
            eq(byClassName(lines, "foo").length, 2);
            eq(byClassName(lines, "bar").length, 1);
            eq(byClassName(lines, "baz").length, 1);
            eq(byClassName(lines, "gutter-class").length, 1);
            cm.removeLineClass(0, "text", "foo");
            cls(0, "bar", null, null, null);
            cm.removeLineClass(0, "text", "foo");
            cls(0, "bar", null, null, null);
            cm.removeLineClass(0, "text", "bar");
            cls(0, null, null, null);
          
            cm.addLineClass(1, "wrap", "quux");
            cls(1, null, "baz", "foo quux", "gutter-class");
            cm.removeLineClass(1, "wrap");
            cls(1, null, "baz", null, "gutter-class");
            cm.removeLineClass(1, "gutter", "gutter-class");
            eq(byClassName(lines, "gutter-class").length, 0);
            cls(1, null, "baz", null, null);
          
            cm.addLineClass(1, "gutter", "gutter-class");
            cls(1, null, "baz", null, "gutter-class");
            cm.removeLineClass(1, "gutter", "gutter-class");
            cls(1, null, "baz", null, null);
          
          }, {value: "hohoho\n", lineNumbers: true});
          
          testCM("atomicMarker", function(cm) {
            addDoc(cm, 10, 10);
            function atom(ll, cl, lr, cr, li, ri) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr),
                                 {atomic: true, inclusiveLeft: li, inclusiveRight: ri});
            }
            var m = atom(0, 1, 0, 5);
            cm.setCursor(Pos(0, 1));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 1));
            m.clear();
            m = atom(0, 0, 0, 5, true);
            eqPos(cm.getCursor(), Pos(0, 5), "pushed out");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            m.clear();
            m = atom(8, 4, 9, 10, false, true);
            cm.setCursor(Pos(9, 8));
            eqPos(cm.getCursor(), Pos(8, 4), "set");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(8, 4), "char right");
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(8, 4), "line down");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(8, 3));
            m.clear();
            m = atom(1, 1, 3, 8);
            cm.setCursor(Pos(0, 0));
            cm.setCursor(Pos(2, 0));
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("delCharBefore");
            eq(cm.getValue().length, 80, "del chunk");
            m = atom(3, 0, 5, 5);
            cm.setCursor(Pos(3, 0));
            cm.execCommand("delWordAfter");
            eq(cm.getValue().length, 53, "del chunk");
          });
          
          testCM("selectionBias", function(cm) {
            cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true});
            cm.setCursor(Pos(0, 2));
            eqPos(cm.getCursor(), Pos(0, 3));
            cm.setCursor(Pos(0, 2));
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setCursor(Pos(0, 2), null, {bias: -1});
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setCursor(Pos(0, 4));
            cm.setCursor(Pos(0, 2), null, {bias: 1});
            eqPos(cm.getCursor(), Pos(0, 3));
          }, {value: "12345"});
          
          testCM("selectionHomeEnd", function(cm) {
            cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true});
            cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true});
            cm.setCursor(Pos(1, 2));
            cm.execCommand("goLineStart");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(1, 3));
          }, {value: "ab\ncdef\ngh"});
          
          testCM("readOnlyMarker", function(cm) {
            function mark(ll, cl, lr, cr, at) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr),
                                 {readOnly: true, atomic: at});
            }
            var m = mark(0, 1, 0, 4);
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi", "end");
            eqPos(cm.getCursor(), Pos(0, 2));
            eq(cm.getLine(0), "abcde");
            cm.execCommand("selectAll");
            cm.replaceSelection("oops", "around");
            eq(cm.getValue(), "oopsbcd");
            cm.undo();
            eqPos(m.find().from, Pos(0, 1));
            eqPos(m.find().to, Pos(0, 4));
            m.clear();
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi", "around");
            eq(cm.getLine(0), "abhicde");
            eqPos(cm.getCursor(), Pos(0, 4));
            m = mark(0, 2, 2, 2, true);
            cm.setSelection(Pos(1, 1), Pos(2, 4));
            cm.replaceSelection("t", "end");
            eqPos(cm.getCursor(), Pos(2, 3));
            eq(cm.getLine(2), "klto");
            cm.execCommand("goCharLeft");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.setSelection(Pos(0, 1), Pos(0, 3));
            cm.replaceSelection("xx", "around");
            eqPos(cm.getCursor(), Pos(0, 3));
            eq(cm.getLine(0), "axxhicde");
          }, {value: "abcde\nfghij\nklmno\n"});
          
          testCM("dirtyBit", function(cm) {
            eq(cm.isClean(), true);
            cm.replaceSelection("boo", null, "test");
            eq(cm.isClean(), false);
            cm.undo();
            eq(cm.isClean(), true);
            cm.replaceSelection("boo", null, "test");
            cm.replaceSelection("baz", null, "test");
            cm.undo();
            eq(cm.isClean(), false);
            cm.markClean();
            eq(cm.isClean(), true);
            cm.undo();
            eq(cm.isClean(), false);
            cm.redo();
            eq(cm.isClean(), true);
          });
          
          testCM("changeGeneration", function(cm) {
            cm.replaceSelection("x");
            var softGen = cm.changeGeneration();
            cm.replaceSelection("x");
            cm.undo();
            eq(cm.getValue(), "");
            is(!cm.isClean(softGen));
            cm.replaceSelection("x");
            var hardGen = cm.changeGeneration(true);
            cm.replaceSelection("x");
            cm.undo();
            eq(cm.getValue(), "x");
            is(cm.isClean(hardGen));
          });
          
          testCM("addKeyMap", function(cm) {
            function sendKey(code) {
              cm.triggerOnKeyDown({type: "keydown", keyCode: code,
                                   preventDefault: function(){}, stopPropagation: function(){}});
            }
          
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 1));
            var test = 0;
            var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }}
            cm.addKeyMap(map1);
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 1));
            eq(test, 1);
            cm.addKeyMap(map2, true);
            sendKey(39);
            eq(test, 2);
            cm.removeKeyMap(map1);
            sendKey(39);
            eq(test, 12);
            cm.removeKeyMap(map2);
            sendKey(39);
            eq(test, 12);
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"});
            sendKey(39);
            eq(test, 55);
            cm.removeKeyMap("mymap");
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 3));
          }, {value: "abc"});
          
          testCM("findPosH", function(cm) {
            forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1},
                     {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true},
                     {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"},
                     {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"},
                     {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true},
                     {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"},
                     {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"},
                     {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"},
                     {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"},
                     {from: Pos(1, 15), to: Pos(1, 10), by: -5},
                     {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"},
                     {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true},
                     {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true},
                     {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) {
              var r = cm.findPosH(t.from, t.by, t.unit || "char");
              eqPos(r, t.to);
              eq(!!r.hitSide, !!t.hitSide);
            });
          }, {value: "line one\nline two.something.other\n"});
          
          testCM("beforeChange", function(cm) {
            cm.on("beforeChange", function(cm, change) {
              var text = [];
              for (var i = 0; i < change.text.length; ++i)
                text.push(change.text[i].replace(/\s/g, "_"));
              change.update(null, null, text);
            });
            cm.setValue("hello, i am a\nnew document\n");
            eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
            CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) {
              if (change.from.line == 0) change.cancel();
            });
            cm.setValue("oops"); // Canceled
            eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
            cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0));
            eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey");
          }, {value: "abcdefghijk"});
          
          testCM("beforeChangeUndo", function(cm) {
            cm.replaceRange("hi", Pos(0, 0), Pos(0));
            cm.replaceRange("bye", Pos(0, 0), Pos(0));
            eq(cm.historySize().undo, 2);
            cm.on("beforeChange", function(cm, change) {
              is(!change.update);
              change.cancel();
            });
            cm.undo();
            eq(cm.historySize().undo, 0);
            eq(cm.getValue(), "bye\ntwo");
          }, {value: "one\ntwo"});
          
          testCM("beforeSelectionChange", function(cm) {
            function notAtEnd(cm, pos) {
              var len = cm.getLine(pos.line).length;
              if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);
              return pos;
            }
            cm.on("beforeSelectionChange", function(cm, obj) {
              obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor),
                           head: notAtEnd(cm, obj.ranges[0].head)}]);
            });
          
            addDoc(cm, 10, 10);
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(0, 9));
            cm.execCommand("selectAll");
            eqPos(cm.getCursor("start"), Pos(0, 0));
            eqPos(cm.getCursor("end"), Pos(9, 9));
          });
          
          testCM("change_removedText", function(cm) {
            cm.setValue("abc\ndef");
          
            var removedText = [];
            cm.on("change", function(cm, change) {
              removedText.push(change.removed);
            });
          
            cm.operation(function() {
              cm.replaceRange("xyz", Pos(0, 0), Pos(1,1));
              cm.replaceRange("123", Pos(0,0));
            });
          
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "abc\nd");
            eq(removedText[1].join("\n"), "");
          
            var removedText = [];
            cm.undo();
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "123");
            eq(removedText[1].join("\n"), "xyz");
          
            var removedText = [];
            cm.redo();
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "abc\nd");
            eq(removedText[1].join("\n"), "");
          });
          
          testCM("lineStyleFromMode", function(cm) {
            CodeMirror.defineMode("test_mode", function() {
              return {token: function(stream) {
                if (stream.match(/^\[[^\]]*\]/)) return "  line-brackets  ";
                if (stream.match(/^\([^\)]*\)/)) return "  line-background-parens  ";
                if (stream.match(/^<[^>]*>/)) return "  span  line-line  line-background-bg  ";
                stream.match(/^\s+|^\S+/);
              }};
            });
            cm.setOption("mode", "test_mode");
            var bracketElts = byClassName(cm.getWrapperElement(), "brackets");
            eq(bracketElts.length, 1, "brackets count");
            eq(bracketElts[0].nodeName, "PRE");
            is(!/brackets.*brackets/.test(bracketElts[0].className));
            var parenElts = byClassName(cm.getWrapperElement(), "parens");
            eq(parenElts.length, 1, "parens count");
            eq(parenElts[0].nodeName, "DIV");
            is(!/parens.*parens/.test(parenElts[0].className));
            eq(parenElts[0].parentElement.nodeName, "DIV");
          
            eq(byClassName(cm.getWrapperElement(), "bg").length, 1);
            eq(byClassName(cm.getWrapperElement(), "line").length, 1);
            var spanElts = byClassName(cm.getWrapperElement(), "cm-span");
            eq(spanElts.length, 2);
            is(/^\s*cm-span\s*$/.test(spanElts[0].className));
          }, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: <tag> <tag>"});
          
          testCM("lineStyleFromBlankLine", function(cm) {
            CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() {
              return {token: function(stream) { stream.skipToEnd(); return "comment"; },
                      blankLine: function() { return "line-blank"; }};
            });
            cm.setOption("mode", "lineStyleFromBlankLine_mode");
            var blankElts = byClassName(cm.getWrapperElement(), "blank");
            eq(blankElts.length, 1);
            eq(blankElts[0].nodeName, "PRE");
            cm.replaceRange("x", Pos(1, 0));
            blankElts = byClassName(cm.getWrapperElement(), "blank");
            eq(blankElts.length, 0);
          }, {value: "foo\n\nbar"});
          
          CodeMirror.registerHelper("xxx", "a", "A");
          CodeMirror.registerHelper("xxx", "b", "B");
          CodeMirror.defineMode("yyy", function() {
            return {
              token: function(stream) { stream.skipToEnd(); },
              xxx: ["a", "b", "q"]
            };
          });
          CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C");
          
          testCM("helpers", function(cm) {
            cm.setOption("mode", "yyy");
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B");
            cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}});
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C");
            cm.setOption("mode", "javascript");
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "");
          });
          
          testCM("selectionHistory", function(cm) {
            for (var i = 0; i < 3; i++) {
              cm.setExtending(true);
              cm.execCommand("goCharRight");
              cm.setExtending(false);
              cm.execCommand("goCharRight");
              cm.execCommand("goCharRight");
            }
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "c");
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "b");
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "c");
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 6));
          }, {value: "a b c d"});
          
          testCM("selectionChangeReducesRedo", function(cm) {
            cm.replaceSelection("X");
            cm.execCommand("goCharRight");
            cm.undoSelection();
            cm.execCommand("selectAll");
            cm.undoSelection();
            eq(cm.getValue(), "Xabc");
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.undoSelection();
            eq(cm.getValue(), "abc");
          }, {value: "abc"});
          
          testCM("selectionHistoryNonOverlapping", function(cm) {
            cm.setSelection(Pos(0, 0), Pos(0, 1));
            cm.setSelection(Pos(0, 2), Pos(0, 3));
            cm.execCommand("undoSelection");
            eqPos(cm.getCursor("anchor"), Pos(0, 0));
            eqPos(cm.getCursor("head"), Pos(0, 1));
          }, {value: "1234"});
          
          testCM("cursorMotionSplitsHistory", function(cm) {
            cm.replaceSelection("a");
            cm.execCommand("goCharRight");
            cm.replaceSelection("b");
            cm.replaceSelection("c");
            cm.undo();
            eq(cm.getValue(), "a1234");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.undo();
            eq(cm.getValue(), "1234");
            eqPos(cm.getCursor(), Pos(0, 0));
          }, {value: "1234"});
          
          testCM("selChangeInOperationDoesNotSplit", function(cm) {
            for (var i = 0; i < 4; i++) {
              cm.operation(function() {
                cm.replaceSelection("x");
                cm.setCursor(Pos(0, cm.getCursor().ch - 1));
              });
            }
            eqPos(cm.getCursor(), Pos(0, 0));
            eq(cm.getValue(), "xxxxa");
            cm.undo();
            eq(cm.getValue(), "a");
          }, {value: "a"});
          
          testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) {
            cm.replaceSelection("U", null, "foo");
            cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"});
            cm.undoSelection();
            eq(cm.getValue(), "a");
            cm.replaceSelection("V", null, "foo");
            cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"});
            cm.undoSelection();
            eq(cm.getValue(), "Va");
          }, {value: "a"});
          
          testCM("getTokenAt", function(cm) {
            var tokPlus = cm.getTokenAt(Pos(0, 2));
            eq(tokPlus.type, "operator");
            eq(tokPlus.string, "+");
            var toks = cm.getLineTokens(0);
            eq(toks.length, 3);
            forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) {
              eq(toks[i].type, expect[0]);
              eq(toks[i].string, expect[1]);
            });
          }, {value: "1+2", mode: "javascript"});
          
          testCM("getTokenTypeAt", function(cm) {
            eq(cm.getTokenTypeAt(Pos(0, 0)), "number");
            eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
            cm.addOverlay({
              token: function(stream) {
                if (stream.match("foo")) return "foo";
                else stream.next();
              }
            });
            eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1);
            eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
          }, {value: "1 + 'foo'", mode: "javascript"});
          
          testCM("resizeLineWidget", function(cm) {
            addDoc(cm, 200, 3);
            var widget = document.createElement("pre");
            widget.innerHTML = "imwidget";
            widget.style.background = "yellow";
            cm.addLineWidget(1, widget, {noHScroll: true});
            cm.setSize(40);
            is(widget.parentNode.offsetWidth < 42);
          });
          
          testCM("combinedOperations", function(cm) {
            var place = document.getElementById("testground");
            var other = CodeMirror(place, {value: "123"});
            try {
              cm.operation(function() {
                cm.addLineClass(0, "wrap", "foo");
                other.addLineClass(0, "wrap", "foo");
              });
              eq(byClassName(cm.getWrapperElement(), "foo").length, 1);
              eq(byClassName(other.getWrapperElement(), "foo").length, 1);
              cm.operation(function() {
                cm.removeLineClass(0, "wrap", "foo");
                other.removeLineClass(0, "wrap", "foo");
              });
              eq(byClassName(cm.getWrapperElement(), "foo").length, 0);
              eq(byClassName(other.getWrapperElement(), "foo").length, 0);
            } finally {
              place.removeChild(other.getWrapperElement());
            }
          }, {value: "abc"});
          
          testCM("eventOrder", function(cm) {
            var seen = [];
            cm.on("change", function() {
              if (!seen.length) cm.replaceSelection(".");
              seen.push("change");
            });
            cm.on("cursorActivity", function() {
              cm.replaceSelection("!");
              seen.push("activity");
            });
            cm.replaceSelection("/");
            eq(seen.join(","), "change,change,activity,change");
          });
          
          test("core_rmClass", function() {
            var node = document.createElement("div");
            node.className = "foo-bar baz-quux yadda";
            CodeMirror.rmClass(node, "quux");
            eq(node.className, "foo-bar baz-quux yadda");
            CodeMirror.rmClass(node, "baz-quux");
            eq(node.className, "foo-bar yadda");
            CodeMirror.rmClass(node, "yadda");
            eq(node.className, "foo-bar");
            CodeMirror.rmClass(node, "foo-bar");
            eq(node.className, "");
            node.className = " foo ";
            CodeMirror.rmClass(node, "foo");
            eq(node.className, "");
          });
          
          test("core_addClass", function() {
            var node = document.createElement("div");
            CodeMirror.addClass(node, "a");
            eq(node.className, "a");
            CodeMirror.addClass(node, "a");
            eq(node.className, "a");
            CodeMirror.addClass(node, "b");
            eq(node.className, "a b");
            CodeMirror.addClass(node, "a");
            CodeMirror.addClass(node, "b");
            eq(node.className, "a b");
          });
          
        • vim_test.js
          CodeMirror.Vim.suppressErrorLogging = true;
          
          var code = '' +
          ' wOrd1 (#%\n' +
          ' word3] \n' +
          'aopop pop 0 1 2 3 4\n' +
          ' (a) [b] {c} \n' +
          'int getchar(void) {\n' +
          '  static char buf[BUFSIZ];\n' +
          '  static char *bufp = buf;\n' +
          '  if (n == 0) {  /* buffer is empty */\n' +
          '    n = read(0, buf, sizeof buf);\n' +
          '    bufp = buf;\n' +
          '  }\n' +
          '\n' +
          '  return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' +
          ' \n' +
          '}\n';
          
          var lines = (function() {
            lineText = code.split('\n');
            var ret = [];
            for (var i = 0; i < lineText.length; i++) {
              ret[i] = {
                line: i,
                length: lineText[i].length,
                lineText: lineText[i],
                textStart: /^\s*/.exec(lineText[i])[0].length
              };
            }
            return ret;
          })();
          var endOfDocument = makeCursor(lines.length - 1,
              lines[lines.length - 1].length);
          var wordLine = lines[0];
          var bigWordLine = lines[1];
          var charLine = lines[2];
          var bracesLine = lines[3];
          var seekBraceLine = lines[4];
          
          var word1 = {
            start: { line: wordLine.line, ch: 1 },
            end: { line: wordLine.line, ch: 5 }
          };
          var word2 = {
            start: { line: wordLine.line, ch: word1.end.ch + 2 },
            end: { line: wordLine.line, ch: word1.end.ch + 4 }
          };
          var word3 = {
            start: { line: bigWordLine.line, ch: 1 },
            end: { line: bigWordLine.line, ch: 5 }
          };
          var bigWord1 = word1;
          var bigWord2 = word2;
          var bigWord3 = {
            start: { line: bigWordLine.line, ch: 1 },
            end: { line: bigWordLine.line, ch: 7 }
          };
          var bigWord4 = {
            start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 },
            end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 }
          };
          
          var oChars = [ { line: charLine.line, ch: 1 },
              { line: charLine.line, ch: 3 },
              { line: charLine.line, ch: 7 } ];
          var pChars = [ { line: charLine.line, ch: 2 },
              { line: charLine.line, ch: 4 },
              { line: charLine.line, ch: 6 },
              { line: charLine.line, ch: 8 } ];
          var numChars = [ { line: charLine.line, ch: 10 },
              { line: charLine.line, ch: 12 },
              { line: charLine.line, ch: 14 },
              { line: charLine.line, ch: 16 },
              { line: charLine.line, ch: 18 }];
          var parens1 = {
            start: { line: bracesLine.line, ch: 1 },
            end: { line: bracesLine.line, ch: 3 }
          };
          var squares1 = {
            start: { line: bracesLine.line, ch: 5 },
            end: { line: bracesLine.line, ch: 7 }
          };
          var curlys1 = {
            start: { line: bracesLine.line, ch: 9 },
            end: { line: bracesLine.line, ch: 11 }
          };
          var seekOutside = {
            start: { line: seekBraceLine.line, ch: 1 },
            end: { line: seekBraceLine.line, ch: 16 }
          };
          var seekInside = {
            start: { line: seekBraceLine.line, ch: 14 },
            end: { line: seekBraceLine.line, ch: 11 }
          };
          
          function copyCursor(cur) {
            return { ch: cur.ch, line: cur.line };
          }
          
          function forEach(arr, func) {
            for (var i = 0; i < arr.length; i++) {
              func(arr[i], i, arr);
            }
          }
          
          function testVim(name, run, opts, expectedFail) {
            var vimOpts = {
              lineNumbers: true,
              vimMode: true,
              showCursorWhenSelecting: true,
              value: code
            };
            for (var prop in opts) {
              if (opts.hasOwnProperty(prop)) {
                vimOpts[prop] = opts[prop];
              }
            }
            return test('vim_' + name, function() {
              var place = document.getElementById("testground");
              var cm = CodeMirror(place, vimOpts);
              var vim = CodeMirror.Vim.maybeInitVimState_(cm);
          
              function doKeysFn(cm) {
                return function(args) {
                  if (args instanceof Array) {
                    arguments = args;
                  }
                  for (var i = 0; i < arguments.length; i++) {
                    CodeMirror.Vim.handleKey(cm, arguments[i]);
                  }
                }
              }
              function doInsertModeKeysFn(cm) {
                return function(args) {
                  if (args instanceof Array) { arguments = args; }
                  function executeHandler(handler) {
                    if (typeof handler == 'string') {
                      CodeMirror.commands[handler](cm);
                    } else {
                      handler(cm);
                    }
                    return true;
                  }
                  for (var i = 0; i < arguments.length; i++) {
                    var key = arguments[i];
                    // Find key in keymap and handle.
                    var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler);
                    // Record for insert mode.
                    if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') {
                      var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
                      if (lastChange) {
                        lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
                      }
                    }
                  }
                }
              }
              function doExFn(cm) {
                return function(command) {
                  cm.openDialog = helpers.fakeOpenDialog(command);
                  helpers.doKeys(':');
                }
              }
              function assertCursorAtFn(cm) {
                return function(line, ch) {
                  var pos;
                  if (ch == null && typeof line.line == 'number') {
                    pos = line;
                  } else {
                    pos = makeCursor(line, ch);
                  }
                  eqPos(pos, cm.getCursor());
                }
              }
              function fakeOpenDialog(result) {
                return function(text, callback) {
                  return callback(result);
                }
              }
              function fakeOpenNotification(matcher) {
                return function(text) {
                  matcher(text);
                }
              }
              var helpers = {
                doKeys: doKeysFn(cm),
                // Warning: Only emulates keymap events, not character insertions. Use
                // replaceRange to simulate character insertions.
                // Keys are in CodeMirror format, NOT vim format.
                doInsertModeKeys: doInsertModeKeysFn(cm),
                doEx: doExFn(cm),
                assertCursorAt: assertCursorAtFn(cm),
                fakeOpenDialog: fakeOpenDialog,
                fakeOpenNotification: fakeOpenNotification,
                getRegisterController: function() {
                  return CodeMirror.Vim.getRegisterController();
                }
              }
              CodeMirror.Vim.resetVimGlobalState_();
              var successful = false;
              var savedOpenNotification = cm.openNotification;
              try {
                run(cm, vim, helpers);
                successful = true;
              } finally {
                cm.openNotification = savedOpenNotification;
                if (!successful || verbose) {
                  place.style.visibility = "visible";
                } else {
                  place.removeChild(cm.getWrapperElement());
                }
              }
            }, expectedFail);
          };
          testVim('qq@q', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'q', 'l', 'l', 'q');
            helpers.assertCursorAt(0,2);
            helpers.doKeys('@', 'q');
            helpers.assertCursorAt(0,4);
          }, { value: '            '});
          testVim('@@', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'q', 'l', 'l', 'q');
            helpers.assertCursorAt(0,2);
            helpers.doKeys('@', 'q');
            helpers.assertCursorAt(0,4);
            helpers.doKeys('@', '@');
            helpers.assertCursorAt(0,6);
          }, { value: '            '});
          var jumplistScene = ''+
            'word\n'+
            '(word)\n'+
            '{word\n'+
            'word.\n'+
            '\n'+
            'word search\n'+
            '}word\n'+
            'word\n'+
            'word\n';
          function testJumplist(name, keys, endPos, startPos, dialog) {
            endPos = makeCursor(endPos[0], endPos[1]);
            startPos = makeCursor(startPos[0], startPos[1]);
            testVim(name, function(cm, vim, helpers) {
              CodeMirror.Vim.resetVimGlobalState_();
              if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
              cm.setCursor(startPos);
              helpers.doKeys.apply(null, keys);
              helpers.assertCursorAt(endPos);
            }, {value: jumplistScene});
          };
          testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,0], [1,5]);
          testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
          testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
          testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
          testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
          testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
          testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
          testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
          testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
          testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
          testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
          testJumplist('jumplist_skip_delted_mark<c-o>',
                       ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
                       [0,2], [0,2]);
          testJumplist('jumplist_skip_delted_mark<c-i>',
                       ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
                       [1,0], [0,2]);
          
          /**
           * @param name Name of the test
           * @param keys An array of keys or a string with a single key to simulate.
           * @param endPos The expected end position of the cursor.
           * @param startPos The position the cursor should start at, defaults to 0, 0.
           */
          function testMotion(name, keys, endPos, startPos) {
            testVim(name, function(cm, vim, helpers) {
              if (!startPos) {
                startPos = { line: 0, ch: 0 };
              }
              cm.setCursor(startPos);
              helpers.doKeys(keys);
              helpers.assertCursorAt(endPos);
            });
          };
          
          function makeCursor(line, ch) {
            return { line: line, ch: ch };
          };
          
          function offsetCursor(cur, offsetLine, offsetCh) {
            return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
          };
          
          // Motion tests
          testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
          testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
          testMotion('h', 'h', makeCursor(0, 0), word1.start);
          testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
          testMotion('l', 'l', makeCursor(0, 1));
          testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
          testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
          testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
          testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
          testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
          testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
          testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
          testMotion('w', 'w', word1.start);
          testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
          testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
          testMotion('w_repeat', ['2', 'w'], word2.start);
          testMotion('w_wrap', ['w'], word3.start, word2.start);
          testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
          testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
          testMotion('W', 'W', bigWord1.start);
          testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
          testMotion('e', 'e', word1.end);
          testMotion('e_repeat', ['2', 'e'], word2.end);
          testMotion('e_wrap', 'e', word3.end, word2.end);
          testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
          testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
          testMotion('b', 'b', word3.start, word3.end);
          testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
          testMotion('b_wrap', 'b', word2.start, word3.start);
          testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
          testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
          testMotion('ge', ['g', 'e'], word2.end, word3.end);
          testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
          testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
          testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
              makeCursor(0, 0));
          testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
          testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
              makeCursor(3, 1));
          testMotion('gg_repeat', ['3', 'g', 'g'],
              makeCursor(lines[2].line, lines[2].textStart));
          testMotion('G', 'G',
              makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
              makeCursor(3, 1));
          testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
              lines[2].textStart));
          // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
          testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
          testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
          testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
          testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
          testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
          testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
          testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
              makeCursor(0, 3));
          testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
          testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
          testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
          testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
              makeCursor(charLine.line, 0));
          testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
              pChars[0]);
          testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
          testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
          testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
          testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
          testMotion('%_parens', ['%'], parens1.end, parens1.start);
          testMotion('%_squares', ['%'], squares1.end, squares1.start);
          testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
          testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
          testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
          testVim('%_seek_skip', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,9);
          }, {value:'01234"("()'});
          testVim('%_skip_string', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,4);
            cm.setCursor(0,2);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,0);
          }, {value:'(")")'});
          (')')
          testVim('%_skip_comment', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,6);
            cm.setCursor(0,3);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,0);
          }, {value:'(/*)*/)'});
          // Make sure that moving down after going to the end of a line always leaves you
          // at the end of a line, but preserves the offset in other cases
          testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['$']);
            helpers.doKeys(['j']);
            // After moving to Eol and then down, we should be at Eol of line 2
            helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
            helpers.doKeys(['j']);
            // After moving down, we should be at Eol of line 3
            helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
            helpers.doKeys(['h']);
            helpers.doKeys(['j']);
            // After moving back one space and then down, since line 4 is shorter than line 2, we should
            // be at Eol of line 2 - 1
            helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
            helpers.doKeys(['j']);
            helpers.doKeys(['j']);
            // After moving down again, since line 3 has enough characters, we should be back to the
            // same place we were at on line 1
            helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
          });
          //making sure gj and gk recover from clipping
          testVim('gj_gk_clipping', function(cm,vim,helpers){
            cm.setCursor(0, 1);
            helpers.doKeys('g','j','g','j');
            helpers.assertCursorAt(2, 1);
            helpers.doKeys('g','k','g','k');
            helpers.assertCursorAt(0, 1);
          },{value: 'line 1\n\nline 2'});
          //testing a mix of j/k and gj/gk
          testVim('j_k_and_gj_gk', function(cm,vim,helpers){
            cm.setSize(120);
            cm.setCursor(0, 0);
            //go to the last character on the first line
            helpers.doKeys('$');
            //move up/down on the column within the wrapped line
            //side-effect: cursor is not locked to eol anymore
            helpers.doKeys('g','k');
            var cur=cm.getCursor();
            eq(cur.line,0);
            is((cur.ch<176),'gk didn\'t move cursor back (1)');
            helpers.doKeys('g','j');
            helpers.assertCursorAt(0, 176);
            //should move to character 177 on line 2 (j/k preserve character index within line)
            helpers.doKeys('j');
            //due to different line wrapping, the cursor can be on a different screen-x now
            //gj and gk preserve screen-x on movement, much like moveV
            helpers.doKeys('3','g','k');
            cur=cm.getCursor();
            eq(cur.line,1);
            is((cur.ch<176),'gk didn\'t move cursor back (2)');
            helpers.doKeys('g','j','2','g','j');
            //should return to the same character-index
            helpers.doKeys('k');
            helpers.assertCursorAt(0, 176);
          },{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'});
          testVim('gj_gk', function(cm, vim, helpers) {
            if (phantom) return;
            cm.setSize(120);
            // Test top of document edge case.
            cm.setCursor(0, 4);
            helpers.doKeys('g', 'j');
            helpers.doKeys('10', 'g', 'k');
            helpers.assertCursorAt(0, 4);
          
            // Test moving down preserves column position.
            helpers.doKeys('g', 'j');
            var pos1 = cm.getCursor();
            var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
            helpers.doKeys('g', 'j');
            helpers.assertCursorAt(expectedPos2);
          
            // Move to the last character
            cm.setCursor(0, 0);
            // Move left to reset HSPos
            helpers.doKeys('h');
            // Test bottom of document edge case.
            helpers.doKeys('100', 'g', 'j');
            var endingPos = cm.getCursor();
            is(endingPos != 0, 'gj should not be on wrapped line 0');
            var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
            var endingCharCoords = cm.charCoords(endingPos);
            is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
          },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
          testVim('}', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(0, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(4, 0);
            cm.setCursor(0, 0);
            helpers.doKeys('6', '}');
            helpers.assertCursorAt(5, 0);
          }, { value: 'a\n\nb\nc\n\nd' });
          testVim('{', function(cm, vim, helpers) {
            cm.setCursor(5, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(4, 0);
            cm.setCursor(5, 0);
            helpers.doKeys('2', '{');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(5, 0);
            helpers.doKeys('6', '{');
            helpers.assertCursorAt(0, 0);
          }, { value: 'a\n\nb\nc\n\nd' });
          testVim('paragraph motions', function(cm, vim, helpers) {
            cm.setCursor(10, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(4, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(7, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(16, 0);
          
            cm.setCursor(9, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(14, 0);
          
            cm.setCursor(6, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(7, 0);
          
            // ip inside empty space
            cm.setCursor(10, 0);
            helpers.doKeys('v', 'i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(12, 0), cm.getCursor('head'));
            helpers.doKeys('i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(13, 1), cm.getCursor('head'));
            helpers.doKeys('2', 'i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            // should switch to visualLine mode
            cm.setCursor(14, 0);
            helpers.doKeys('<Esc>', 'v', 'i', 'p');
            helpers.assertCursorAt(14, 0);
          
            cm.setCursor(14, 0);
            helpers.doKeys('<Esc>', 'V', 'i', 'p');
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            // ap inside empty space
            cm.setCursor(10, 0);
            helpers.doKeys('<Esc>', 'v', 'a', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(13, 1), cm.getCursor('head'));
            helpers.doKeys('a', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            cm.setCursor(13, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(13, 0), cm.getCursor('anchor'));
            eqPos(Pos(14, 0), cm.getCursor('head'));
          
            cm.setCursor(16, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(14, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(0, 0), cm.getCursor('anchor'));
            eqPos(Pos(4, 0), cm.getCursor('head'));
          
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'i', 'p');
            var register = helpers.getRegisterController().getRegister();
            eq('a\na\n', register.toString());
            is(register.linewise);
            helpers.doKeys('3', 'j', 'p');
            helpers.doKeys('y', 'i', 'p');
            is(register.linewise);
            eq('b\na\na\nc\n', register.toString());
          }, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' });
          
          // Operator tests
          testVim('dl', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'l');
            eq('word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dl_eol', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('d', 'l');
            eq(' word1', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 5);
          }, { value: ' word1 ' });
          testVim('dl_repeat', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('2', 'd', 'l');
            eq('ord1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' w', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dh', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'h');
            eq(' wrd1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('o', register.toString());
            is(!register.linewise);
            eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dj', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'j');
            eq(' word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' word1\nword2\n', register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2\n word3' });
          testVim('dj_end_of_document', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'j');
            eq(' word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1 ' });
          testVim('dk', function(cm, vim, helpers) {
            var curStart = makeCursor(1, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'k');
            eq(' word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' word1\nword2\n', register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2\n word3' });
          testVim('dk_start_of_document', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'k');
            eq(' word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1 ' });
          testVim('dw_space', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'w');
            eq('word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dw_word', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'w');
            eq(' word2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1 ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 word2' });
          testVim('dw_only_word', function(cm, vim, helpers) {
            // Test that if there is only 1 word left, dw deletes till the end of the
            // line.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1 ', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1 ' });
          testVim('dw_eol', function(cm, vim, helpers) {
            // Assert that dw does not delete the newline if last word to delete is at end
            // of line.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' \nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\nword2' });
          testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
            // Assert that dw does not delete the newline if last word to delete is at end
            // of line and it is followed by multiple newlines.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' \n\nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\n\nword2' });
          testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('  \nword', cm.getValue());
          }, { value: '\n  \nword' });
          testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('word', cm.getValue());
          }, { value: '\nword' });
          testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n', cm.getValue());
          }, { value: '\n\n' });
          testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n   \n', cm.getValue());
          }, { value: '  \n   \n' });
          testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n\n', cm.getValue());
          }, { value: '  \n\n' });
          testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n   \nword2', cm.getValue());
          }, { value: 'word1\n   \nword2'})
          testVim('dw_end_of_document', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('d', 'w');
            eq('\nab', cm.getValue());
          }, { value: '\nabc' });
          testVim('dw_repeat', function(cm, vim, helpers) {
            // Assert that dw does delete newline if it should go to the next line, and
            // that repeat works properly.
            cm.setCursor(0, 1);
            helpers.doKeys('d', '2', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\nword2' });
          testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'e');
            eq('\n\n', cm.getValue());
          }, { value: 'word\n\n' });
          testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('d', 'e');
            eq('wor', cm.getValue());
          }, { value: 'word\n\n\n' });
          testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'e');
            eq('', cm.getValue());
          }, { value: '   \n\n\n' });
          testVim('de_end_of_document', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('d', 'e');
            eq('\nab', cm.getValue());
          }, { value: '\nabc' });
          testVim('db_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('\n\n', cm.getValue());
          }, { value: '\n\n\n' });
          testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('\nword', cm.getValue());
          }, { value: '\n\nword' });
          testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 3);
            helpers.doKeys('d', 'b');
            eq('\n\nd', cm.getValue());
          }, { value: '\n\nword' });
          testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('', cm.getValue());
          }, { value: '\n   \n' });
          testVim('db_start_of_document', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'b');
            eq('abc\n', cm.getValue());
          }, { value: 'abc\n' });
          testVim('dge_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'g', 'e');
            // Note: In real VIM the result should be '', but it's not quite consistent,
            // since 2 newlines are deleted. But in the similar case of word\n\n, only
            // 1 newline is deleted. We'll diverge from VIM's behavior since it's much
            // easier this way.
            eq('\n', cm.getValue());
          }, { value: '\n\n' });
          testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('wor\n', cm.getValue());
          }, { value: 'word\n\n'});
          testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('', cm.getValue());
          }, { value: '\n  \n' });
          testVim('dge_start_of_document', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('bc\n', cm.getValue());
          }, { value: 'abc\n' });
          testVim('d_inclusive', function(cm, vim, helpers) {
            // Assert that when inclusive is set, the character the cursor is on gets
            // deleted too.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'e');
            eq('  ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('d_reverse', function(cm, vim, helpers) {
            // Test that deleting in reverse works.
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'b');
            eq(' word2 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\n', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2 ' });
          testVim('dd', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 1, ch: 0 });
            var expectedLineCount = cm.lineCount() - 1;
            helpers.doKeys('d', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[1].textStart);
          });
          testVim('dd_prefix_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 2, ch: 0 });
            var expectedLineCount = cm.lineCount() - 2;
            helpers.doKeys('2', 'd', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[2].textStart);
          });
          testVim('dd_motion_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 2, ch: 0 });
            var expectedLineCount = cm.lineCount() - 2;
            helpers.doKeys('d', '2', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[2].textStart);
          });
          testVim('dd_multiply_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount() - 6;
            helpers.doKeys('2', 'd', '3', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[6].textStart);
          });
          testVim('dd_lastline', function(cm, vim, helpers) {
            cm.setCursor(cm.lineCount(), 0);
            var expectedLineCount = cm.lineCount() - 1;
            helpers.doKeys('d', 'd');
            eq(expectedLineCount, cm.lineCount());
            helpers.assertCursorAt(cm.lineCount() - 1, 0);
          });
          testVim('dd_only_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            var expectedRegister = cm.getValue() + "\n";
            helpers.doKeys('d','d');
            eq(1, cm.lineCount());
            eq('', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedRegister, register.toString());
          }, { value: "thisistheonlyline" });
          // Yank commands should behave the exact same as d commands, expect that nothing
          // gets deleted.
          testVim('yw_repeat', function(cm, vim, helpers) {
            // Assert that yw does yank newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('y', '2', 'w');
            eq(' word1\nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2' });
          testVim('yy_multiply_repeat', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount();
            helpers.doKeys('2', 'y', '3', 'y');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            eqPos(curStart, cm.getCursor());
          });
          // Change commands behave like d commands except that it also enters insert
          // mode. In addition, when the change is linewise, an additional newline is
          // inserted so that insert mode starts on that line.
          testVim('cw', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('c', '2', 'w');
            eq(' word3', cm.getValue());
            helpers.assertCursorAt(0, 0);
          }, { value: 'word1 word2 word3'});
          testVim('cw_repeat', function(cm, vim, helpers) {
            // Assert that cw does delete newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('c', '2', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: ' word1\nword2' });
          testVim('cc_multiply_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount() - 5;
            helpers.doKeys('2', 'c', '3', 'c');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('cc_should_not_append_to_document', function(cm, vim, helpers) {
            var expectedLineCount = cm.lineCount();
            cm.setCursor(cm.lastLine(), 0);
            helpers.doKeys('c', 'c');
            eq(expectedLineCount, cm.lineCount());
          });
          function fillArray(val, times) {
            var arr = [];
            for (var i = 0; i < times; i++) {
              arr.push(val);
            }
            return arr;
          }
          testVim('c_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'c');
            var replacement = fillArray('hello', 3);
            cm.replaceSelections(replacement);
            eq('1hello\n5hello\nahellofg', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(2, 3);
            helpers.doKeys('<C-v>', '2', 'k', 'h', 'C');
            replacement = fillArray('world', 3);
            cm.replaceSelections(replacement);
            eq('1hworld\n5hworld\nahworld', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('c_visual_block_replay', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'c');
            var replacement = fillArray('fo', 3);
            cm.replaceSelections(replacement);
            eq('1fo4\n5fo8\nafodefg', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 0);
            helpers.doKeys('.');
            eq('foo4\nfoo8\nfoodefg', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          
          testVim('d_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'd');
            eq('1\n5\nafg', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('D_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'D');
            eq('1\n5\na', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          
          // Swapcase commands edit in place and do not modify registers.
          testVim('g~w_repeat', function(cm, vim, helpers) {
            // Assert that dw does delete newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('g', '~', '2', 'w');
            eq(' WORD1\nWORD2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2' });
          testVim('g~g~', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            var expectedLineCount = cm.lineCount();
            var expectedValue = cm.getValue().toUpperCase();
            helpers.doKeys('2', 'g', '~', '3', 'g', '~');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
          testVim('gu_and_gU', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 7);
            var value = cm.getValue();
            cm.setCursor(curStart);
            helpers.doKeys('2', 'g', 'U', 'w');
            eq(cm.getValue(), 'wa wb xX WC wd');
            eqPos(curStart, cm.getCursor());
            helpers.doKeys('2', 'g', 'u', 'w');
            eq(cm.getValue(), value);
          
            helpers.doKeys('2', 'g', 'U', 'B');
            eq(cm.getValue(), 'wa WB Xx wc wd');
            eqPos(makeCursor(0, 3), cm.getCursor());
          
            cm.setCursor(makeCursor(0, 4));
            helpers.doKeys('g', 'u', 'i', 'w');
            eq(cm.getValue(), 'wa wb Xx wc wd');
            eqPos(makeCursor(0, 3), cm.getCursor());
          
            // TODO: support gUgU guu
            // eqPos(makeCursor(0, 0), cm.getCursor());
          
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
          }, { value: 'wa wb xx wc wd' });
          testVim('visual_block_~', function(cm, vim, helpers) {
            cm.setCursor(1, 1);
            helpers.doKeys('<C-v>', 'l', 'l', 'j', '~');
            helpers.assertCursorAt(1, 1);
            eq('hello\nwoRLd\naBCDe', cm.getValue());
            cm.setCursor(2, 0);
            helpers.doKeys('v', 'l', 'l', '~');
            helpers.assertCursorAt(2, 0);
            eq('hello\nwoRLd\nAbcDe', cm.getValue());
          },{value: 'hello\nwOrld\nabcde' });
          testVim('._swapCase_visualBlock', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'j', 'j', 'l', '~');
            cm.setCursor(0, 3);
            helpers.doKeys('.');
            eq('HelLO\nWorLd\nAbcdE', cm.getValue());
          },{value: 'hEllo\nwOrlD\naBcDe' });
          testVim('._delete_visualBlock', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'j', 'x');
            eq('ive\ne\nsome\nsugar', cm.getValue());
            helpers.doKeys('.');
            eq('ve\n\nsome\nsugar', cm.getValue());
            helpers.doKeys('j', 'j', '.');
            eq('ve\n\nome\nugar', cm.getValue());
            helpers.doKeys('u', '<C-r>', '.');
            eq('ve\n\nme\ngar', cm.getValue());
          },{value: 'give\nme\nsome\nsugar' });
          testVim('>{motion}', function(cm, vim, helpers) {
            cm.setCursor(1, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = '   word1\n  word2\nword3 ';
            helpers.doKeys('>', 'k');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
          testVim('>>', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = '   word1\n  word2\nword3 ';
            helpers.doKeys('2', '>', '>');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
          testVim('<{motion}', function(cm, vim, helpers) {
            cm.setCursor(1, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = ' word1\nword2\nword3 ';
            helpers.doKeys('<', 'k');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: '   word1\n  word2\nword3 ', indentUnit: 2 });
          testVim('<<', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = ' word1\nword2\nword3 ';
            helpers.doKeys('2', '<', '<');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: '   word1\n  word2\nword3 ', indentUnit: 2 });
          
          // Edit tests
          function testEdit(name, before, pos, edit, after) {
            return testVim(name, function(cm, vim, helpers) {
                       var ch = before.search(pos)
                       var line = before.substring(0, ch).split('\n').length - 1;
                       if (line) {
                         ch = before.substring(0, ch).split('\n').pop().length;
                       }
                       cm.setCursor(line, ch);
                       helpers.doKeys.apply(this, edit.split(''));
                       eq(after, cm.getValue());
                     }, {value: before});
          }
          
          // These Delete tests effectively cover word-wise Change, Visual & Yank.
          // Tabs are used as differentiated whitespace to catch edge cases.
          // Normal word:
          testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
          testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
          testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
          testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
          testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
          testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
          testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
          testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
          testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
          testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
          testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
          testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
          testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
          testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
          // Big word:
          testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
          testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
          testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
          testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
          testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
          testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
          testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
          testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
          // Deleting text objects
          //    Open and close on same line
          testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz');
          testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz');
          testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz');
          testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo  baz');
          testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo  baz');
          
          testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz');
          testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz');
          testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo  baz');
          testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo  baz');
          
          testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz');
          testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz');
          testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo  baz');
          testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo  baz');
          
          //  delete around and inner b.
          testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )');
          
          //  delete around and inner B.
          testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }');
          testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }');
          
          testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }');
          testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz');
          testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz');
          testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz');
          testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz');
          testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0});
          
          //  Open and close on different lines, equally indented
          testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b');
          testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b');
          testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab');
          testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab');
          testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab');
          
          // open and close on diff lines, open indented less than close
          testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b');
          testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b');
          testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab');
          testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab');
          
          // open and close on diff lines, open indented more than close
          testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b');
          testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b');
          testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb');
          testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb');
          
          function testSelection(name, before, pos, keys, sel) {
            return testVim(name, function(cm, vim, helpers) {
                       var ch = before.search(pos)
                       var line = before.substring(0, ch).split('\n').length - 1;
                       if (line) {
                         ch = before.substring(0, ch).split('\n').pop().length;
                       }
                       cm.setCursor(line, ch);
                       helpers.doKeys.apply(this, keys.split(''));
                       eq(sel, cm.getSelection());
                     }, {value: before});
          }
          testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr');
          testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t ');
          testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr');
          testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t ');
          testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr');
          testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr');
          testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr');
          testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t');
          testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}');
          
          testVim('mouse_select', function(cm, vim, helpers) {
            cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'});
            is(cm.state.vim.visualMode);
            is(!cm.state.vim.visualLine);
            is(!cm.state.vim.visualBlock);
            helpers.doKeys('<Esc>');
            is(!cm.somethingSelected());
            helpers.doKeys('g', 'v');
            eq('cd', cm.getSelection());
          }, {value: 'abcdef'});
          
          // Operator-motion tests
          testVim('D', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('D');
            eq(' wo\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 2);
          }, { value: ' word1\nword2\n word3' });
          testVim('C', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('C');
            eq(' wo\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: ' word1\nword2\n word3' });
          testVim('Y', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('Y');
            eq(' word1\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\n word3' });
          testVim('~', function(cm, vim, helpers) {
            helpers.doKeys('3', '~');
            eq('ABCdefg', cm.getValue());
            helpers.assertCursorAt(0, 3);
          }, { value: 'abcdefg' });
          
          // Action tests
          testVim('ctrl-a', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-a>');
            eq('-9', cm.getValue());
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('2','<C-a>');
            eq('-7', cm.getValue());
          }, {value: '-10'});
          testVim('ctrl-x', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-x>');
            eq('-1', cm.getValue());
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('2','<C-x>');
            eq('-3', cm.getValue());
          }, {value: '0'});
          testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
            forEach(['<C-x>', '<C-a>'], function(key) {
              cm.setCursor(0, 0);
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 5);
              helpers.doKeys('l');
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 10);
              cm.setCursor(0, 11);
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 11);
            });
          }, {value: '__jmp1 jmp2 jmp'});
          testVim('a', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('a');
            helpers.assertCursorAt(0, 2);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('a_eol', function(cm, vim, helpers) {
            cm.setCursor(0, lines[0].length - 1);
            helpers.doKeys('a');
            helpers.assertCursorAt(0, lines[0].length);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('A_endOfSelectedArea', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'j', 'l');
            helpers.doKeys('A');
            helpers.assertCursorAt(1, 2);
            eq('vim-insert', cm.getOption('keyMap'));
          }, {value: 'foo\nbar'});
          testVim('i', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('i');
            helpers.assertCursorAt(0, 1);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('i_repeat', function(cm, vim, helpers) {
            helpers.doKeys('3', 'i');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('testtesttest', cm.getValue());
            helpers.assertCursorAt(0, 11);
          }, { value: '' });
          testVim('i_repeat_delete', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('2', 'i');
            cm.replaceRange('z', cm.getCursor());
            helpers.doInsertModeKeys('Backspace', 'Backspace');
            helpers.doKeys('<Esc>');
            eq('abe', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'abcde' });
          testVim('A', function(cm, vim, helpers) {
            helpers.doKeys('A');
            helpers.assertCursorAt(0, lines[0].length);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('A_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'A');
            var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
            replacement.pop();
            cm.replaceSelections(replacement);
            eq('testhello\nmehello\npleahellose', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 0);
            helpers.doKeys('.');
            // TODO this doesn't work yet
            // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue());
          }, {value: 'test\nme\nplease'});
          testVim('I', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('I');
            helpers.assertCursorAt(0, lines[0].textStart);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('I_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('3', 'I');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('testtesttestblah', cm.getValue());
            helpers.assertCursorAt(0, 11);
          }, { value: 'blah' });
          testVim('I_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'I');
            var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
            replacement.pop();
            cm.replaceSelections(replacement);
            eq('hellotest\nhellome\nhelloplease', cm.getValue());
          }, {value: 'test\nme\nplease'});
          testVim('o', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('o');
            eq('word1\n\nword2', cm.getValue());
            helpers.assertCursorAt(1, 0);
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'word1\nword2' });
          testVim('o_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('3', 'o');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('\ntest\ntest\ntest', cm.getValue());
            helpers.assertCursorAt(3, 3);
          }, { value: '' });
          testVim('O', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('O');
            eq('\nword1\nword2', cm.getValue());
            helpers.assertCursorAt(0, 0);
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'word1\nword2' });
          testVim('J', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('J');
            var expectedValue = 'word1  word2\nword3\n word4';
            eq(expectedValue, cm.getValue());
            helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
          }, { value: 'word1 \n    word2\nword3\n word4' });
          testVim('J_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('3', 'J');
            var expectedValue = 'word1  word2 word3\n word4';
            eq(expectedValue, cm.getValue());
            helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
          }, { value: 'word1 \n    word2\nword3\n word4' });
          testVim('p', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
            helpers.doKeys('p');
            eq('__abc\ndef_', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_register', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
            helpers.doKeys('"', 'a', 'p');
            eq('__abc\ndef_', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_wrong_register', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
            helpers.doKeys('p');
            eq('___', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: '___' });
          testVim('p_line', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd\n', true);
            helpers.doKeys('2', 'p');
            eq('___\n  a\nd\n  a\nd', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_lastline', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd', true);
            helpers.doKeys('2', 'p');
            eq('___\n  a\nd\n  a\nd', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys(']', 'p');
            eq('  ___\n  abc\n    def', cm.getValue());
          }, { value: '  ___' });
          testVim(']p_first_indent_is_larger', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '    abc\n  def\n', true);
            helpers.doKeys(']', 'p');
            eq('  ___\n  abc\ndef', cm.getValue());
          }, { value: '  ___' });
          testVim(']p_with_tab_indents', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true);
            helpers.doKeys(']', 'p');
            eq('\t___\n\tabc\n\t\tdef', cm.getValue());
          }, { value: '\t___', indentWithTabs: true});
          testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys(']', 'p');
            eq('\t___\n\tabc\n\t\tdef', cm.getValue());
          }, { value: '\t___', indentWithTabs: true, tabSize: 2 });
          testVim('[p', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys('[', 'p');
            eq('  abc\n    def\n  ___', cm.getValue());
          }, { value: '  ___' });
          testVim('P', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
            helpers.doKeys('P');
            eq('_abc\ndef__', cm.getValue());
            helpers.assertCursorAt(1, 3);
          }, { value: '___' });
          testVim('P_line', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd\n', true);
            helpers.doKeys('2', 'P');
            eq('  a\nd\n  a\nd\n___', cm.getValue());
            helpers.assertCursorAt(0, 2);
          }, { value: '___' });
          testVim('r', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('3', 'r', 'u');
            eq('wuuuet\nanother', cm.getValue(),'3r failed');
            helpers.assertCursorAt(0, 3);
            cm.setCursor(0, 4);
            helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
            eq('wuuu  \n    her', cm.getValue(),'Replacing selection by space-characters failed');
          }, { value: 'wordet\nanother' });
          testVim('r_visual_block', function(cm, vim, helpers) {
            cm.setCursor(2, 3);
            helpers.doKeys('<C-v>', 'k', 'k', 'h', 'h', 'r', 'l');
            eq('1lll\n5lll\nalllefg', cm.getValue());
            helpers.doKeys('<C-v>', 'l', 'j', 'r', '<Space>');
            eq('1  l\n5  l\nalllefg', cm.getValue());
            cm.setCursor(2, 0);
            helpers.doKeys('o');
            helpers.doKeys('<Esc>');
            cm.replaceRange('\t\t', cm.getCursor());
            helpers.doKeys('<C-v>', 'h', 'h', 'r', 'r');
            eq('1  l\n5  l\nalllefg\nrrrrrrrr', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('R', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('R');
            helpers.assertCursorAt(0, 1);
            eq('vim-replace', cm.getOption('keyMap'));
            is(cm.state.overwrite, 'Setting overwrite state failed');
          });
          testVim('mark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 't');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(2, 0);
            cm.replaceRange('   h', cm.getCursor());
            cm.setCursor(0, 0);
            helpers.doKeys('\'', 't');
            helpers.assertCursorAt(2, 3);
          });
          testVim('jumpToMark_next', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(0, 0);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(0, 0);
            helpers.doKeys('2', ']', '`');
            helpers.assertCursorAt(3, 2);
            cm.setCursor(0, 0);
            helpers.doKeys('2', ']', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 2);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 4);
          });
          testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(4, 0);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(4, 0);
          });
          testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 2);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 1);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_next_action', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ']', '`');
            helpers.assertCursorAt(0, 0);
            var actual = cm.getLine(0);
            var expected = 'pop pop 0 1 2 3 4';
            eq(actual, expected, "Deleting while jumping to the next mark failed.");
          });
          testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ']', '\'');
            helpers.assertCursorAt(0, 1);
            var actual = cm.getLine(0);
            var expected = ' (a) [b] {c} '
            eq(actual, expected, "Deleting while jumping to the next mark line failed.");
          });
          testVim('jumpToMark_prev', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(4, 0);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(4, 0);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(5, 0);
            helpers.doKeys('2', '[', '`');
            helpers.assertCursorAt(3, 2);
            cm.setCursor(5, 0);
            helpers.doKeys('2', '[', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 2);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
            cm.setCursor(4, 4);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 0);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 2);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 6);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('delmark_single', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 't');
            helpers.doEx('delmarks t');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 't');
            helpers.assertCursorAt(0, 0);
          });
          testVim('delmark_range', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks b-d');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_multi', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks bcd');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_multi_space', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks b c d');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_all', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks a b-de');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(0, 0);
          });
          testVim('visual', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l');
            helpers.assertCursorAt(0, 4);
            eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
            helpers.doKeys('d');
            eq('15', cm.getValue());
          }, { value: '12345' });
          testVim('visual_yank', function(cm, vim, helpers) {
            helpers.doKeys('v', '3', 'l', 'y');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('p');
            eq('aa te test for yank', cm.getValue());
          }, { value: 'a test for yank' })
          testVim('visual_w', function(cm, vim, helpers) {
            helpers.doKeys('v', 'w');
            eq(cm.getSelection(), 'motion t');
          }, { value: 'motion test'});
          testVim('visual_initial_selection', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v');
            cm.getSelection('n');
          }, { value: 'init'});
          testVim('visual_crossover_left', function(cm, vim, helpers) {
            cm.setCursor(0, 2);
            helpers.doKeys('v', 'l', 'h', 'h');
            cm.getSelection('ro');
          }, { value: 'cross'});
          testVim('visual_crossover_left', function(cm, vim, helpers) {
            cm.setCursor(0, 2);
            helpers.doKeys('v', 'h', 'l', 'l');
            cm.getSelection('os');
          }, { value: 'cross'});
          testVim('visual_crossover_up', function(cm, vim, helpers) {
            cm.setCursor(3, 2);
            helpers.doKeys('v', 'j', 'k', 'k');
            eqPos(Pos(2, 2), cm.getCursor('head'));
            eqPos(Pos(3, 3), cm.getCursor('anchor'));
            helpers.doKeys('k');
            eqPos(Pos(1, 2), cm.getCursor('head'));
            eqPos(Pos(3, 3), cm.getCursor('anchor'));
          }, { value: 'cross\ncross\ncross\ncross\ncross\n'});
          testVim('visual_crossover_down', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('v', 'k', 'j', 'j');
            eqPos(Pos(2, 3), cm.getCursor('head'));
            eqPos(Pos(1, 2), cm.getCursor('anchor'));
            helpers.doKeys('j');
            eqPos(Pos(3, 3), cm.getCursor('head'));
            eqPos(Pos(1, 2), cm.getCursor('anchor'));
          }, { value: 'cross\ncross\ncross\ncross\ncross\n'});
          testVim('visual_exit', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'l', 'j', 'j', '<Esc>');
            eqPos(cm.getCursor('anchor'), cm.getCursor('head'));
            eq(vim.visualMode, false);
          }, { value: 'hello\nworld\nfoo' });
          testVim('visual_line', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
            eq(' 4\n 5', cm.getValue());
          }, { value: ' 1\n 2\n 3\n 4\n 5' });
          testVim('visual_block_move_to_eol', function(cm, vim, helpers) {
            // moveToEol should move all block cursors to end of line
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', 'G', '$');
            var selections = cm.getSelections().join();
            eq("123,45,6", selections);
          }, {value: '123\n45\n6'});
          testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
            // test the block selection with lines of different length
            // i.e. extending the selection
            // till the end of the longest line.
            helpers.doKeys('<C-v>', 'l', 'j', 'j', '6', 'l', 'd');
            helpers.doKeys('d', 'd', 'd', 'd');
            eq('', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) {
            // check for left side selection in case
            // of moving up to a shorter line.
            cm.replaceRange('', cm.getCursor());
            cm.setCursor(3, 4);
            helpers.doKeys('<C-v>', 'l', 'k', 'k', 'd');
            eq('hello world\n{\ntis\nsa!', cm.getValue());
          }, {value: 'hello world\n{\nthis is\nsparta!'});
          testVim('visual_block_corners', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('<C-v>', '2', 'l', 'k');
            // circle around the anchor
            // and check the selections
            var selections = cm.getSelections();
            eq('345891', selections.join(''));
            helpers.doKeys('4', 'h');
            selections = cm.getSelections();
            eq('123678', selections.join(''));
            helpers.doKeys('j', 'j');
            selections = cm.getSelections();
            eq('678abc', selections.join(''));
            helpers.doKeys('4', 'l');
            selections = cm.getSelections();
            eq('891cde', selections.join(''));
          }, {value: '12345\n67891\nabcde'});
          testVim('visual_block_mode_switch', function(cm, vim, helpers) {
            // switch between visual modes
            cm.setCursor(1, 1);
            // blockwise to characterwise visual
            helpers.doKeys('<C-v>', 'j', 'l', 'v');
            selections = cm.getSelections();
            eq('7891\nabc', selections.join(''));
            // characterwise to blockwise
            helpers.doKeys('<C-v>');
            selections = cm.getSelections();
            eq('78bc', selections.join(''));
            // blockwise to linewise visual
            helpers.doKeys('V');
            selections = cm.getSelections();
            eq('67891\nabcde', selections.join(''));
          }, {value: '12345\n67891\nabcde'});
          testVim('visual_block_crossing_short_line', function(cm, vim, helpers) {
            // visual block with long and short lines
            cm.setCursor(0, 3);
            helpers.doKeys('<C-v>', 'j', 'j', 'j');
            var selections = cm.getSelections().join();
            eq('4,,d,b', selections);
            helpers.doKeys('3', 'k');
            selections = cm.getSelections().join();
            eq('4', selections);
            helpers.doKeys('5', 'j', 'k');
            selections = cm.getSelections().join("");
            eq(10, selections.length);
          }, {value: '123456\n78\nabcdefg\nfoobar\n}\n'});
          testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3' , 'l', '<Esc>');
            eqPos(makeCursor(0, 3), cm.getCursor());
            helpers.doKeys('h', '<C-v>', '2' , 'j' ,'3' , 'l');
            eq(cm.getSelections().join(), "3456,,cdef");
            helpers.doKeys('4' , 'h');
            eq(cm.getSelections().join(), "23,8,bc");
            helpers.doKeys('2' , 'l');
            eq(cm.getSelections().join(), "34,,cd");
          }, {value: '123456\n78\nabcdefg\nfoobar'});
          
          testVim('visual_marks', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v');
            // Test visual mode marks
            cm.setCursor(2, 1);
            helpers.doKeys('\'', '<');
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('\'', '>');
            helpers.assertCursorAt(2, 0);
          });
          testVim('visual_join', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
            eq(' 1 2 3\n 4\n 5', cm.getValue());
            is(!vim.visualMode);
          }, { value: ' 1\n 2\n 3\n 4\n 5' });
          testVim('visual_join_2', function(cm, vim, helpers) {
            helpers.doKeys('G', 'V', 'g', 'g', 'J');
            eq('1 2 3 4 5 6 ', cm.getValue());
            is(!vim.visualMode);
          }, { value: '1\n2\n3\n4\n5\n6\n'});
          testVim('visual_blank', function(cm, vim, helpers) {
            helpers.doKeys('v', 'k');
            eq(vim.visualMode, true);
          }, { value: '\n' });
          testVim('reselect_visual', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v');
            helpers.assertCursorAt(0, 5);
            eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
            helpers.doKeys('v');
            cm.setCursor(1, 0);
            helpers.doKeys('v', 'l', 'l', 'p');
            eq('123456\n2345\nbar', cm.getValue());
            cm.setCursor(0, 0);
            helpers.doKeys('g', 'v');
            // here the fake cursor is at (1, 3)
            helpers.assertCursorAt(1, 4);
            eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
            helpers.doKeys('v');
            cm.setCursor(2, 0);
            helpers.doKeys('v', 'l', 'l', 'g', 'v');
            helpers.assertCursorAt(1, 4);
            eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
            helpers.doKeys('g', 'v');
            helpers.assertCursorAt(2, 3);
            eqPos(makeCursor(2, 0), cm.getCursor('anchor'));
            eq('123456\n2345\nbar', cm.getValue());
          }, { value: '123456\nfoo\nbar' });
          testVim('reselect_visual_line', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd');
            eq('foo\nand\nbar', cm.getValue());
            cm.setCursor(1, 0);
            helpers.doKeys('V', 'y', 'j');
            helpers.doKeys('V', 'p' , 'g', 'v', 'd');
            eq('foo\nand', cm.getValue());
          }, { value: 'hello\nthis\nis\nfoo\nand\nbar' });
          testVim('reselect_visual_block', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('<C-v>', 'k', 'h', '<C-v>');
            cm.setCursor(2, 1);
            helpers.doKeys('v', 'l', 'g', 'v');
            eqPos(Pos(1, 2), vim.sel.anchor);
            eqPos(Pos(0, 1), vim.sel.head);
            // Ensure selection is done with visual block mode rather than one
            // continuous range.
            eq(cm.getSelections().join(''), '23oo')
            helpers.doKeys('g', 'v');
            eqPos(Pos(2, 1), vim.sel.anchor);
            eqPos(Pos(2, 2), vim.sel.head);
            helpers.doKeys('<Esc>');
            // Ensure selection of deleted range
            cm.setCursor(1, 1);
            helpers.doKeys('v', '<C-v>', 'j', 'd', 'g', 'v');
            eq(cm.getSelections().join(''), 'or');
          }, { value: '123456\nfoo\nbar' });
          testVim('s_normal', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('s');
            helpers.doKeys('<Esc>');
            eq('ac', cm.getValue());
          }, { value: 'abc'});
          testVim('s_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v', 's');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(0, 0);
            eq('ac', cm.getValue());
          }, { value: 'abc'});
          testVim('o_visual', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys('v','l','l','l','o');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('v','v','j','j','j','o');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('O');
            helpers.doKeys('l','l')
            helpers.assertCursorAt(3, 3);
            helpers.doKeys('d');
            eq('p',cm.getValue());
          }, { value: 'abcd\nefgh\nijkl\nmnop'});
          testVim('o_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>','3','j','l','l', 'o');
            eqPos(Pos(3, 3), vim.sel.anchor);
            eqPos(Pos(0, 1), vim.sel.head);
            helpers.doKeys('O');
            eqPos(Pos(3, 1), vim.sel.anchor);
            eqPos(Pos(0, 3), vim.sel.head);
            helpers.doKeys('o');
            eqPos(Pos(0, 3), vim.sel.anchor);
            eqPos(Pos(3, 1), vim.sel.head);
          }, { value: 'abcd\nefgh\nijkl\nmnop'});
          testVim('changeCase_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'l', 'l');
            helpers.doKeys('U');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('v', 'l', 'l');
            helpers.doKeys('u');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('l', 'l', 'l', '.');
            helpers.assertCursorAt(0, 3);
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('j', '@', 'a');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(3, 0);
            helpers.doKeys('V', 'U', 'j', '.');
            eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue());
          }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'});
          testVim('changeCase_visual_block', function(cm, vim, helpers) {
            cm.setCursor(2, 1);
            helpers.doKeys('<C-v>', 'k', 'k', 'h', 'U');
            eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue());
            cm.setCursor(0, 2);
            helpers.doKeys('.');
            eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue());
            // check when last line is shorter.
            cm.setCursor(2, 2);
            helpers.doKeys('.');
            eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue());
          }, { value: 'abcdef\nghijkl\nmnopq\nfoo'});
          testVim('visual_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'l', 'l', 'y');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p');
            helpers.assertCursorAt(1, 5);
            eq('this is a\nunithitest for visual paste', cm.getValue());
            cm.setCursor(0, 0);
            // in case of pasting whole line
            helpers.doKeys('y', 'y');
            cm.setCursor(1, 6);
            helpers.doKeys('v', 'l', 'l', 'l', 'p');
            helpers.assertCursorAt(2, 0);
            eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue());
          }, { value: 'this is a\nunit test for visual paste'});
          
          // This checks the contents of the register used to paste the text
          testVim('v_paste_from_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            cm.setCursor(1, 0);
            helpers.doKeys('v', 'p');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+register/.test(text));
            });
          }, { value: 'register contents\nare not erased'});
          testVim('S_normal', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('j', 'S');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(1, 0);
            eq('aa\n\ncc', cm.getValue());
          }, { value: 'aa\nbb\ncc'});
          testVim('blockwise_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3', 'j', 'l', 'y');
            cm.setCursor(0, 2);
            // paste one char after the current cursor position
            helpers.doKeys('p');
            eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue());
            cm.setCursor(0, 0);
            helpers.doKeys('v', '4', 'l', 'y');
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3', 'j', 'p');
            eq('helheelhelo\norwold\noofo\narba', cm.getValue());
          }, { value: 'hello\nworld\nfoo\nbar'});
          testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) {
            // extend short lines in case of different line lengths.
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', 'j', 'j', 'y');
            cm.setCursor(0, 3);
            helpers.doKeys('p');
            eq('hellho\nfoo f\nbar b', cm.getValue());
          }, { value: 'hello\nfoo\nbar'});
          testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'x');
            cm.setCursor(0, 0);
            helpers.doKeys('P');
            eq('cut\nand\npaste\nme', cm.getValue());
          }, { value: 'cut\nand\npaste\nme'});
          testVim('blockwise_paste_from_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', '"', 'a', 'y');
            cm.setCursor(0, 3);
            helpers.doKeys('"', 'a', 'p');
            eq('foobfar\nhellho\nworlwd', cm.getValue());
          }, { value: 'foobar\nhello\nworld'});
          testVim('blockwise_paste_last_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'y');
            cm.setCursor(3, 0);
            helpers.doKeys('p');
            eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue());
          }, { value: 'cut\nand\npaste\nme'});
          
          testVim('S_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v', 'j', 'S');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(0, 0);
            eq('\ncc', cm.getValue());
          }, { value: 'aa\nbb\ncc'});
          
          testVim('/ and n/N', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 11);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 6);
            helpers.doKeys('N');
            helpers.assertCursorAt(0, 11);
          
            cm.setCursor(0, 0);
            helpers.doKeys('2', '/');
            helpers.assertCursorAt(1, 6);
          }, { value: 'match nope match \n nope Match' });
          testVim('/_case', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('Match');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 6);
          }, { value: 'match nope match \n nope Match' });
          testVim('/_2_pcre', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', true);
            cm.openDialog = helpers.fakeOpenDialog('(word){2}');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 9);
            helpers.doKeys('n');
            helpers.assertCursorAt(2, 1);
          }, { value: 'word\n another wordword\n wordwordword\n' });
          testVim('/_2_nopcre', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', false);
            cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 9);
            helpers.doKeys('n');
            helpers.assertCursorAt(2, 1);
          }, { value: 'word\n another wordword\n wordwordword\n' });
          testVim('/_nongreedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('aa');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('?_nongreedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('aa');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('/_greedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a+');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('?_greedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a+');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a*');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 5);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 0);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa  aa\n aa'});
          testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a*');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 0);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 5);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa  aa\n aa'});
          testVim('? and n/N', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 6);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 11);
            helpers.doKeys('N');
            helpers.assertCursorAt(1, 6);
          
            cm.setCursor(0, 0);
            helpers.doKeys('2', '?');
            helpers.assertCursorAt(0, 11);
          }, { value: 'match nope match \n nope Match' });
          testVim('*', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 22);
          
            cm.setCursor(0, 9);
            helpers.doKeys('2', '*');
            helpers.assertCursorAt(1, 8);
          }, { value: 'nomatch match nomatch match \nnomatch Match' });
          testVim('*_no_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 0);
          }, { value: ' \n match \n' });
          testVim('*_symbol', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('*');
            helpers.assertCursorAt(1, 0);
          }, { value: ' /}\n/} match \n' });
          testVim('#', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('#');
            helpers.assertCursorAt(1, 8);
          
            cm.setCursor(0, 9);
            helpers.doKeys('2', '#');
            helpers.assertCursorAt(0, 22);
          }, { value: 'nomatch match nomatch match \nnomatch Match' });
          testVim('*_seek', function(cm, vim, helpers) {
            // Should skip over space and symbols.
            cm.setCursor(0, 3);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 22);
          }, { value: '    :=  match nomatch match \nnomatch Match' });
          testVim('#', function(cm, vim, helpers) {
            // Should skip over space and symbols.
            cm.setCursor(0, 3);
            helpers.doKeys('#');
            helpers.assertCursorAt(1, 8);
          }, { value: '    :=  match nomatch match \nnomatch Match' });
          testVim('g*', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('g', '*');
            helpers.assertCursorAt(0, 18);
            cm.setCursor(0, 8);
            helpers.doKeys('3', 'g', '*');
            helpers.assertCursorAt(1, 8);
          }, { value: 'matches match alsoMatch\nmatchme matching' });
          testVim('g#', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('g', '#');
            helpers.assertCursorAt(0, 0);
            cm.setCursor(0, 8);
            helpers.doKeys('3', 'g', '#');
            helpers.assertCursorAt(1, 0);
          }, { value: 'matches match alsoMatch\nmatchme matching' });
          testVim('macro_insert', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '0', 'i');
            cm.replaceRange('foo', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q', '@', 'a');
            eq('foofoo', cm.getValue());
          }, { value: ''});
          testVim('macro_insert_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '$', 'a');
            cm.replaceRange('larry.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('a');
            cm.replaceRange('curly.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('a');
            cm.replaceRange('moe.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('@', 'a');
            // At this point, the most recent edit should be the 2nd insert change
            // inside the macro, i.e. "curly.".
            helpers.doKeys('.');
            eq('larry.curly.moe.larry.curly.curly.', cm.getValue());
          }, { value: ''});
          testVim('macro_space', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<Space>', '<Space>');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('q', 'a', '<Space>', '<Space>', 'q');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0, 6);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0, 8);
          }, { value: 'one line of text.'});
          testVim('macro_t_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 't', 'e', 'q');
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('l', '@', 'a');
            helpers.assertCursorAt(0, 6);
            helpers.doKeys('l', ';');
            helpers.assertCursorAt(0, 12);
          }, { value: 'one line of text.'});
          testVim('macro_f_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'b', 'f', 'e', 'q');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('@', 'b');
            helpers.assertCursorAt(0, 7);
            helpers.doKeys(';');
            helpers.assertCursorAt(0, 13);
          }, { value: 'one line of text.'});
          testVim('macro_slash_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'c');
            cm.openDialog = helpers.fakeOpenDialog('e');
            helpers.doKeys('/', 'q');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('@', 'c');
            helpers.assertCursorAt(0, 7);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 13);
          }, { value: 'one line of text.'});
          testVim('macro_multislash_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'd');
            cm.openDialog = helpers.fakeOpenDialog('e');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('t');
            helpers.doKeys('/', 'q');
            helpers.assertCursorAt(0, 12);
            helpers.doKeys('@', 'd');
            helpers.assertCursorAt(0, 15);
          }, { value: 'one line of text to rule them all.'});
          testVim('macro_parens', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'z', 'i');
            cm.replaceRange('(', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('e', 'a');
            cm.replaceRange(')', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('w', '@', 'z');
            helpers.doKeys('w', '@', 'z');
            eq('(see) (spot) (run)', cm.getValue());
          }, { value: 'see spot run'});
          testVim('macro_overwrite', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'z', '0', 'i');
            cm.replaceRange('I ', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('e');
            // Now replace the macro with something else.
            helpers.doKeys('q', 'z', 'a');
            cm.replaceRange('.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('e', '@', 'z');
            helpers.doKeys('e', '@', 'z');
            eq('I see. spot. run.', cm.getValue());
          }, { value: 'see spot run'});
          testVim('macro_search_f', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'f', ' ');
            helpers.assertCursorAt(0,3);
            helpers.doKeys('q', '0');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0,3);
          }, { value: 'The quick brown fox jumped over the lazy dog.'});
          testVim('macro_search_2f', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '2', 'f', ' ');
            helpers.assertCursorAt(0,9);
            helpers.doKeys('q', '0');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0,9);
          }, { value: 'The quick brown fox jumped over the lazy dog.'});
          testVim('yank_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'b', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo/.test(text));
              is(/b\s+bar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', 'l', 'j', '"', 'a', 'y');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+oo\nar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_line_to_line_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'A', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_word_to_word_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            helpers.doKeys('j', '"', 'A', 'y', 'w');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foobar/.test(text));
              is(/"\s+foobar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_line_to_word_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            helpers.doKeys('j', '"', 'A', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_word_to_line_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'A', 'y', 'w');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('macro_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'i');
            cm.replaceRange('gangnam', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('q', 'b', 'o');
            cm.replaceRange('style', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+i/.test(text));
              is(/b\s+o/.test(text));
            });
            helpers.doKeys(':');
          }, { value: ''});
          testVim('._register', function(cm,vim,helpers) {
            cm.setCursor(0,0);
            helpers.doKeys('i');
            cm.replaceRange('foo',cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/\.\s+foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim(':_register', function(cm,vim,helpers) {
            helpers.doEx('bar');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/:\s+bar/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_register_escape', function(cm, vim, helpers) {
            // Check that the register is restored if the user escapes rather than confirms.
            cm.openDialog = helpers.fakeOpenDialog('waldo');
            helpers.doKeys('/');
            var onKeyDown;
            var onKeyUp;
            var KEYCODES = {
              f: 70,
              o: 79,
              Esc: 27
            };
            cm.openDialog = function(template, callback, options) {
              onKeyDown = options.onKeyDown;
              onKeyUp = options.onKeyUp;
            };
            var close = function() {};
            helpers.doKeys('/');
            // Fake some keyboard events coming in.
            onKeyDown({keyCode: KEYCODES.f}, '', close);
            onKeyUp({keyCode: KEYCODES.f}, '', close);
            onKeyDown({keyCode: KEYCODES.o}, 'f', close);
            onKeyUp({keyCode: KEYCODES.o}, 'f', close);
            onKeyDown({keyCode: KEYCODES.o}, 'fo', close);
            onKeyUp({keyCode: KEYCODES.o}, 'fo', close);
            onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close);
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/waldo/.test(text));
              is(!/foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_register', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('foo');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/\/\s+foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_history', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('this');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('checks');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('search');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('history');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('checks');
            helpers.doKeys('/');
            var onKeyDown;
            var onKeyUp;
            var query = '';
            var keyCodes = {
              Up: 38,
              Down: 40
            };
            cm.openDialog = function(template, callback, options) {
              onKeyUp = options.onKeyUp;
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') query = newVal;
            }
            helpers.doKeys('/');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'checks');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'history');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'search');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'this');
            onKeyDown({keyCode: keyCodes.Down}, query, close);
            onKeyUp({keyCode: keyCodes.Down}, query, close);
            eq(query, 'search');
          }, {value: ''});
          testVim('exCommand_history', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('registers');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('sort');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('map');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('invalid');
            helpers.doKeys(':');
            var onKeyDown;
            var onKeyUp;
            var input = '';
            var keyCodes = {
              Up: 38,
              Down: 40,
              s: 115
            };
            cm.openDialog = function(template, callback, options) {
              onKeyUp = options.onKeyUp;
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') input = newVal;
            }
            helpers.doKeys(':');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'invalid');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'map');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'sort');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'registers');
            onKeyDown({keyCode: keyCodes.s}, '', close);
            input = 's';
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'sort');
          }, {value: ''});
          testVim('.', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('2', 'd', 'w');
            helpers.doKeys('.');
            eq('5 6', cm.getValue());
          }, { value: '1 2 3 4 5 6'});
          testVim('._repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('2', 'd', 'w');
            helpers.doKeys('3', '.');
            eq('6', cm.getValue());
          }, { value: '1 2 3 4 5 6'});
          testVim('._insert', function(cm, vim, helpers) {
            helpers.doKeys('i');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('testestt', cm.getValue());
            helpers.assertCursorAt(0, 6);
          }, { value: ''});
          testVim('._insert_repeat', function(cm, vim, helpers) {
            helpers.doKeys('i');
            cm.replaceRange('test', cm.getCursor());
            cm.setCursor(0, 4);
            helpers.doKeys('<Esc>');
            helpers.doKeys('2', '.');
            eq('testesttestt', cm.getValue());
            helpers.assertCursorAt(0, 10);
          }, { value: ''});
          testVim('._repeat_insert', function(cm, vim, helpers) {
            helpers.doKeys('3', 'i');
            cm.replaceRange('te', cm.getCursor());
            cm.setCursor(0, 2);
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('tetettetetee', cm.getValue());
            helpers.assertCursorAt(0, 10);
          }, { value: ''});
          testVim('._insert_o', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            cm.setCursor(1, 1);
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('\nz\nz', cm.getValue());
            helpers.assertCursorAt(2, 0);
          }, { value: ''});
          testVim('._insert_o_repeat', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(1, 0);
            helpers.doKeys('2', '.');
            eq('\nz\nz\nz', cm.getValue());
            helpers.assertCursorAt(3, 0);
          }, { value: ''});
          testVim('._insert_o_indent', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(1, 2);
            helpers.doKeys('.');
            eq('{\n  z\n  z', cm.getValue());
            helpers.assertCursorAt(2, 2);
          }, { value: '{'});
          testVim('._insert_cw', function(cm, vim, helpers) {
            helpers.doKeys('c', 'w');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 3);
            helpers.doKeys('2', 'l');
            helpers.doKeys('.');
            eq('test test word3', cm.getValue());
            helpers.assertCursorAt(0, 8);
          }, { value: 'word1 word2 word3' });
          testVim('._insert_cw_repeat', function(cm, vim, helpers) {
            // For some reason, repeat cw in desktop VIM will does not repeat insert mode
            // changes. Will conform to that behavior.
            helpers.doKeys('c', 'w');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 4);
            helpers.doKeys('l');
            helpers.doKeys('2', '.');
            eq('test test', cm.getValue());
            helpers.assertCursorAt(0, 8);
          }, { value: 'word1 word2 word3' });
          testVim('._delete', function(cm, vim, helpers) {
            cm.setCursor(0, 5);
            helpers.doKeys('i');
            helpers.doInsertModeKeys('Backspace');
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('zace', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'zabcde'});
          testVim('._delete_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('i');
            helpers.doInsertModeKeys('Backspace');
            helpers.doKeys('<Esc>');
            helpers.doKeys('2', '.');
            eq('zzce', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'zzabcde'});
          testVim('._visual_>', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('V', 'j', '>');
            cm.setCursor(2, 0)
            helpers.doKeys('.');
            eq('  1\n  2\n  3\n  4', cm.getValue());
            helpers.assertCursorAt(2, 2);
          }, { value: '1\n2\n3\n4'});
          testVim('f;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(9, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('F;', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('F', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(2, cm.getCursor().ch);
          }, { value: '01x3xx6x8x'});
          testVim('t;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(8, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('T;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(2, cm.getCursor().ch);
          }, { value: '0xx3xx678x'});
          testVim('f,', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('f', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(2, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('F,', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('F', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(9, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('t,', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('t', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(3, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('T,', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('T', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(8, cm.getCursor().ch);
          }, { value: '01x3xx67xx'});
          testVim('fd,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ';');
            eq('56789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ',');
            eq('01239', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fd,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ';');
            eq('01239', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ',');
            eq('56789', cm.getValue());
          }, { value: '0123456789'});
          testVim('td,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ';');
            eq('456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ',');
            eq('012349', cm.getValue());
          }, { value: '0123456789'});
          testVim('Td,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ';');
            eq('012349', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ',');
            eq('456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('fc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ';', '<Esc>');
            eq('56789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ',');
            eq('01239', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ';', '<Esc>');
            eq('01239', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ',');
            eq('56789', cm.getValue());
          }, { value: '0123456789'});
          testVim('tc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ';', '<Esc>');
            eq('456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ',');
            eq('012349', cm.getValue());
          }, { value: '0123456789'});
          testVim('Tc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ';', '<Esc>');
            eq('012349', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ',');
            eq('456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('fy,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ';', 'P');
            eq('012340123456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ',', 'P');
            eq('012345678456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fy,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ';', 'p');
            eq('012345678945678', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ',', 'P');
            eq('012340123456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('ty,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ';', 'P');
            eq('01230123456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ',', 'p');
            eq('01234567895678', cm.getValue());
          }, { value: '0123456789'});
          testVim('Ty,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ';', 'p');
            eq('01234567895678', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ',', 'P');
            eq('01230123456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('HML', function(cm, vim, helpers) {
            var lines = 35;
            var textHeight = cm.defaultTextHeight();
            cm.setSize(600, lines*textHeight);
            cm.setCursor(120, 0);
            helpers.doKeys('H');
            helpers.assertCursorAt(86, 2);
            helpers.doKeys('L');
            helpers.assertCursorAt(120, 4);
            helpers.doKeys('M');
            helpers.assertCursorAt(103,4);
          }, { value: (function(){
            var lines = new Array(100);
            var upper = '  xx\n';
            var lower = '    xx\n';
            upper = lines.join(upper);
            lower = lines.join(lower);
            return upper + lower;
          })()});
          
          var zVals = [];
          forEach(['zb','zz','zt','z-','z.','z<CR>'], function(e, idx){
            var lineNum = 250;
            var lines = 35;
            testVim(e, function(cm, vim, helpers) {
              var k1 = e[0];
              var k2 = e.substring(1);
              var textHeight = cm.defaultTextHeight();
              cm.setSize(600, lines*textHeight);
              cm.setCursor(lineNum, 0);
              helpers.doKeys(k1, k2);
              zVals[idx] = cm.getScrollInfo().top;
            }, { value: (function(){
              return new Array(500).join('\n');
            })()});
          });
          testVim('zb<zz', function(cm, vim, helpers){
            eq(zVals[0]<zVals[1], true);
          });
          testVim('zz<zt', function(cm, vim, helpers){
            eq(zVals[1]<zVals[2], true);
          });
          testVim('zb==z-', function(cm, vim, helpers){
            eq(zVals[0], zVals[3]);
          });
          testVim('zz==z.', function(cm, vim, helpers){
            eq(zVals[1], zVals[4]);
          });
          testVim('zt==z<CR>', function(cm, vim, helpers){
            eq(zVals[2], zVals[5]);
          });
          
          var moveTillCharacterSandbox =
            'The quick brown fox \n'
            'jumped over the lazy dog.'
          testVim('moveTillCharacter', function(cm, vim, helpers){
            cm.setCursor(0, 0);
            // Search for the 'q'.
            cm.openDialog = helpers.fakeOpenDialog('q');
            helpers.doKeys('/');
            eq(4, cm.getCursor().ch);
            // Jump to just before the first o in the list.
            helpers.doKeys('t');
            helpers.doKeys('o');
            eq('The quick brown fox \n', cm.getValue());
            // Delete that one character.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('o');
            eq('The quick bown fox \n', cm.getValue());
            // Delete everything until the next 'o'.
            helpers.doKeys('.');
            eq('The quick box \n', cm.getValue());
            // An unmatched character should have no effect.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('q');
            eq('The quick box \n', cm.getValue());
            // Matches should only be possible on single lines.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('z');
            eq('The quick box \n', cm.getValue());
            // After all that, the search for 'q' should still be active, so the 'N' command
            // can run it again in reverse. Use that to delete everything back to the 'q'.
            helpers.doKeys('d');
            helpers.doKeys('N');
            eq('The ox \n', cm.getValue());
            eq(4, cm.getCursor().ch);
          }, { value: moveTillCharacterSandbox});
          testVim('searchForPipe', function(cm, vim, helpers){
            CodeMirror.Vim.setOption('pcre', false);
            cm.setCursor(0, 0);
            // Search for the '|'.
            cm.openDialog = helpers.fakeOpenDialog('|');
            helpers.doKeys('/');
            eq(4, cm.getCursor().ch);
          }, { value: 'this|that'});
          
          
          var scrollMotionSandbox =
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n';
          testVim('scrollMotion', function(cm, vim, helpers){
            var prevCursor, prevScrollInfo;
            cm.setCursor(0, 0);
            // ctrl-y at the top of the file should have no effect.
            helpers.doKeys('<C-y>');
            eq(0, cm.getCursor().line);
            prevScrollInfo = cm.getScrollInfo();
            helpers.doKeys('<C-e>');
            eq(1, cm.getCursor().line);
            is(prevScrollInfo.top < cm.getScrollInfo().top);
            // Jump to the end of the sandbox.
            cm.setCursor(1000, 0);
            prevCursor = cm.getCursor();
            // ctrl-e at the bottom of the file should have no effect.
            helpers.doKeys('<C-e>');
            eq(prevCursor.line, cm.getCursor().line);
            prevScrollInfo = cm.getScrollInfo();
            helpers.doKeys('<C-y>');
            eq(prevCursor.line - 1, cm.getCursor().line, "Y");
            is(prevScrollInfo.top > cm.getScrollInfo().top);
          }, { value: scrollMotionSandbox});
          
          var squareBracketMotionSandbox = ''+
            '({\n'+//0
            '  ({\n'+//11
            '  /*comment {\n'+//2
            '            */(\n'+//3
            '#else                \n'+//4
            '  /*       )\n'+//5
            '#if        }\n'+//6
            '  )}*/\n'+//7
            ')}\n'+//8
            '{}\n'+//9
            '#else {{\n'+//10
            '{}\n'+//11
            '}\n'+//12
            '{\n'+//13
            '#endif\n'+//14
            '}\n'+//15
            '}\n'+//16
            '#else';//17
          testVim('[[, ]]', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys(']', ']');
            helpers.assertCursorAt(9,0);
            helpers.doKeys('2', ']', ']');
            helpers.assertCursorAt(13,0);
            helpers.doKeys(']', ']');
            helpers.assertCursorAt(17,0);
            helpers.doKeys('[', '[');
            helpers.assertCursorAt(13,0);
            helpers.doKeys('2', '[', '[');
            helpers.assertCursorAt(9,0);
            helpers.doKeys('[', '[');
            helpers.assertCursorAt(0,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[], ][', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys(']', '[');
            helpers.assertCursorAt(12,0);
            helpers.doKeys('2', ']', '[');
            helpers.assertCursorAt(16,0);
            helpers.doKeys(']', '[');
            helpers.assertCursorAt(17,0);
            helpers.doKeys('[', ']');
            helpers.assertCursorAt(16,0);
            helpers.doKeys('2', '[', ']');
            helpers.assertCursorAt(12,0);
            helpers.doKeys('[', ']');
            helpers.assertCursorAt(0,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[{, ]}', function(cm, vim, helpers) {
            cm.setCursor(4, 10);
            helpers.doKeys('[', '{');
            helpers.assertCursorAt(2,12);
            helpers.doKeys('2', '[', '{');
            helpers.assertCursorAt(0,1);
            cm.setCursor(4, 10);
            helpers.doKeys(']', '}');
            helpers.assertCursorAt(6,11);
            helpers.doKeys('2', ']', '}');
            helpers.assertCursorAt(8,1);
            cm.setCursor(0,1);
            helpers.doKeys(']', '}');
            helpers.assertCursorAt(8,1);
            helpers.doKeys('[', '{');
            helpers.assertCursorAt(0,1);
          }, { value: squareBracketMotionSandbox});
          testVim('[(, ])', function(cm, vim, helpers) {
            cm.setCursor(4, 10);
            helpers.doKeys('[', '(');
            helpers.assertCursorAt(3,14);
            helpers.doKeys('2', '[', '(');
            helpers.assertCursorAt(0,0);
            cm.setCursor(4, 10);
            helpers.doKeys(']', ')');
            helpers.assertCursorAt(5,11);
            helpers.doKeys('2', ']', ')');
            helpers.assertCursorAt(8,0);
            helpers.doKeys('[', '(');
            helpers.assertCursorAt(0,0);
            helpers.doKeys(']', ')');
            helpers.assertCursorAt(8,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
            forEach(['*', '/'], function(key){
              cm.setCursor(7, 0);
              helpers.doKeys('2', '[', key);
              helpers.assertCursorAt(2,2);
              helpers.doKeys('2', ']', key);
              helpers.assertCursorAt(7,5);
            });
          }, { value: squareBracketMotionSandbox});
          testVim('[#, ]#', function(cm, vim, helpers) {
            cm.setCursor(10, 3);
            helpers.doKeys('2', '[', '#');
            helpers.assertCursorAt(4,0);
            helpers.doKeys('5', ']', '#');
            helpers.assertCursorAt(17,0);
            cm.setCursor(10, 3);
            helpers.doKeys(']', '#');
            helpers.assertCursorAt(14,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
            cm.setCursor(11, 0);
            helpers.doKeys('[', 'm');
            helpers.assertCursorAt(10,7);
            helpers.doKeys('4', '[', 'm');
            helpers.assertCursorAt(1,3);
            helpers.doKeys('5', ']', 'm');
            helpers.assertCursorAt(11,0);
            helpers.doKeys('[', 'M');
            helpers.assertCursorAt(9,1);
            helpers.doKeys('3', ']', 'M');
            helpers.assertCursorAt(15,0);
            helpers.doKeys('5', '[', 'M');
            helpers.assertCursorAt(7,3);
          }, { value: squareBracketMotionSandbox});
          
          // Ex mode tests
          testVim('ex_go_to_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('4');
            helpers.assertCursorAt(3, 0);
          }, { value: 'a\nb\nc\nd\ne\n'});
          testVim('ex_write', function(cm, vim, helpers) {
            var tmp = CodeMirror.commands.save;
            var written;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            // Test that w, wr, wri ... write all trigger :write.
            var command = 'write';
            for (var i = 1; i < command.length; i++) {
              written = false;
              actualCm = null;
              helpers.doEx(command.substring(0, i));
              eq(written, true);
              eq(actualCm, cm);
            }
            CodeMirror.commands.save = tmp;
          });
          testVim('ex_sort', function(cm, vim, helpers) {
            helpers.doEx('sort');
            eq('Z\na\nb\nc\nd', cm.getValue());
          }, { value: 'b\nZ\nd\nc\na'});
          testVim('ex_sort_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort!');
            eq('d\nc\nb\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_range', function(cm, vim, helpers) {
            helpers.doEx('2,3sort');
            eq('b\nc\nd\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_oneline', function(cm, vim, helpers) {
            helpers.doEx('2sort');
            // Expect no change.
            eq('b\nd\nc\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {
            helpers.doEx('sort i');
            eq('a\nb\nc\nd\nZ', cm.getValue());
          }, { value: 'b\nZ\nd\nc\na'});
          testVim('ex_sort_unique', function(cm, vim, helpers) {
            helpers.doEx('sort u');
            eq('Z\na\nb\nc\nd', cm.getValue());
          }, { value: 'b\nZ\na\na\nd\na\nc\na'});
          testVim('ex_sort_decimal', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('d3\n s5\n6\n.9', cm.getValue());
          }, { value: '6\nd3\n s5\n.9'});
          testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('z-9\nd3\n s5\n6\n.9', cm.getValue());
          }, { value: '6\nd3\n s5\n.9\nz-9'});
          testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort! d');
            eq('.9\n6\n s5\nd3', cm.getValue());
          }, { value: '6\nd3\n s5\n.9'});
          testVim('ex_sort_hex', function(cm, vim, helpers) {
            helpers.doEx('sort x');
            eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());
          }, { value: '6\nd3\n s5\n&0xB\n.9'});
          testVim('ex_sort_octal', function(cm, vim, helpers) {
            helpers.doEx('sort o');
            eq('.8\n.9\nd3\n s5\n6', cm.getValue());
          }, { value: '6\nd3\n s5\n.9\n.8'});
          testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('y\nz\nc1\nb2\na3', cm.getValue());
          }, { value: 'a3\nz\nc1\ny\nb2'});
          testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort! d');
            eq('a3\nb2\nc1\nz\ny', cm.getValue());
          }, { value: 'a3\nz\nc1\ny\nb2'});
          // test for :global command
          testVim('ex_global', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('g/one/s//two');
            eq('two two\n two two\n two two', cm.getValue());
            helpers.doEx('1,2g/two/s//one');
            eq('one one\n one one\n two two', cm.getValue());
          }, {value: 'one one\n one one\n one one'});
          testVim('ex_global_confirm', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            var onKeyDown;
            var openDialogSave = cm.openDialog;
            var KEYCODES = {
              a: 65,
              n: 78,
              q: 81,
              y: 89
            };
            // Intercept the ex command, 'global'
            cm.openDialog = function(template, callback, options) {
              // Intercept the prompt for the embedded ex command, 'substitute'
              cm.openDialog = function(template, callback, options) {
                onKeyDown = options.onKeyDown;
              };
              callback('g/one/s//two/gc');
            };
            helpers.doKeys(':');
            var close = function() {};
            onKeyDown({keyCode: KEYCODES.n}, '', close);
            onKeyDown({keyCode: KEYCODES.y}, '', close);
            onKeyDown({keyCode: KEYCODES.a}, '', close);
            onKeyDown({keyCode: KEYCODES.q}, '', close);
            onKeyDown({keyCode: KEYCODES.y}, '', close);
            eq('one two\n two two\n one one\n two one\n one one', cm.getValue());
          }, {value: 'one one\n one one\n one one\n one one\n one one'});
          // Basic substitute tests.
          testVim('ex_substitute_same_line', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('s/one/two/g');
            eq('one one\n two two', cm.getValue());
          }, { value: 'one one\n one one'});
          testVim('ex_substitute_full_file', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('%s/one/two/g');
            eq('two two\n two two', cm.getValue());
          }, { value: 'one one\n one one'});
          testVim('ex_substitute_input_range', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('1,3s/\\d/0/g');
            eq('0\n0\n0\n4', cm.getValue());
          }, { value: '1\n2\n3\n4' });
          testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            // Set last visual mode selection marks '< and '> at lines 2 and 4
            helpers.doKeys('V', '2', 'j', 'v');
            helpers.doEx('\'<,\'>s/\\d/0/g');
            eq('1\n0\n0\n0\n5', cm.getValue());
          }, { value: '1\n2\n3\n4\n5' });
          testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
            // If the query is empty, use last query.
            cm.setCursor(1, 0);
            cm.openDialog = helpers.fakeOpenDialog('1');
            helpers.doKeys('/');
            helpers.doEx('s//b/g');
            eq('abb ab2 ab3', cm.getValue());
          }, { value: 'a11 a12 a13' });
          testVim('ex_substitute_javascript', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', false);
            cm.setCursor(1, 0);
            // Throw all the things that javascript likes to treat as special values
            // into the replace part. All should be literal (this is VIM).
            helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g')
            eq('a $$ $\' $` $& 0 b', cm.getValue());
          }, { value: 'a 0 b' });
          testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('s/a/b/g');
            cm.setCursor(1, 0);
            helpers.doEx('s');
            eq('b b\nb a', cm.getValue());
          }, {value: 'a a\na a'});
          
          // More complex substitute tests that test both pcre and nopcre options.
          function testSubstitute(name, options) {
            testVim(name + '_pcre', function(cm, vim, helpers) {
              cm.setCursor(1, 0);
              CodeMirror.Vim.setOption('pcre', true);
              helpers.doEx(options.expr);
              eq(options.expectedValue, cm.getValue());
            }, options);
            // If no noPcreExpr is defined, assume that it's the same as the expr.
            var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr;
            testVim(name + '_nopcre', function(cm, vim, helpers) {
              cm.setCursor(1, 0);
              CodeMirror.Vim.setOption('pcre', false);
              helpers.doEx(noPcreExpr);
              eq(options.expectedValue, cm.getValue());
            }, options);
          }
          testSubstitute('ex_substitute_capture', {
            value: 'a11 a12 a13',
            expectedValue: 'a1111 a1212 a1313',
            // $n is a backreference
            expr: 's/(\\d+)/$1$1/g',
            // \n is a backreference.
            noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'});
          testSubstitute('ex_substitute_capture2', {
            value: 'a 0 b',
            expectedValue: 'a $00 b',
            expr: 's/(\\d+)/$$$1$1/g',
            noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'});
          testSubstitute('ex_substitute_nocapture', {
            value: 'a11 a12 a13',
            expectedValue: 'a$1$1 a$1$1 a$1$1',
            expr: 's/(\\d+)/$$1$$1/g',
            noPcreExpr: 's/\\(\\d+\\)/$1$1/g'});
          testSubstitute('ex_substitute_nocapture2', {
            value: 'a 0 b',
            expectedValue: 'a $10 b',
            expr: 's/(\\d+)/$$1$1/g',
            noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'});
          testSubstitute('ex_substitute_nocapture', {
            value: 'a b c',
            expectedValue: 'a $ c',
            expr: 's/b/$$/',
            noPcreExpr: 's/b/$/'});
          testSubstitute('ex_substitute_slash_regex', {
            value: 'one/two \n three/four',
            expectedValue: 'one|two \n three|four',
            expr: '%s/\\//|'});
          testSubstitute('ex_substitute_pipe_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'one,two \n three,four',
            expr: '%s/\\|/,/',
            noPcreExpr: '%s/|/,/'});
          testSubstitute('ex_substitute_or_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'ana|twa \n thraa|faar',
            expr: '%s/o|e|u/a/g',
            noPcreExpr: '%s/o\\|e\\|u/a/g'});
          testSubstitute('ex_substitute_or_word_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'five|five \n three|four',
            expr: '%s/(one|two)/five/g',
            noPcreExpr: '%s/\\(one\\|two\\)/five/g'});
          testSubstitute('ex_substitute_backslashslash_regex', {
            value: 'one\\two \n three\\four',
            expectedValue: 'one,two \n three,four',
            expr: '%s/\\\\/,'});
          testSubstitute('ex_substitute_slash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one/two \n three/four',
            expr: '%s/,/\\/'});
          testSubstitute('ex_substitute_backslash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one\\two \n three\\four',
            expr: '%s/,/\\\\/g'});
          testSubstitute('ex_substitute_multibackslash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes.
            expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes.
          testSubstitute('ex_substitute_braces_word', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ab abb ab{2}',
            expr: '%s/(ab){2}//g',
            noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'});
          testSubstitute('ex_substitute_braces_range', {
            value: 'a aa aaa aaaa',
            expectedValue: 'a   a',
            expr: '%s/a{2,3}//g',
            noPcreExpr: '%s/a\\{2,3\\}//g'});
          testSubstitute('ex_substitute_braces_literal', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab abb ',
            expr: '%s/ab\\{2\\}//g',
            noPcreExpr: '%s/ab{2}//g'});
          testSubstitute('ex_substitute_braces_char', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab  ab{2}',
            expr: '%s/ab{2}//g',
            noPcreExpr: '%s/ab\\{2\\}//g'});
          testSubstitute('ex_substitute_braces_no_escape', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab  ab{2}',
            expr: '%s/ab{2}//g',
            noPcreExpr: '%s/ab\\{2}//g'});
          testSubstitute('ex_substitute_count', {
            value: '1\n2\n3\n4',
            expectedValue: '1\n0\n0\n4',
            expr: 's/\\d/0/i 2'});
          testSubstitute('ex_substitute_count_with_range', {
            value: '1\n2\n3\n4',
            expectedValue: '1\n2\n0\n0',
            expr: '1,3s/\\d/0/ 3'});
          testSubstitute('ex_substitute_not_global', {
            value: 'aaa\nbaa\ncaa',
            expectedValue: 'xaa\nbxa\ncxa',
            expr: '%s/a/x/'});
          function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {
            testVim(name, function(cm, vim, helpers) {
              var savedOpenDialog = cm.openDialog;
              var savedKeyName = CodeMirror.keyName;
              var onKeyDown;
              var recordedCallback;
              var closed = true; // Start out closed, set false on second openDialog.
              function close() {
                closed = true;
              }
              // First openDialog should save callback.
              cm.openDialog = function(template, callback, options) {
                recordedCallback = callback;
              }
              // Do first openDialog.
              helpers.doKeys(':');
              // Second openDialog should save keyDown handler.
              cm.openDialog = function(template, callback, options) {
                onKeyDown = options.onKeyDown;
                closed = false;
              };
              // Return the command to Vim and trigger second openDialog.
              recordedCallback(command);
              // The event should really use keyCode, but here just mock it out and use
              // key and replace keyName to just return key.
              CodeMirror.keyName = function (e) { return e.key; }
              keys = keys.toUpperCase();
              for (var i = 0; i < keys.length; i++) {
                is(!closed);
                onKeyDown({ key: keys.charAt(i) }, '', close);
              }
              try {
                eq(expectedValue, cm.getValue());
                helpers.assertCursorAt(finalPos);
                is(closed);
              } catch(e) {
                throw e
              } finally {
                // Restore overriden functions.
                CodeMirror.keyName = savedKeyName;
                cm.openDialog = savedOpenDialog;
              }
            }, { value: initialValue });
          };
          testSubstituteConfirm('ex_substitute_confirm_emptydoc',
              '%s/x/b/c', '', '', '', makeCursor(0, 0));
          testSubstituteConfirm('ex_substitute_confirm_nomatch',
              '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));
          testSubstituteConfirm('ex_substitute_confirm_accept',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_random_keys',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_some',
              '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_all',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_accept_then_all',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_quit',
              '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_last',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_oneline',
              '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_range_accept',
              '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_some',
              '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_all',
              '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_last',
              '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));
          //:noh should clear highlighting of search-results but allow to resume search through n
          testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('?');
            helpers.doEx('noh');
            eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
          }, { value: 'match nope match \n nope Match' });
          testVim('set_boolean', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', true, 'boolean');
            // Test default value is set.
            is(CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set to non-boolean
              CodeMirror.Vim.setOption('testoption', '5');
              fail();
            } catch (expected) {};
            // Test setOption
            CodeMirror.Vim.setOption('testoption', false);
            is(!CodeMirror.Vim.getOption('testoption'));
          });
          testVim('ex_set_boolean', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', true, 'boolean');
            // Test default value is set.
            is(CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set to non-boolean
              helpers.doEx('set testoption=22');
              fail();
            } catch (expected) {};
            // Test setOption
            helpers.doEx('set notestoption');
            is(!CodeMirror.Vim.getOption('testoption'));
          });
          testVim('set_string', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', 'a', 'string');
            // Test default value is set.
            eq('a', CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set non-string.
              CodeMirror.Vim.setOption('testoption', true);
              fail();
            } catch (expected) {};
            try {
              // Test fail to set 'notestoption'
              CodeMirror.Vim.setOption('notestoption', 'b');
              fail();
            } catch (expected) {};
            // Test setOption
            CodeMirror.Vim.setOption('testoption', 'c');
            eq('c', CodeMirror.Vim.getOption('testoption'));
          });
          testVim('ex_set_string', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', 'a', 'string');
            // Test default value is set.
            eq('a', CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set 'notestoption'
              helpers.doEx('set notestoption=b');
              fail();
            } catch (expected) {};
            // Test setOption
            helpers.doEx('set testoption=c')
            eq('c', CodeMirror.Vim.getOption('testoption'));
          });
          // TODO: Reset key maps after each test.
          testVim('ex_map_key2key', function(cm, vim, helpers) {
            helpers.doEx('map a x');
            helpers.doKeys('a');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          testVim('ex_unmap_key2key', function(cm, vim, helpers) {
            helpers.doEx('unmap a');
            helpers.doKeys('a');
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'abc' });
          testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) {
            try {
              helpers.doEx('unmap a');
              fail();
            } catch (expected) {}
            helpers.doKeys('a');
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'abc' });
          testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
            helpers.doEx('map ; :');
            var dialogOpened = false;
            cm.openDialog = function() {
              dialogOpened = true;
            }
            helpers.doKeys(';');
            eq(dialogOpened, true);
          });
          testVim('ex_map_ex2key:', function(cm, vim, helpers) {
            helpers.doEx('map :del x');
            helpers.doEx('del');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          testVim('ex_map_ex2ex', function(cm, vim, helpers) {
            helpers.doEx('map :del :w');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            helpers.doEx('del');
            CodeMirror.commands.save = tmp;
            eq(written, true);
            eq(actualCm, cm);
          });
          testVim('ex_map_key2ex', function(cm, vim, helpers) {
            helpers.doEx('map a :w');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            helpers.doKeys('a');
            CodeMirror.commands.save = tmp;
            eq(written, true);
            eq(actualCm, cm);
          });
          testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) {
            CodeMirror.Vim.map('b', ':w', 'visual');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            // Mapping should not work in normal mode.
            helpers.doKeys('b');
            eq(written, false);
            // Mapping should work in visual mode.
            helpers.doKeys('v', 'b');
            eq(written, true);
            eq(actualCm, cm);
          
            CodeMirror.commands.save = tmp;
          });
          testVim('ex_imap', function(cm, vim, helpers) {
            CodeMirror.Vim.map('jk', '<Esc>', 'insert');
            helpers.doKeys('i');
            is(vim.insertMode);
            helpers.doKeys('j', 'k');
            is(!vim.insertMode);
          })
          
          // Testing registration of functions as ex-commands and mapping to <Key>-keys
          testVim('ex_api_test', function(cm, vim, helpers) {
            var res=false;
            var val='from';
            CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
              if(params.args)val=params.args[0];
              else res=true;
            });
            helpers.doEx(':ext to');
            eq(val,'to','Defining ex-command failed');
            CodeMirror.Vim.map('<C-CR><Space>',':ext');
            helpers.doKeys('<C-CR>','<Space>');
            is(res,'Mapping to key failed');
          });
          // For now, this test needs to be last because it messes up : for future tests.
          testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
            helpers.doEx('map : x');
            helpers.doKeys(':');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          
          // Test event handlers
          testVim('beforeSelectionChange', function(cm, vim, helpers) {
            cm.setCursor(0, 100);
            eqPos(cm.getCursor('head'), cm.getCursor('anchor'));
          }, { value: 'abc' });
          
          
          
      • theme
        • 3024-day.css
          /*
          
              Name:       3024 day
              Author:     Jan T. Sott (http://github.com/idleberg)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;}
          .cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;}
          .cm-s-3024-day.CodeMirror ::selection { background: #d6d5d4; }
          .cm-s-3024-day.CodeMirror ::-moz-selection { background: #d9d9d9; }
          
          .cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;}
          .cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; }
          .cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; }
          .cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;}
          
          .cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;}
          
          .cm-s-3024-day span.cm-comment {color: #cdab53;}
          .cm-s-3024-day span.cm-atom {color: #a16a94;}
          .cm-s-3024-day span.cm-number {color: #a16a94;}
          
          .cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;}
          .cm-s-3024-day span.cm-keyword {color: #db2d20;}
          .cm-s-3024-day span.cm-string {color: #fded02;}
          
          .cm-s-3024-day span.cm-variable {color: #01a252;}
          .cm-s-3024-day span.cm-variable-2 {color: #01a0e4;}
          .cm-s-3024-day span.cm-def {color: #e8bbd0;}
          .cm-s-3024-day span.cm-bracket {color: #3a3432;}
          .cm-s-3024-day span.cm-tag {color: #db2d20;}
          .cm-s-3024-day span.cm-link {color: #a16a94;}
          .cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;}
          
          .cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;}
          
        • 3024-night.css
          /*
          
              Name:       3024 night
              Author:     Jan T. Sott (http://github.com/idleberg)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;}
          .cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;}
          .cm-s-3024-night.CodeMirror ::selection { background: rgba(58, 52, 50, .99); }
          .cm-s-3024-night.CodeMirror ::-moz-selection { background: rgba(58, 52, 50, .99); }
          .cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;}
          .cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; }
          .cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; }
          .cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;}
          
          .cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;}
          
          .cm-s-3024-night span.cm-comment {color: #cdab53;}
          .cm-s-3024-night span.cm-atom {color: #a16a94;}
          .cm-s-3024-night span.cm-number {color: #a16a94;}
          
          .cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;}
          .cm-s-3024-night span.cm-keyword {color: #db2d20;}
          .cm-s-3024-night span.cm-string {color: #fded02;}
          
          .cm-s-3024-night span.cm-variable {color: #01a252;}
          .cm-s-3024-night span.cm-variable-2 {color: #01a0e4;}
          .cm-s-3024-night span.cm-def {color: #e8bbd0;}
          .cm-s-3024-night span.cm-bracket {color: #d6d5d4;}
          .cm-s-3024-night span.cm-tag {color: #db2d20;}
          .cm-s-3024-night span.cm-link {color: #a16a94;}
          .cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;}
          
          .cm-s-3024-night .CodeMirror-activeline-background {background: #2F2F2F !important;}
          .cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • ambiance-mobile.css
          .cm-s-ambiance.CodeMirror {
            -webkit-box-shadow: none;
            -moz-box-shadow: none;
            box-shadow: none;
          }
          
        • ambiance.css
          /* ambiance theme for codemirror */
          
          /* Color scheme */
          
          .cm-s-ambiance .cm-keyword { color: #cda869; }
          .cm-s-ambiance .cm-atom { color: #CF7EA9; }
          .cm-s-ambiance .cm-number { color: #78CF8A; }
          .cm-s-ambiance .cm-def { color: #aac6e3; }
          .cm-s-ambiance .cm-variable { color: #ffb795; }
          .cm-s-ambiance .cm-variable-2 { color: #eed1b3; }
          .cm-s-ambiance .cm-variable-3 { color: #faded3; }
          .cm-s-ambiance .cm-property { color: #eed1b3; }
          .cm-s-ambiance .cm-operator {color: #fa8d6a;}
          .cm-s-ambiance .cm-comment { color: #555; font-style:italic; }
          .cm-s-ambiance .cm-string { color: #8f9d6a; }
          .cm-s-ambiance .cm-string-2 { color: #9d937c; }
          .cm-s-ambiance .cm-meta { color: #D2A8A1; }
          .cm-s-ambiance .cm-qualifier { color: yellow; }
          .cm-s-ambiance .cm-builtin { color: #9999cc; }
          .cm-s-ambiance .cm-bracket { color: #24C2C7; }
          .cm-s-ambiance .cm-tag { color: #fee4ff }
          .cm-s-ambiance .cm-attribute {  color: #9B859D; }
          .cm-s-ambiance .cm-header {color: blue;}
          .cm-s-ambiance .cm-quote { color: #24C2C7; }
          .cm-s-ambiance .cm-hr { color: pink; }
          .cm-s-ambiance .cm-link { color: #F4C20B; }
          .cm-s-ambiance .cm-special { color: #FF9D00; }
          .cm-s-ambiance .cm-error { color: #AF2018; }
          
          .cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }
          .cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }
          
          .cm-s-ambiance .CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }
          .cm-s-ambiance.CodeMirror-focused .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
          .cm-s-ambiance.CodeMirror ::selection { background: rgba(255, 255, 255, 0.10); }
          .cm-s-ambiance.CodeMirror ::-moz-selection { background: rgba(255, 255, 255, 0.10); }
          
          /* Editor styling */
          
          .cm-s-ambiance.CodeMirror {
            line-height: 1.40em;
            color: #E6E1DC;
            background-color: #202020;
            -webkit-box-shadow: inset 0 0 10px black;
            -moz-box-shadow: inset 0 0 10px black;
            box-shadow: inset 0 0 10px black;
          }
          
          .cm-s-ambiance .CodeMirror-gutters {
            background: #3D3D3D;
            border-right: 1px solid #4D4D4D;
            box-shadow: 0 10px 20px black;
          }
          
          .cm-s-ambiance .CodeMirror-linenumber {
            text-shadow: 0px 1px 1px #4d4d4d;
            color: #111;
            padding: 0 5px;
          }
          
          .cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }
          .cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }
          
          .cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {
            border-left: 1px solid #7991E8;
          }
          
          .cm-s-ambiance .CodeMirror-activeline-background {
            background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);
          }
          
          .cm-s-ambiance.CodeMirror,
          .cm-s-ambiance .CodeMirror-gutters {
            background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC");
          }
          
        • base16-dark.css
          /*
          
              Name:       Base16 Default Dark
              Author:     Chris Kempson (http://chriskempson.com)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;}
          .cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;}
          .cm-s-base16-dark.CodeMirror ::selection { background: rgba(48, 48, 48, .99); }
          .cm-s-base16-dark.CodeMirror ::-moz-selection { background: rgba(48, 48, 48, .99); }
          .cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;}
          .cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }
          .cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }
          .cm-s-base16-dark .CodeMirror-linenumber {color: #505050;}
          .cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;}
          
          .cm-s-base16-dark span.cm-comment {color: #8f5536;}
          .cm-s-base16-dark span.cm-atom {color: #aa759f;}
          .cm-s-base16-dark span.cm-number {color: #aa759f;}
          
          .cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;}
          .cm-s-base16-dark span.cm-keyword {color: #ac4142;}
          .cm-s-base16-dark span.cm-string {color: #f4bf75;}
          
          .cm-s-base16-dark span.cm-variable {color: #90a959;}
          .cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;}
          .cm-s-base16-dark span.cm-def {color: #d28445;}
          .cm-s-base16-dark span.cm-bracket {color: #e0e0e0;}
          .cm-s-base16-dark span.cm-tag {color: #ac4142;}
          .cm-s-base16-dark span.cm-link {color: #aa759f;}
          .cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;}
          
          .cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;}
          .cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • base16-light.css
          /*
          
              Name:       Base16 Default Light
              Author:     Chris Kempson (http://chriskempson.com)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;}
          .cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;}
          .cm-s-base16-light.CodeMirror ::selection { background: #e0e0e0; }
          .cm-s-base16-light.CodeMirror ::-moz-selection { background: #e0e0e0; }
          .cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;}
          .cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }
          .cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }
          .cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;}
          .cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;}
          
          .cm-s-base16-light span.cm-comment {color: #8f5536;}
          .cm-s-base16-light span.cm-atom {color: #aa759f;}
          .cm-s-base16-light span.cm-number {color: #aa759f;}
          
          .cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;}
          .cm-s-base16-light span.cm-keyword {color: #ac4142;}
          .cm-s-base16-light span.cm-string {color: #f4bf75;}
          
          .cm-s-base16-light span.cm-variable {color: #90a959;}
          .cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;}
          .cm-s-base16-light span.cm-def {color: #d28445;}
          .cm-s-base16-light span.cm-bracket {color: #202020;}
          .cm-s-base16-light span.cm-tag {color: #ac4142;}
          .cm-s-base16-light span.cm-link {color: #aa759f;}
          .cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;}
          
          .cm-s-base16-light .CodeMirror-activeline-background {background: #DDDCDC !important;}
          .cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • blackboard.css
          /* Port of TextMate's Blackboard theme */
          
          .cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }
          .cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
          .cm-s-blackboard.CodeMirror ::selection { background: rgba(37, 59, 118, .99); }
          .cm-s-blackboard.CodeMirror ::-moz-selection { background: rgba(37, 59, 118, .99); }
          .cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }
          .cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }
          .cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }
          .cm-s-blackboard .CodeMirror-linenumber { color: #888; }
          .cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
          
          .cm-s-blackboard .cm-keyword { color: #FBDE2D; }
          .cm-s-blackboard .cm-atom { color: #D8FA3C; }
          .cm-s-blackboard .cm-number { color: #D8FA3C; }
          .cm-s-blackboard .cm-def { color: #8DA6CE; }
          .cm-s-blackboard .cm-variable { color: #FF6400; }
          .cm-s-blackboard .cm-operator { color: #FBDE2D;}
          .cm-s-blackboard .cm-comment { color: #AEAEAE; }
          .cm-s-blackboard .cm-string { color: #61CE3C; }
          .cm-s-blackboard .cm-string-2 { color: #61CE3C; }
          .cm-s-blackboard .cm-meta { color: #D8FA3C; }
          .cm-s-blackboard .cm-builtin { color: #8DA6CE; }
          .cm-s-blackboard .cm-tag { color: #8DA6CE; }
          .cm-s-blackboard .cm-attribute { color: #8DA6CE; }
          .cm-s-blackboard .cm-header { color: #FF6400; }
          .cm-s-blackboard .cm-hr { color: #AEAEAE; }
          .cm-s-blackboard .cm-link { color: #8DA6CE; }
          .cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
          
          .cm-s-blackboard .CodeMirror-activeline-background {background: #3C3636 !important;}
          .cm-s-blackboard .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}
        • cobalt.css
          .cm-s-cobalt.CodeMirror { background: #002240; color: white; }
          .cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
          .cm-s-cobalt.CodeMirror ::selection { background: rgba(179, 101, 57, .99); }
          .cm-s-cobalt.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); }
          .cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }
          .cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-cobalt span.cm-comment { color: #08f; }
          .cm-s-cobalt span.cm-atom { color: #845dc4; }
          .cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
          .cm-s-cobalt span.cm-keyword { color: #ffee80; }
          .cm-s-cobalt span.cm-string { color: #3ad900; }
          .cm-s-cobalt span.cm-meta { color: #ff9d00; }
          .cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
          .cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
          .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
          .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
          .cm-s-cobalt span.cm-link { color: #845dc4; }
          .cm-s-cobalt span.cm-error { color: #9d1e15; }
          
          .cm-s-cobalt .CodeMirror-activeline-background {background: #002D57 !important;}
          .cm-s-cobalt .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}
          
        • colorforth.css
          .cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; }
          .cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; }
          .cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; }
          .cm-s-colorforth .CodeMirror-linenumber { color: #bababa; }
          .cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-colorforth span.cm-comment     { color: #ededed; }
          .cm-s-colorforth span.cm-def         { color: #ff1c1c; font-weight:bold; }
          .cm-s-colorforth span.cm-keyword     { color: #ffd900; }
          .cm-s-colorforth span.cm-builtin     { color: #00d95a; }
          .cm-s-colorforth span.cm-variable    { color: #73ff00; }
          .cm-s-colorforth span.cm-string      { color: #007bff; }
          .cm-s-colorforth span.cm-number      { color: #00c4ff; }
          .cm-s-colorforth span.cm-atom        { color: #606060; }
          
          .cm-s-colorforth span.cm-variable-2  { color: #EEE; }
          .cm-s-colorforth span.cm-variable-3  { color: #DDD; }
          .cm-s-colorforth span.cm-property    {}
          .cm-s-colorforth span.cm-operator    {}
          
          .cm-s-colorforth span.cm-meta        { color: yellow; }
          .cm-s-colorforth span.cm-qualifier   { color: #FFF700; }
          .cm-s-colorforth span.cm-bracket     { color: #cc7; }
          .cm-s-colorforth span.cm-tag         { color: #FFBD40; }
          .cm-s-colorforth span.cm-attribute   { color: #FFF700; }
          .cm-s-colorforth span.cm-error       { color: #f00; }
          
          .cm-s-colorforth .CodeMirror-selected { background: #333d53 !important; }
          
          .cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); }
          
          .cm-s-colorforth .CodeMirror-activeline-background {background: #253540 !important;}
          
        • eclipse.css
          .cm-s-eclipse span.cm-meta {color: #FF1717;}
          .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
          .cm-s-eclipse span.cm-atom {color: #219;}
          .cm-s-eclipse span.cm-number {color: #164;}
          .cm-s-eclipse span.cm-def {color: #00f;}
          .cm-s-eclipse span.cm-variable {color: black;}
          .cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
          .cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
          .cm-s-eclipse span.cm-property {color: black;}
          .cm-s-eclipse span.cm-operator {color: black;}
          .cm-s-eclipse span.cm-comment {color: #3F7F5F;}
          .cm-s-eclipse span.cm-string {color: #2A00FF;}
          .cm-s-eclipse span.cm-string-2 {color: #f50;}
          .cm-s-eclipse span.cm-qualifier {color: #555;}
          .cm-s-eclipse span.cm-builtin {color: #30a;}
          .cm-s-eclipse span.cm-bracket {color: #cc7;}
          .cm-s-eclipse span.cm-tag {color: #170;}
          .cm-s-eclipse span.cm-attribute {color: #00c;}
          .cm-s-eclipse span.cm-link {color: #219;}
          .cm-s-eclipse span.cm-error {color: #f00;}
          
          .cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • elegant.css
          .cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
          .cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
          .cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
          .cm-s-elegant span.cm-variable {color: black;}
          .cm-s-elegant span.cm-variable-2 {color: #b11;}
          .cm-s-elegant span.cm-qualifier {color: #555;}
          .cm-s-elegant span.cm-keyword {color: #730;}
          .cm-s-elegant span.cm-builtin {color: #30a;}
          .cm-s-elegant span.cm-link {color: #762;}
          .cm-s-elegant span.cm-error {background-color: #fdd;}
          
          .cm-s-elegant .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-elegant .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • erlang-dark.css
          .cm-s-erlang-dark.CodeMirror { background: #002240; color: white; }
          .cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
          .cm-s-erlang-dark.CodeMirror ::selection { background: rgba(179, 101, 57, .99); }
          .cm-s-erlang-dark.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); }
          .cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-erlang-dark .CodeMirror-guttermarker { color: white; }
          .cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-erlang-dark span.cm-atom       { color: #f133f1; }
          .cm-s-erlang-dark span.cm-attribute  { color: #ff80e1; }
          .cm-s-erlang-dark span.cm-bracket    { color: #ff9d00; }
          .cm-s-erlang-dark span.cm-builtin    { color: #eaa; }
          .cm-s-erlang-dark span.cm-comment    { color: #77f; }
          .cm-s-erlang-dark span.cm-def        { color: #e7a; }
          .cm-s-erlang-dark span.cm-keyword    { color: #ffee80; }
          .cm-s-erlang-dark span.cm-meta       { color: #50fefe; }
          .cm-s-erlang-dark span.cm-number     { color: #ffd0d0; }
          .cm-s-erlang-dark span.cm-operator   { color: #d55; }
          .cm-s-erlang-dark span.cm-property   { color: #ccc; }
          .cm-s-erlang-dark span.cm-qualifier  { color: #ccc; }
          .cm-s-erlang-dark span.cm-quote      { color: #ccc; }
          .cm-s-erlang-dark span.cm-special    { color: #ffbbbb; }
          .cm-s-erlang-dark span.cm-string     { color: #3ad900; }
          .cm-s-erlang-dark span.cm-string-2   { color: #ccc; }
          .cm-s-erlang-dark span.cm-tag        { color: #9effff; }
          .cm-s-erlang-dark span.cm-variable   { color: #50fe50; }
          .cm-s-erlang-dark span.cm-variable-2 { color: #e0e; }
          .cm-s-erlang-dark span.cm-variable-3 { color: #ccc; }
          .cm-s-erlang-dark span.cm-error      { color: #9d1e15; }
          
          .cm-s-erlang-dark .CodeMirror-activeline-background {background: #013461 !important;}
          .cm-s-erlang-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • lesser-dark.css
          /*
          http://lesscss.org/ dark theme
          Ported to CodeMirror by Peter Kroon
          */
          .cm-s-lesser-dark {
            line-height: 1.3em;
          }
          .cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
          .cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
          .cm-s-lesser-dark.CodeMirror ::selection { background: rgba(69, 68, 59, .99); }
          .cm-s-lesser-dark.CodeMirror ::-moz-selection { background: rgba(69, 68, 59, .99); }
          .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          .cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/
          
          .cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
          
          .cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }
          .cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; }
          .cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }
          
          .cm-s-lesser-dark span.cm-keyword { color: #599eff; }
          .cm-s-lesser-dark span.cm-atom { color: #C2B470; }
          .cm-s-lesser-dark span.cm-number { color: #B35E4D; }
          .cm-s-lesser-dark span.cm-def {color: white;}
          .cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
          .cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
          .cm-s-lesser-dark span.cm-variable-3 { color: white; }
          .cm-s-lesser-dark span.cm-property {color: #92A75C;}
          .cm-s-lesser-dark span.cm-operator {color: #92A75C;}
          .cm-s-lesser-dark span.cm-comment { color: #666; }
          .cm-s-lesser-dark span.cm-string { color: #BCD279; }
          .cm-s-lesser-dark span.cm-string-2 {color: #f50;}
          .cm-s-lesser-dark span.cm-meta { color: #738C73; }
          .cm-s-lesser-dark span.cm-qualifier {color: #555;}
          .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
          .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
          .cm-s-lesser-dark span.cm-tag { color: #669199; }
          .cm-s-lesser-dark span.cm-attribute {color: #00c;}
          .cm-s-lesser-dark span.cm-header {color: #a0a;}
          .cm-s-lesser-dark span.cm-quote {color: #090;}
          .cm-s-lesser-dark span.cm-hr {color: #999;}
          .cm-s-lesser-dark span.cm-link {color: #00c;}
          .cm-s-lesser-dark span.cm-error { color: #9d1e15; }
          
          .cm-s-lesser-dark .CodeMirror-activeline-background {background: #3C3A3A !important;}
          .cm-s-lesser-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • mbo.css
          /****************************************************************/
          /*   Based on mbonaci's Brackets mbo theme                      */
          /*   https://github.com/mbonaci/global/blob/master/Mbo.tmTheme  */
          /*   Create your own: http://tmtheme-editor.herokuapp.com       */
          /****************************************************************/
          
          .cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;}
          .cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;}
          .cm-s-mbo.CodeMirror ::selection { background: rgba(113, 108, 98, .99); }
          .cm-s-mbo.CodeMirror ::-moz-selection { background: rgba(113, 108, 98, .99); }
          .cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;}
          .cm-s-mbo .CodeMirror-guttermarker { color: white; }
          .cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; }
          .cm-s-mbo .CodeMirror-linenumber {color: #dadada;}
          .cm-s-mbo .CodeMirror-cursor {border-left: 1px solid #ffffec !important;}
          
          .cm-s-mbo span.cm-comment {color: #95958a;}
          .cm-s-mbo span.cm-atom {color: #00a8c6;}
          .cm-s-mbo span.cm-number {color: #00a8c6;}
          
          .cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;}
          .cm-s-mbo span.cm-keyword {color: #ffb928;}
          .cm-s-mbo span.cm-string {color: #ffcf6c;}
          .cm-s-mbo span.cm-string.cm-property {color: #ffffec;}
          
          .cm-s-mbo span.cm-variable {color: #ffffec;}
          .cm-s-mbo span.cm-variable-2 {color: #00a8c6;}
          .cm-s-mbo span.cm-def {color: #ffffec;}
          .cm-s-mbo span.cm-bracket {color: #fffffc; font-weight: bold;}
          .cm-s-mbo span.cm-tag {color: #9ddfe9;}
          .cm-s-mbo span.cm-link {color: #f54b07;}
          .cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;}
          .cm-s-mbo span.cm-qualifier {color: #ffffec;}
          
          .cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;}
          .cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;}
          .cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);}
          
        • mdn-like.css
          /*
            MDN-LIKE Theme - Mozilla
            Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
            Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
            GitHub: @peterkroon
          
            The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation
          
          */
          .cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; }
          .cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; }
          .cm-s-mdn-like.CodeMirror ::selection { background: #cfc; }
          .cm-s-mdn-like.CodeMirror ::-moz-selection { background: #cfc; }
          
          .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }
          .cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; margin-left: 3px; }
          div.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; }
          
          .cm-s-mdn-like .cm-keyword {  color: #6262FF; }
          .cm-s-mdn-like .cm-atom { color: #F90; }
          .cm-s-mdn-like .cm-number { color:  #ca7841; }
          .cm-s-mdn-like .cm-def { color: #8DA6CE; }
          .cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; }
          .cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; }
          
          .cm-s-mdn-like .cm-variable { color: #07a; }
          .cm-s-mdn-like .cm-property { color: #905; }
          .cm-s-mdn-like .cm-qualifier { color: #690; }
          
          .cm-s-mdn-like .cm-operator { color: #cda869; }
          .cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; }
          .cm-s-mdn-like .cm-string { color:#07a; font-style:italic; }
          .cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/
          .cm-s-mdn-like .cm-meta { color: #000; } /*?*/
          .cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/
          .cm-s-mdn-like .cm-tag { color: #997643; }
          .cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/
          .cm-s-mdn-like .cm-header { color: #FF6400; }
          .cm-s-mdn-like .cm-hr { color: #AEAEAE; }
          .cm-s-mdn-like .cm-link {   color:#ad9361; font-style:italic; text-decoration:none; }
          .cm-s-mdn-like .cm-error { border-bottom: 1px solid red; }
          
          div.cm-s-mdn-like .CodeMirror-activeline-background {background: #efefff;}
          div.cm-s-mdn-like span.CodeMirror-matchingbracket {outline:1px solid grey; color: inherit;}
          
          .cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); }
          
        • midnight.css
          /* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */
          
          /*<!--match-->*/
          .cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; }
          .cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; }
          
          /*<!--activeline-->*/
          .cm-s-midnight .CodeMirror-activeline-background {background: #253540 !important;}
          
          .cm-s-midnight.CodeMirror {
              background: #0F192A;
              color: #D1EDFF;
          }
          
          .cm-s-midnight.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
          
          .cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;}
          .cm-s-midnight.CodeMirror ::selection { background: rgba(49, 77, 103, .99); }
          .cm-s-midnight.CodeMirror ::-moz-selection { background: rgba(49, 77, 103, .99); }
          .cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;}
          .cm-s-midnight .CodeMirror-guttermarker { color: white; }
          .cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-midnight .CodeMirror-linenumber {color: #D0D0D0;}
          .cm-s-midnight .CodeMirror-cursor {
              border-left: 1px solid #F8F8F0 !important;
          }
          
          .cm-s-midnight span.cm-comment {color: #428BDD;}
          .cm-s-midnight span.cm-atom {color: #AE81FF;}
          .cm-s-midnight span.cm-number {color: #D1EDFF;}
          
          .cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute {color: #A6E22E;}
          .cm-s-midnight span.cm-keyword {color: #E83737;}
          .cm-s-midnight span.cm-string {color: #1DC116;}
          
          .cm-s-midnight span.cm-variable {color: #FFAA3E;}
          .cm-s-midnight span.cm-variable-2 {color: #FFAA3E;}
          .cm-s-midnight span.cm-def {color: #4DD;}
          .cm-s-midnight span.cm-bracket {color: #D1EDFF;}
          .cm-s-midnight span.cm-tag {color: #449;}
          .cm-s-midnight span.cm-link {color: #AE81FF;}
          .cm-s-midnight span.cm-error {background: #F92672; color: #F8F8F0;}
          
          .cm-s-midnight .CodeMirror-matchingbracket {
            text-decoration: underline;
            color: white !important;
          }
          
        • monokai.css
          /* Based on Sublime Text's Monokai theme */
          
          .cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;}
          .cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
          .cm-s-monokai.CodeMirror ::selection { background: rgba(73, 72, 62, .99); }
          .cm-s-monokai.CodeMirror ::-moz-selection { background: rgba(73, 72, 62, .99); }
          .cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;}
          .cm-s-monokai .CodeMirror-guttermarker { color: white; }
          .cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;}
          .cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
          
          .cm-s-monokai span.cm-comment {color: #75715e;}
          .cm-s-monokai span.cm-atom {color: #ae81ff;}
          .cm-s-monokai span.cm-number {color: #ae81ff;}
          
          .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
          .cm-s-monokai span.cm-keyword {color: #f92672;}
          .cm-s-monokai span.cm-string {color: #e6db74;}
          
          .cm-s-monokai span.cm-variable {color: #a6e22e;}
          .cm-s-monokai span.cm-variable-2 {color: #9effff;}
          .cm-s-monokai span.cm-def {color: #fd971f;}
          .cm-s-monokai span.cm-bracket {color: #f8f8f2;}
          .cm-s-monokai span.cm-tag {color: #f92672;}
          .cm-s-monokai span.cm-link {color: #ae81ff;}
          .cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
          
          .cm-s-monokai .CodeMirror-activeline-background {background: #373831 !important;}
          .cm-s-monokai .CodeMirror-matchingbracket {
            text-decoration: underline;
            color: white !important;
          }
          
        • neat.css
          .cm-s-neat span.cm-comment { color: #a86; }
          .cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
          .cm-s-neat span.cm-string { color: #a22; }
          .cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
          .cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
          .cm-s-neat span.cm-variable { color: black; }
          .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
          .cm-s-neat span.cm-meta {color: #555;}
          .cm-s-neat span.cm-link { color: #3a3; }
          
          .cm-s-neat .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-neat .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • neo.css
          /* neo theme for codemirror */
          
          /* Color scheme */
          
          .cm-s-neo.CodeMirror {
            background-color:#ffffff;
            color:#2e383c;
            line-height:1.4375;
          }
          .cm-s-neo .cm-comment {color:#75787b}
          .cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3}
          .cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a}
          .cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328}
          .cm-s-neo .cm-string {color:#b35e14}
          .cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65}
          
          
          /* Editor styling */
          
          .cm-s-neo pre {
            padding:0;
          }
          
          .cm-s-neo .CodeMirror-gutters {
            border:none;
            border-right:10px solid transparent;
            background-color:transparent;
          }
          
          .cm-s-neo .CodeMirror-linenumber {
            padding:0;
            color:#e0e2e5;
          }
          
          .cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; }
          .cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; }
          
          .cm-s-neo div.CodeMirror-cursor {
            width: auto;
            border: 0;
            background: rgba(155,157,162,0.37);
            z-index: 1;
          }
          
        • night.css
          /* Loosely based on the Midnight Textmate theme */
          
          .cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; }
          .cm-s-night div.CodeMirror-selected { background: #447 !important; }
          .cm-s-night.CodeMirror ::selection { background: rgba(68, 68, 119, .99); }
          .cm-s-night.CodeMirror ::-moz-selection { background: rgba(68, 68, 119, .99); }
          .cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-night .CodeMirror-guttermarker { color: white; }
          .cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; }
          .cm-s-night .CodeMirror-linenumber { color: #f8f8f8; }
          .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-night span.cm-comment { color: #6900a1; }
          .cm-s-night span.cm-atom { color: #845dc4; }
          .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
          .cm-s-night span.cm-keyword { color: #599eff; }
          .cm-s-night span.cm-string { color: #37f14a; }
          .cm-s-night span.cm-meta { color: #7678e2; }
          .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
          .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
          .cm-s-night span.cm-bracket { color: #8da6ce; }
          .cm-s-night span.cm-comment { color: #6900a1; }
          .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
          .cm-s-night span.cm-link { color: #845dc4; }
          .cm-s-night span.cm-error { color: #9d1e15; }
          
          .cm-s-night .CodeMirror-activeline-background {background: #1C005A !important;}
          .cm-s-night .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • paraiso-dark.css
          /*
          
              Name:       Paraíso (Dark)
              Author:     Jan T. Sott
          
              Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
              Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
          
          */
          
          .cm-s-paraiso-dark.CodeMirror {background: #2f1e2e; color: #b9b6b0;}
          .cm-s-paraiso-dark div.CodeMirror-selected {background: #41323f !important;}
          .cm-s-paraiso-dark.CodeMirror ::selection { background: rgba(65, 50, 63, .99); }
          .cm-s-paraiso-dark.CodeMirror ::-moz-selection { background: rgba(65, 50, 63, .99); }
          .cm-s-paraiso-dark .CodeMirror-gutters {background: #2f1e2e; border-right: 0px;}
          .cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }
          .cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }
          .cm-s-paraiso-dark .CodeMirror-linenumber {color: #776e71;}
          .cm-s-paraiso-dark .CodeMirror-cursor {border-left: 1px solid #8d8687 !important;}
          
          .cm-s-paraiso-dark span.cm-comment {color: #e96ba8;}
          .cm-s-paraiso-dark span.cm-atom {color: #815ba4;}
          .cm-s-paraiso-dark span.cm-number {color: #815ba4;}
          
          .cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute {color: #48b685;}
          .cm-s-paraiso-dark span.cm-keyword {color: #ef6155;}
          .cm-s-paraiso-dark span.cm-string {color: #fec418;}
          
          .cm-s-paraiso-dark span.cm-variable {color: #48b685;}
          .cm-s-paraiso-dark span.cm-variable-2 {color: #06b6ef;}
          .cm-s-paraiso-dark span.cm-def {color: #f99b15;}
          .cm-s-paraiso-dark span.cm-bracket {color: #b9b6b0;}
          .cm-s-paraiso-dark span.cm-tag {color: #ef6155;}
          .cm-s-paraiso-dark span.cm-link {color: #815ba4;}
          .cm-s-paraiso-dark span.cm-error {background: #ef6155; color: #8d8687;}
          
          .cm-s-paraiso-dark .CodeMirror-activeline-background {background: #4D344A !important;}
          .cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • paraiso-light.css
          /*
          
              Name:       Paraíso (Light)
              Author:     Jan T. Sott
          
              Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
              Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
          
          */
          
          .cm-s-paraiso-light.CodeMirror {background: #e7e9db; color: #41323f;}
          .cm-s-paraiso-light div.CodeMirror-selected {background: #b9b6b0 !important;}
          .cm-s-paraiso-light.CodeMirror ::selection { background: #b9b6b0; }
          .cm-s-paraiso-light.CodeMirror ::-moz-selection { background: #b9b6b0; }
          .cm-s-paraiso-light .CodeMirror-gutters {background: #e7e9db; border-right: 0px;}
          .cm-s-paraiso-light .CodeMirror-guttermarker { color: black; }
          .cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; }
          .cm-s-paraiso-light .CodeMirror-linenumber {color: #8d8687;}
          .cm-s-paraiso-light .CodeMirror-cursor {border-left: 1px solid #776e71 !important;}
          
          .cm-s-paraiso-light span.cm-comment {color: #e96ba8;}
          .cm-s-paraiso-light span.cm-atom {color: #815ba4;}
          .cm-s-paraiso-light span.cm-number {color: #815ba4;}
          
          .cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute {color: #48b685;}
          .cm-s-paraiso-light span.cm-keyword {color: #ef6155;}
          .cm-s-paraiso-light span.cm-string {color: #fec418;}
          
          .cm-s-paraiso-light span.cm-variable {color: #48b685;}
          .cm-s-paraiso-light span.cm-variable-2 {color: #06b6ef;}
          .cm-s-paraiso-light span.cm-def {color: #f99b15;}
          .cm-s-paraiso-light span.cm-bracket {color: #41323f;}
          .cm-s-paraiso-light span.cm-tag {color: #ef6155;}
          .cm-s-paraiso-light span.cm-link {color: #815ba4;}
          .cm-s-paraiso-light span.cm-error {background: #ef6155; color: #776e71;}
          
          .cm-s-paraiso-light .CodeMirror-activeline-background {background: #CFD1C4 !important;}
          .cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • pastel-on-dark.css
          /**
           * Pastel On Dark theme ported from ACE editor
           * @license MIT
           * @copyright AtomicPages LLC 2014
           * @author Dennis Thompson, AtomicPages LLC
           * @version 1.1
           * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme
           */
          
          .cm-s-pastel-on-dark.CodeMirror {
          	background: #2c2827;
          	color: #8F938F;
          	line-height: 1.5;
          	font-size: 14px;
          }
          .cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; }
          .cm-s-pastel-on-dark.CodeMirror ::selection { background: rgba(221,240,255,0.2); }
          .cm-s-pastel-on-dark.CodeMirror ::-moz-selection { background: rgba(221,240,255,0.2); }
          
          .cm-s-pastel-on-dark .CodeMirror-gutters {
          	background: #34302f;
          	border-right: 0px;
          	padding: 0 3px;
          }
          .cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; }
          .cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; }
          .cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; }
          .cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
          .cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; }
          .cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; }
          .cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; }
          .cm-s-pastel-on-dark span.cm-property { color: #8F938F; }
          .cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; }
          .cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; }
          .cm-s-pastel-on-dark span.cm-string { color: #66A968; }
          .cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; }
          .cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; }
          .cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; }
          .cm-s-pastel-on-dark span.cm-def { color: #757aD8; }
          .cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; }
          .cm-s-pastel-on-dark span.cm-tag { color: #C1C144; }
          .cm-s-pastel-on-dark span.cm-link { color: #ae81ff; }
          .cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; }
          .cm-s-pastel-on-dark span.cm-error {
          	background: #757aD8;
          	color: #f8f8f0;
          }
          .cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031) !important; }
          .cm-s-pastel-on-dark .CodeMirror-matchingbracket {
          	border: 1px solid rgba(255,255,255,0.25);
          	color: #8F938F !important;
          	margin: -1px -1px 0 -1px;
          }
          
        • rubyblue.css
          .cm-s-rubyblue.CodeMirror { background: #112435; color: white; }
          .cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }
          .cm-s-rubyblue.CodeMirror ::selection { background: rgba(56, 86, 111, 0.99); }
          .cm-s-rubyblue.CodeMirror ::-moz-selection { background: rgba(56, 86, 111, 0.99); }
          .cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; }
          .cm-s-rubyblue .CodeMirror-guttermarker { color: white; }
          .cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; }
          .cm-s-rubyblue .CodeMirror-linenumber { color: white; }
          .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
          .cm-s-rubyblue span.cm-atom { color: #F4C20B; }
          .cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
          .cm-s-rubyblue span.cm-keyword { color: #F0F; }
          .cm-s-rubyblue span.cm-string { color: #F08047; }
          .cm-s-rubyblue span.cm-meta { color: #F0F; }
          .cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
          .cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
          .cm-s-rubyblue span.cm-bracket { color: #F0F; }
          .cm-s-rubyblue span.cm-link { color: #F4C20B; }
          .cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
          .cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }
          .cm-s-rubyblue span.cm-error { color: #AF2018; }
          
          .cm-s-rubyblue .CodeMirror-activeline-background {background: #173047 !important;}
          
        • solarized.css
          /*
          Solarized theme for code-mirror
          http://ethanschoonover.com/solarized
          */
          
          /*
          Solarized color pallet
          http://ethanschoonover.com/solarized/img/solarized-palette.png
          */
          
          .solarized.base03 { color: #002b36; }
          .solarized.base02 { color: #073642; }
          .solarized.base01 { color: #586e75; }
          .solarized.base00 { color: #657b83; }
          .solarized.base0 { color: #839496; }
          .solarized.base1 { color: #93a1a1; }
          .solarized.base2 { color: #eee8d5; }
          .solarized.base3  { color: #fdf6e3; }
          .solarized.solar-yellow  { color: #b58900; }
          .solarized.solar-orange  { color: #cb4b16; }
          .solarized.solar-red { color: #dc322f; }
          .solarized.solar-magenta { color: #d33682; }
          .solarized.solar-violet  { color: #6c71c4; }
          .solarized.solar-blue { color: #268bd2; }
          .solarized.solar-cyan { color: #2aa198; }
          .solarized.solar-green { color: #859900; }
          
          /* Color scheme for code-mirror */
          
          .cm-s-solarized {
            line-height: 1.45em;
            color-profile: sRGB;
            rendering-intent: auto;
          }
          .cm-s-solarized.cm-s-dark {
            color: #839496;
            background-color:  #002b36;
            text-shadow: #002b36 0 1px;
          }
          .cm-s-solarized.cm-s-light {
            background-color: #fdf6e3;
            color: #657b83;
            text-shadow: #eee8d5 0 1px;
          }
          
          .cm-s-solarized .CodeMirror-widget {
            text-shadow: none;
          }
          
          
          .cm-s-solarized .cm-keyword { color: #cb4b16 }
          .cm-s-solarized .cm-atom { color: #d33682; }
          .cm-s-solarized .cm-number { color: #d33682; }
          .cm-s-solarized .cm-def { color: #2aa198; }
          
          .cm-s-solarized .cm-variable { color: #268bd2; }
          .cm-s-solarized .cm-variable-2 { color: #b58900; }
          .cm-s-solarized .cm-variable-3 { color: #6c71c4; }
          
          .cm-s-solarized .cm-property { color: #2aa198; }
          .cm-s-solarized .cm-operator {color: #6c71c4;}
          
          .cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }
          
          .cm-s-solarized .cm-string { color: #859900; }
          .cm-s-solarized .cm-string-2 { color: #b58900; }
          
          .cm-s-solarized .cm-meta { color: #859900; }
          .cm-s-solarized .cm-qualifier { color: #b58900; }
          .cm-s-solarized .cm-builtin { color: #d33682; }
          .cm-s-solarized .cm-bracket { color: #cb4b16; }
          .cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }
          .cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }
          .cm-s-solarized .cm-tag { color: #93a1a1 }
          .cm-s-solarized .cm-attribute {  color: #2aa198; }
          .cm-s-solarized .cm-header { color: #586e75; }
          .cm-s-solarized .cm-quote { color: #93a1a1; }
          .cm-s-solarized .cm-hr {
            color: transparent;
            border-top: 1px solid #586e75;
            display: block;
          }
          .cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }
          .cm-s-solarized .cm-special { color: #6c71c4; }
          .cm-s-solarized .cm-em {
            color: #999;
            text-decoration: underline;
            text-decoration-style: dotted;
          }
          .cm-s-solarized .cm-strong { color: #eee; }
          .cm-s-solarized .cm-error,
          .cm-s-solarized .cm-invalidchar {
            color: #586e75;
            border-bottom: 1px dotted #dc322f;
          }
          
          .cm-s-solarized.cm-s-dark .CodeMirror-selected { background: #073642; }
          .cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); }
          .cm-s-solarized.cm-s-dark.CodeMirror ::-moz-selection { background: rgba(7, 54, 66, 0.99); }
          
          .cm-s-solarized.cm-s-light .CodeMirror-selected { background: #eee8d5; }
          .cm-s-solarized.cm-s-light.CodeMirror ::selection { background: #eee8d5; }
          .cm-s-solarized.cm-s-lightCodeMirror ::-moz-selection { background: #eee8d5; }
          
          /* Editor styling */
          
          
          
          /* Little shadow on the view-port of the buffer view */
          .cm-s-solarized.CodeMirror {
            -moz-box-shadow: inset 7px 0 12px -6px #000;
            -webkit-box-shadow: inset 7px 0 12px -6px #000;
            box-shadow: inset 7px 0 12px -6px #000;
          }
          
          /* Gutter border and some shadow from it  */
          .cm-s-solarized .CodeMirror-gutters {
            border-right: 1px solid;
          }
          
          /* Gutter colors and line number styling based of color scheme (dark / light) */
          
          /* Dark */
          .cm-s-solarized.cm-s-dark .CodeMirror-gutters {
            background-color:  #002b36;
            border-color: #00232c;
          }
          
          .cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
            text-shadow: #021014 0 -1px;
          }
          
          /* Light */
          .cm-s-solarized.cm-s-light .CodeMirror-gutters {
            background-color: #fdf6e3;
            border-color: #eee8d5;
          }
          
          /* Common */
          .cm-s-solarized .CodeMirror-linenumber {
            color: #586e75;
            padding: 0 5px;
          }
          .cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
          .cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }
          .cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }
          
          .cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {
            color: #586e75;
          }
          
          .cm-s-solarized .CodeMirror-lines .CodeMirror-cursor {
            border-left: 1px solid #819090;
          }
          
          /*
          Active line. Negative margin compensates left padding of the text in the
          view-port
          */
          .cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
            background: rgba(255, 255, 255, 0.10);
          }
          .cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
            background: rgba(0, 0, 0, 0.10);
          }
          
        • the-matrix.css
          .cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; }
          .cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D !important; }
          .cm-s-the-matrix.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-the-matrix.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; }
          .cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; }
          .cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; }
          .cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; }
          .cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00 !important; }
          
          .cm-s-the-matrix span.cm-keyword {color: #008803; font-weight: bold;}
          .cm-s-the-matrix span.cm-atom {color: #3FF;}
          .cm-s-the-matrix span.cm-number {color: #FFB94F;}
          .cm-s-the-matrix span.cm-def {color: #99C;}
          .cm-s-the-matrix span.cm-variable {color: #F6C;}
          .cm-s-the-matrix span.cm-variable-2 {color: #C6F;}
          .cm-s-the-matrix span.cm-variable-3 {color: #96F;}
          .cm-s-the-matrix span.cm-property {color: #62FFA0;}
          .cm-s-the-matrix span.cm-operator {color: #999}
          .cm-s-the-matrix span.cm-comment {color: #CCCCCC;}
          .cm-s-the-matrix span.cm-string {color: #39C;}
          .cm-s-the-matrix span.cm-meta {color: #C9F;}
          .cm-s-the-matrix span.cm-qualifier {color: #FFF700;}
          .cm-s-the-matrix span.cm-builtin {color: #30a;}
          .cm-s-the-matrix span.cm-bracket {color: #cc7;}
          .cm-s-the-matrix span.cm-tag {color: #FFBD40;}
          .cm-s-the-matrix span.cm-attribute {color: #FFF700;}
          .cm-s-the-matrix span.cm-error {color: #FF0000;}
          
          .cm-s-the-matrix .CodeMirror-activeline-background {background: #040;}
          
        • tomorrow-night-bright.css
          /*
          
              Name:       Tomorrow Night - Bright
              Author:     Chris Kempson
          
              Port done by Gerard Braad <me@gbraad.nl>
          
          */
          
          .cm-s-tomorrow-night-bright.CodeMirror {background: #000000; color: #eaeaea;}
          .cm-s-tomorrow-night-bright div.CodeMirror-selected {background: #424242 !important;}
          .cm-s-tomorrow-night-bright .CodeMirror-gutters {background: #000000; border-right: 0px;}
          .cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }
          .cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-tomorrow-night-bright .CodeMirror-linenumber {color: #424242;}
          .cm-s-tomorrow-night-bright .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}
          
          .cm-s-tomorrow-night-bright span.cm-comment {color: #d27b53;}
          .cm-s-tomorrow-night-bright span.cm-atom {color: #a16a94;}
          .cm-s-tomorrow-night-bright span.cm-number {color: #a16a94;}
          
          .cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute {color: #99cc99;}
          .cm-s-tomorrow-night-bright span.cm-keyword {color: #d54e53;}
          .cm-s-tomorrow-night-bright span.cm-string {color: #e7c547;}
          
          .cm-s-tomorrow-night-bright span.cm-variable {color: #b9ca4a;}
          .cm-s-tomorrow-night-bright span.cm-variable-2 {color: #7aa6da;}
          .cm-s-tomorrow-night-bright span.cm-def {color: #e78c45;}
          .cm-s-tomorrow-night-bright span.cm-bracket {color: #eaeaea;}
          .cm-s-tomorrow-night-bright span.cm-tag {color: #d54e53;}
          .cm-s-tomorrow-night-bright span.cm-link {color: #a16a94;}
          .cm-s-tomorrow-night-bright span.cm-error {background: #d54e53; color: #6A6A6A;}
          
          .cm-s-tomorrow-night-bright .CodeMirror-activeline-background {background: #2a2a2a !important;}
          .cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • tomorrow-night-eighties.css
          /*
          
              Name:       Tomorrow Night - Eighties
              Author:     Chris Kempson
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;}
          .cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;}
          .cm-s-tomorrow-night-eighties.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-tomorrow-night-eighties.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;}
          .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }
          .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;}
          .cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}
          
          .cm-s-tomorrow-night-eighties span.cm-comment {color: #d27b53;}
          .cm-s-tomorrow-night-eighties span.cm-atom {color: #a16a94;}
          .cm-s-tomorrow-night-eighties span.cm-number {color: #a16a94;}
          
          .cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute {color: #99cc99;}
          .cm-s-tomorrow-night-eighties span.cm-keyword {color: #f2777a;}
          .cm-s-tomorrow-night-eighties span.cm-string {color: #ffcc66;}
          
          .cm-s-tomorrow-night-eighties span.cm-variable {color: #99cc99;}
          .cm-s-tomorrow-night-eighties span.cm-variable-2 {color: #6699cc;}
          .cm-s-tomorrow-night-eighties span.cm-def {color: #f99157;}
          .cm-s-tomorrow-night-eighties span.cm-bracket {color: #CCCCCC;}
          .cm-s-tomorrow-night-eighties span.cm-tag {color: #f2777a;}
          .cm-s-tomorrow-night-eighties span.cm-link {color: #a16a94;}
          .cm-s-tomorrow-night-eighties span.cm-error {background: #f2777a; color: #6A6A6A;}
          
          .cm-s-tomorrow-night-eighties .CodeMirror-activeline-background {background: #343600 !important;}
          .cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • twilight.css
          .cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/
          .cm-s-twilight .CodeMirror-selected { background: #323232 !important; } /**/
          .cm-s-twilight.CodeMirror ::selection { background: rgba(50, 50, 50, 0.99); }
          .cm-s-twilight.CodeMirror ::-moz-selection { background: rgba(50, 50, 50, 0.99); }
          
          .cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }
          .cm-s-twilight .CodeMirror-guttermarker { color: white; }
          .cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }
          .cm-s-twilight .CodeMirror-linenumber { color: #aaa; }
          .cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-twilight .cm-keyword {  color: #f9ee98; } /**/
          .cm-s-twilight .cm-atom { color: #FC0; }
          .cm-s-twilight .cm-number { color:  #ca7841; } /**/
          .cm-s-twilight .cm-def { color: #8DA6CE; }
          .cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/
          .cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/
          .cm-s-twilight .cm-operator { color: #cda869; } /**/
          .cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/
          .cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/
          .cm-s-twilight .cm-string-2 { color:#bd6b18 } /*?*/
          .cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/
          .cm-s-twilight .cm-builtin { color: #cda869; } /*?*/
          .cm-s-twilight .cm-tag { color: #997643; } /**/
          .cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/
          .cm-s-twilight .cm-header { color: #FF6400; }
          .cm-s-twilight .cm-hr { color: #AEAEAE; }
          .cm-s-twilight .cm-link {   color:#ad9361; font-style:italic; text-decoration:none; } /**/
          .cm-s-twilight .cm-error { border-bottom: 1px solid red; }
          
          .cm-s-twilight .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-twilight .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • vibrant-ink.css
          /* Taken from the popular Visual Studio Vibrant Ink Schema */
          
          .cm-s-vibrant-ink.CodeMirror { background: black; color: white; }
          .cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; }
          .cm-s-vibrant-ink.CodeMirror ::selection { background: rgba(53, 73, 60, 0.99); }
          .cm-s-vibrant-ink.CodeMirror ::-moz-selection { background: rgba(53, 73, 60, 0.99); }
          
          .cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; }
          .cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-vibrant-ink .cm-keyword {  color: #CC7832; }
          .cm-s-vibrant-ink .cm-atom { color: #FC0; }
          .cm-s-vibrant-ink .cm-number { color:  #FFEE98; }
          .cm-s-vibrant-ink .cm-def { color: #8DA6CE; }
          .cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D }
          .cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D }
          .cm-s-vibrant-ink .cm-operator { color: #888; }
          .cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; }
          .cm-s-vibrant-ink .cm-string { color:  #A5C25C }
          .cm-s-vibrant-ink .cm-string-2 { color: red }
          .cm-s-vibrant-ink .cm-meta { color: #D8FA3C; }
          .cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-tag { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-header { color: #FF6400; }
          .cm-s-vibrant-ink .cm-hr { color: #AEAEAE; }
          .cm-s-vibrant-ink .cm-link { color: blue; }
          .cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; }
          
          .cm-s-vibrant-ink .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-vibrant-ink .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • xq-dark.css
          /*
          Copyright (C) 2011 by MarkLogic Corporation
          Author: Mike Brevoort <mike@brevoort.com>
          
          Permission is hereby granted, free of charge, to any person obtaining a copy
          of this software and associated documentation files (the "Software"), to deal
          in the Software without restriction, including without limitation the rights
          to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
          copies of the Software, and to permit persons to whom the Software is
          furnished to do so, subject to the following conditions:
          
          The above copyright notice and this permission notice shall be included in
          all copies or substantial portions of the Software.
          
          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
          AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
          THE SOFTWARE.
          */
          .cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-selected { background: #27007A !important; }
          .cm-s-xq-dark.CodeMirror ::selection { background: rgba(39, 0, 122, 0.99); }
          .cm-s-xq-dark.CodeMirror ::-moz-selection { background: rgba(39, 0, 122, 0.99); }
          .cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; }
          .cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
          .cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
          .cm-s-xq-dark span.cm-number {color: #164;}
          .cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
          .cm-s-xq-dark span.cm-variable {color: #FFF;}
          .cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
          .cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
          .cm-s-xq-dark span.cm-property {}
          .cm-s-xq-dark span.cm-operator {}
          .cm-s-xq-dark span.cm-comment {color: gray;}
          .cm-s-xq-dark span.cm-string {color: #9FEE00;}
          .cm-s-xq-dark span.cm-meta {color: yellow;}
          .cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
          .cm-s-xq-dark span.cm-builtin {color: #30a;}
          .cm-s-xq-dark span.cm-bracket {color: #cc7;}
          .cm-s-xq-dark span.cm-tag {color: #FFBD40;}
          .cm-s-xq-dark span.cm-attribute {color: #FFF700;}
          .cm-s-xq-dark span.cm-error {color: #f00;}
          
          .cm-s-xq-dark .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-xq-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
        • xq-light.css
          /*
          Copyright (C) 2011 by MarkLogic Corporation
          Author: Mike Brevoort <mike@brevoort.com>
          
          Permission is hereby granted, free of charge, to any person obtaining a copy
          of this software and associated documentation files (the "Software"), to deal
          in the Software without restriction, including without limitation the rights
          to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
          copies of the Software, and to permit persons to whom the Software is
          furnished to do so, subject to the following conditions:
          
          The above copyright notice and this permission notice shall be included in
          all copies or substantial portions of the Software.
          
          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
          AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
          THE SOFTWARE.
          */
          .cm-s-xq-light span.cm-keyword {line-height: 1em; font-weight: bold; color: #5A5CAD; }
          .cm-s-xq-light span.cm-atom {color: #6C8CD5;}
          .cm-s-xq-light span.cm-number {color: #164;}
          .cm-s-xq-light span.cm-def {text-decoration:underline;}
          .cm-s-xq-light span.cm-variable {color: black; }
          .cm-s-xq-light span.cm-variable-2 {color:black;}
          .cm-s-xq-light span.cm-variable-3 {color: black; }
          .cm-s-xq-light span.cm-property {}
          .cm-s-xq-light span.cm-operator {}
          .cm-s-xq-light span.cm-comment {color: #0080FF; font-style: italic;}
          .cm-s-xq-light span.cm-string {color: red;}
          .cm-s-xq-light span.cm-meta {color: yellow;}
          .cm-s-xq-light span.cm-qualifier {color: grey}
          .cm-s-xq-light span.cm-builtin {color: #7EA656;}
          .cm-s-xq-light span.cm-bracket {color: #cc7;}
          .cm-s-xq-light span.cm-tag {color: #3F7F7F;}
          .cm-s-xq-light span.cm-attribute {color: #7F007F;}
          .cm-s-xq-light span.cm-error {color: #f00;}
          
          .cm-s-xq-light .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-xq-light .CodeMirror-matchingbracket {outline:1px solid grey;color:black !important;background:yellow;}
        • zenburn.css
          /**
           * "
           *  Using Zenburn color palette from the Emacs Zenburn Theme
           *  https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el
           *
           *  Also using parts of https://github.com/xavi/coderay-lighttable-theme
           * "
           * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css
           */
          
          .cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; }
          .cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; }
          .cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white !important; }
          .cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; }
          .cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; }
          .cm-s-zenburn span.cm-comment { color: #7f9f7f; }
          .cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; }
          .cm-s-zenburn span.cm-atom { color: #bfebbf; }
          .cm-s-zenburn span.cm-def { color: #dcdccc; }
          .cm-s-zenburn span.cm-variable { color: #dfaf8f; }
          .cm-s-zenburn span.cm-variable-2 { color: #dcdccc; }
          .cm-s-zenburn span.cm-string { color: #cc9393; }
          .cm-s-zenburn span.cm-string-2 { color: #cc9393; }
          .cm-s-zenburn span.cm-number { color: #dcdccc; }
          .cm-s-zenburn span.cm-tag { color: #93e0e3; }
          .cm-s-zenburn span.cm-property { color: #dfaf8f; }
          .cm-s-zenburn span.cm-attribute { color: #dfaf8f; }
          .cm-s-zenburn span.cm-qualifier { color: #7cb8bb; }
          .cm-s-zenburn span.cm-meta { color: #f0dfaf; }
          .cm-s-zenburn span.cm-header { color: #f0efd0; }
          .cm-s-zenburn span.cm-operator { color: #f0efd0; }
          .cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; }
          .cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; }
          .cm-s-zenburn .CodeMirror-activeline { background: #000000; }
          .cm-s-zenburn .CodeMirror-activeline-background { background: #000000; }
          .cm-s-zenburn .CodeMirror-selected { background: #545454; }
          .cm-s-zenburn .CodeMirror-focused .CodeMirror-selected { background: #4f4f4f; }
          
      • AUTHORS
        List of CodeMirror contributors. Updated before every release.
        
        4r2r
        Aaron Brooks
        Abdelouahab
        Abe Fettig
        Adam Ahmed
        Adam King
        adanlobato
        Adán Lobato
        Adrian Aichner
        aeroson
        Ahmad Amireh
        Ahmad M. Zawawi
        ahoward
        Akeksandr Motsjonov
        Alberto González Palomo
        Alberto Pose
        Albert Xing
        Alexander Pavlov
        Alexander Schepanovski
        Alexander Shvets
        Alexander Solovyov
        Alexandre Bique
        alexey-k
        Alex Piggott
        Aliaksei Chapyzhenka
        Amsul
        amuntean
        Amy
        Ananya Sen
        anaran
        AndersMad
        Anders Nawroth
        Anderson Mesquita
        Andrea G
        Andreas Reischuck
        Andre von Houck
        Andrey Fedorov
        Andrey Klyuchnikov
        Andrey Lushnikov
        Andy Joslin
        Andy Kimball
        Andy Li
        angelozerr
        angelo.zerr@gmail.com
        Ankit
        Ankit Ahuja
        Ansel Santosa
        Anthony Grimes
        Anton Kovalyov
        areos
        as3boyan
        AtomicPages LLC
        Atul Bhouraskar
        Aurelian Oancea
        Bastian Müller
        Bem Jones-Bey
        benbro
        Beni Cherniavsky-Paskin
        Benjamin DeCoste
        Ben Keen
        Bernhard Sirlinger
        Bert Chang
        Billy Moon
        binny
        B Krishna Chaitanya
        Blaine G
        blukat29
        boomyjee
        borawjm
        Brandon Frohs
        Brandon Wamboldt
        Brett Zamir
        Brian Grinstead
        Brian Sletten
        Bruce Mitchener
        Chandra Sekhar Pydi
        Charles Skelton
        Cheah Chu Yeow
        Chris Coyier
        Chris Granger
        Chris Houseknecht
        Chris Morgan
        Christian Oyarzun
        Christian Petrov
        Christopher Brown
        ciaranj
        CodeAnimal
        ComFreek
        Curtis Gagliardi
        dagsta
        daines
        Dale Jung
        Dan Bentley
        Dan Heberden
        Daniel, Dao Quang Minh
        Daniele Di Sarli
        Daniel Faust
        Daniel Huigens
        Daniel KJ
        Daniel Neel
        Daniel Parnell
        Danny Yoo
        darealshinji
        Darius Roberts
        Dave Myers
        David Mignot
        David Pathakjee
        David Vázquez
        deebugger
        Deep Thought
        Devon Carew
        dignifiedquire
        Dimage Sapelkin
        Dmitry Kiselyov
        domagoj412
        Dominator008
        Domizio Demichelis
        Doug Wikle
        Drew Bratcher
        Drew Hintz
        Drew Khoury
        Dror BG
        duralog
        eborden
        edsharp
        ekhaled
        Enam Mijbah Noor
        Eric Allam
        eustas
        Fabien O'Carroll
        Fabio Zendhi Nagao
        Faiza Alsaied
        Fauntleroy
        fbuchinger
        feizhang365
        Felipe Lalanne
        Felix Raab
        Filip Noetzel
        flack
        ForbesLindesay
        Forbes Lindesay
        Ford_Lawnmower
        Forrest Oliphant
        Frank Wiegand
        Gabriel Gheorghian
        Gabriel Horner
        Gabriel Nahmias
        galambalazs
        Gautam Mehta
        gekkoe
        Gerard Braad
        Gergely Hegykozi
        Giovanni Calò
        Glenn Jorde
        Glenn Ruehle
        Golevka
        Gordon Smith
        Grant Skinner
        greengiant
        Gregory Koberger
        Guillaume Massé
        Guillaume Massé
        Gustavo Rodrigues
        Hakan Tunc
        Hans Engel
        Hardest
        Hasan Karahan
        Herculano Campos
        Hiroyuki Makino
        hitsthings
        Hocdoc
        Ian Beck
        Ian Dickinson
        Ian Wehrman
        Ian Wetherbee
        Ice White
        ICHIKAWA, Yuji
        ilvalle
        Ingo Richter
        Irakli Gozalishvili
        Ivan Kurnosov
        Jacob Lee
        Jakob Miland
        Jakub Vrana
        Jakub Vrána
        James Campos
        James Thorne
        Jamie Hill
        Jan Jongboom
        jankeromnes
        Jan Keromnes
        Jan Odvarko
        Jan T. Sott
        Jared Forsyth
        Jason
        Jason Barnabe
        Jason Grout
        Jason Johnston
        Jason San Jose
        Jason Siefken
        Jaydeep Solanki
        Jean Boussier
        jeffkenton
        Jeff Pickhardt
        jem (graphite)
        Jeremy Parmenter
        Jochen Berger
        Johan Ask
        John Connor
        John Lees-Miller
        John Snelson
        John Van Der Loo
        Jonathan Malmaud
        jongalloway
        Jon Malmaud
        Jon Sangster
        Joost-Wim Boekesteijn
        Joseph Pecoraro
        Joshua Newman
        Josh Watzman
        jots
        jsoojeon
        Juan Benavides Romero
        Jucovschi Constantin
        Juho Vuori
        Justin Hileman
        jwallers@gmail.com
        kaniga
        Ken Newman
        Ken Rockot
        Kevin Sawicki
        Kevin Ushey
        Klaus Silveira
        Koh Zi Han, Cliff
        komakino
        Konstantin Lopuhin
        koops
        ks-ifware
        kubelsmieci
        KwanEsq
        Lanfei
        Lanny
        Laszlo Vidacs
        leaf corcoran
        Leonid Khachaturov
        Leon Sorokin
        Leonya Khachaturov
        Liam Newman
        LM
        lochel
        Lorenzo Stoakes
        Luciano Longo
        Luke Stagner
        lynschinzer
        Maksim Lin
        Maksym Taran
        Malay Majithia
        Manuel Rego Casasnovas
        Marat Dreizin
        Marcel Gerber
        Marco Aurélio
        Marco Munizaga
        Marcus Bointon
        Marek Rudnicki
        Marijn Haverbeke
        Mário Gonçalves
        Mario Pietsch
        Mark Lentczner
        Marko Bonaci
        Martin Balek
        Martín Gaitán
        Martin Hasoň
        Mason Malone
        Mateusz Paprocki
        Mathias Bynens
        mats cronqvist
        Matthew Beale
        Matthias Bussonnier
        Matthias BUSSONNIER
        Matt McDonald
        Matt Pass
        Matt Sacks
        mauricio
        Maximilian Hils
        Maxim Kraev
        Max Kirsch
        Max Xiantu
        mbarkhau
        Metatheos
        Micah Dubinko
        Michael Lehenbauer
        Michael Zhou
        Mighty Guava
        Miguel Castillo
        mihailik
        Mike
        Mike Brevoort
        Mike Diaz
        Mike Ivanov
        Mike Kadin
        MinRK
        Miraculix87
        misfo
        mloginov
        Moritz Schwörer
        mps
        mtaran-google
        Narciso Jaramillo
        Nathan Williams
        ndr
        nerbert
        nextrevision
        ngn
        nguillaumin
        Ng Zhi An
        Nicholas Bollweg
        Nicholas Bollweg (Nick)
        Nick Small
        Niels van Groningen
        nightwing
        Nikita Beloglazov
        Nikita Vasilyev
        Nikolay Kostov
        nilp0inter
        Nisarg Jhaveri
        nlwillia
        Norman Rzepka
        pablo
        Page
        Panupong Pasupat
        paris
        Patil Arpith
        Patrick Stoica
        Patrick Strawderman
        Paul Garvin
        Paul Ivanov
        Pavel Feldman
        Pavel Strashkin
        Paweł Bartkiewicz
        peteguhl
        Peter Flynn
        peterkroon
        Peter Kroon
        prasanthj
        Prasanth J
        Radek Piórkowski
        Rahul
        Randall Mason
        Randy Burden
        Randy Edmunds
        Rasmus Erik Voel Jensen
        Ray Ratchup
        Richard van der Meer
        Richard Z.H. Wang
        Robert Crossfield
        Roberto Abdelkader Martínez Pérez
        robertop23
        Robert Plummer
        Ruslan Osmanov
        Ryan Prior
        sabaca
        Samuel Ainsworth
        sandeepshetty
        Sander AKA Redsandro
        santec
        Sascha Peilicke
        satchmorun
        sathyamoorthi
        SCLINIC\jdecker
        Scott Aikin
        Scott Goodhew
        Sebastian Zaha
        shaund
        shaun gilchrist
        Shawn A
        sheopory
        Shiv Deepak
        Shmuel Englard
        Shubham Jain
        silverwind
        snasa
        soliton4
        sonson
        spastorelli
        srajanpaliwal
        Stanislav Oaserele
        Stas Kobzar
        Stefan Borsje
        Steffen Beyer
        Steve O'Hara
        stoskov
        Taha Jahangir
        Takuji Shimokawa
        Tarmil
        tel
        tfjgeorge
        Thaddee Tyl
        TheHowl
        think
        Thomas Dvornik
        Thomas Schmid
        Tim Alby
        Tim Baumann
        Timothy Farrell
        Timothy Hatcher
        TobiasBg
        Tomas-A
        Tomas Varaneckas
        Tom Erik Støwer
        Tom MacWright
        Tony Jian
        Travis Heppe
        Triangle717
        twifkak
        Vestimir Markov
        vf
        Vincent Woo
        Volker Mische
        wenli
        Wesley Wiser
        Will Binns-Smith
        William Jamieson
        William Stein
        Willy
        Wojtek Ptak
        Xavier Mendez
        Yassin N. Hassan
        YNH Webdev
        Yunchi Luo
        Yuvi Panda
        Zachary Dremann
        Zhang Hao
        zziuni
        魏鹏刚
        
      • CONTRIBUTING.md
        # How to contribute
        
        - [Getting help](#getting-help-)
        - [Submitting bug reports](#submitting-bug-reports-)
        - [Contributing code](#contributing-code-)
        
        ## Getting help
        
        Community discussion, questions, and informal bug reporting is done on the
        [discuss.CodeMirror forum](http://discuss.codemirror.net).
        
        ## Submitting bug reports
        
        The preferred way to report bugs is to use the
        [GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before
        reporting a bug, read these pointers.
        
        **Note:** The issue tracker is for *bugs*, not requests for help. Questions
        should be asked on the
        [discuss.CodeMirror forum](http://discuss.codemirror.net) instead.
        
        ### Reporting bugs effectively
        
        - CodeMirror is maintained by volunteers. They don't owe you anything, so be
          polite. Reports with an indignant or belligerent tone tend to be moved to the
          bottom of the pile.
        
        - Include information about **the browser in which the problem occurred**. Even
          if you tested several browsers, and the problem occurred in all of them,
          mention this fact in the bug report. Also include browser version numbers and
          the operating system that you're on.
        
        - Mention which release of CodeMirror you're using. Preferably, try also with
          the current development snapshot, to ensure the problem has not already been
          fixed.
        
        - Mention very precisely what went wrong. "X is broken" is not a good bug
          report. What did you expect to happen? What happened instead? Describe the
          exact steps a maintainer has to take to make the problem occur. We can not
          fix something that we can not observe.
        
        - If the problem can not be reproduced in any of the demos included in the
          CodeMirror distribution, please provide an HTML document that demonstrates
          the problem. The best way to do this is to go to
          [jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and
          include the resulting link in your bug report.
        
        ## Contributing code
        
        - Make sure you have a [GitHub Account](https://github.com/signup/free)
        - Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
          ([how to fork a repo](https://help.github.com/articles/fork-a-repo))
        - Make your changes
        - If your changes are easy to test or likely to regress, add tests.
          Tests for the core go into `test/test.js`, some modes have their own
          test suite under `mode/XXX/test.js`. Feel free to add new test
          suites to modes that don't have one yet (be sure to link the new
          tests into `test/index.html`).
        - Follow the general code style of the rest of the project (see
          below). Run `bin/lint` to verify that the linter is happy.
        - Make sure all tests pass. Visit `test/index.html` in your browser to
          run them.
        - Submit a pull request
        ([how to create a pull request](https://help.github.com/articles/fork-a-repo))
        
        ### Coding standards
        
        - 2 spaces per indentation level, no tabs.
        - Include semicolons after statements.
        - Note that the linter (`bin/lint`) which is run after each commit
          complains about unused variables and functions. Prefix their names
          with an underscore to muffle it.
        
        - CodeMirror does *not* follow JSHint or JSLint prescribed style.
          Patches that try to 'fix' code to pass one of these linters will be
          unceremoniously discarded.
        
      • LICENSE
        Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        THE SOFTWARE.
        
      • README.md
        # CodeMirror
        [![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
        [![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)  
        [Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png)](https://marijnhaverbeke.nl/fund/)
        
        CodeMirror is a JavaScript component that provides a code editor in
        the browser. When a mode is available for the language you are coding
        in, it will color your code, and optionally help with indentation.
        
        The project page is http://codemirror.net  
        The manual is at http://codemirror.net/doc/manual.html  
        The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
        
      • bower.json
        {
          "name": "codemirror",
          "version":"5.0.1",
          "main": ["lib/codemirror.js", "lib/codemirror.css"],
          "ignore": [
            "**/.*",
            "node_modules",
            "components",
            "bin",
            "demo",
            "doc",
            "test",
            "index.html",
            "package.json"
          ]
        }
        
      • index.html
        <!doctype html>
        
        <title>CodeMirror</title>
        <meta charset="utf-8"/>
        
        <link rel=stylesheet href="lib/codemirror.css">
        <link rel=stylesheet href="doc/docs.css">
        <script src="lib/codemirror.js"></script>
        <script src="mode/xml/xml.js"></script>
        <script src="mode/javascript/javascript.js"></script>
        <script src="mode/css/css.js"></script>
        <script src="mode/htmlmixed/htmlmixed.js"></script>
        <script src="addon/edit/matchbrackets.js"></script>
        
        <script src="doc/activebookmark.js"></script>
        
        <style>
          .CodeMirror { height: auto; border: 1px solid #ddd; }
          .CodeMirror-scroll { max-height: 200px; }
          .CodeMirror pre { padding-left: 7px; line-height: 1.25; }
        </style>
        
        <div id=nav>
          <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="doc/logo.png"></a>
        
          <ul>
            <li><a class=active data-default="true" href="#description">Home</a>
            <li><a href="doc/manual.html">Manual</a>
            <li><a href="https://github.com/codemirror/codemirror">Code</a>
          </ul>
          <ul>
            <li><a href="#features">Features</a>
            <li><a href="#community">Community</a>
            <li><a href="#browsersupport">Browser support</a>
          </ul>
        </div>
        
        <article>
        
        <section id=description class=first>
          <p><strong>CodeMirror</strong> is a versatile text editor
          implemented in JavaScript for the browser. It is specialized for
          editing code, and comes with a number of <a href="mode/index.html">language modes</a> and <a href="doc/manual.html#addons">addons</a>
          that implement more advanced editing functionality.</p>
        
          <p>A rich <a href="doc/manual.html#api">programming API</a> and a
          CSS <a href="doc/manual.html#styling">theming</a> system are
          available for customizing CodeMirror to fit your application, and
          extending it with new functionality.</p>
        </section>
        
        <section id=demo>
          <h2>This is CodeMirror</h2>
          <form style="position: relative; margin-top: .5em;"><textarea id=demotext>
        <!-- Create a simple CodeMirror instance -->
        <link rel="stylesheet" href="lib/codemirror.css">
        <script src="lib/codemirror.js"></script>
        <script>
          var editor = CodeMirror.fromTextArea(myTextarea, {
            lineNumbers: true
          });
        </script></textarea>
          <select id="demolist" onchange="document.location = this.options[this.selectedIndex].value;">
            <option value="#">Other demos...</option>
            <option value="demo/complete.html">Autocompletion</option>
            <option value="demo/folding.html">Code folding</option>
            <option value="demo/theme.html">Themes</option>
            <option value="mode/htmlmixed/index.html">Mixed language modes</option>
            <option value="demo/bidi.html">Bi-directional text</option>
            <option value="demo/variableheight.html">Variable font sizes</option>
            <option value="demo/search.html">Search interface</option>
            <option value="demo/vim.html">Vim bindings</option>
            <option value="demo/emacs.html">Emacs bindings</option>
            <option value="demo/sublime.html">Sublime Text bindings</option>
            <option value="demo/tern.html">Tern integration</option>
            <option value="demo/merge.html">Merge/diff interface</option>
            <option value="demo/fullscreen.html">Full-screen editor</option>
            <option value="demo/simplescrollbars.html">Custom scrollbars</option>
          </select></form>
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("demotext"), {
              lineNumbers: true,
              mode: "text/html",
              matchBrackets: true
            });
          </script>
        
          <div class=actions>
            <div class=actionspicture>
              <img src="doc/yinyang.png" class=yinyang>
              <div class="actionlink download">
                <a href="http://codemirror.net/codemirror.zip">DOWNLOAD</a>
              </div>
              <div class="actionlink fund">
                <a href="https://marijnhaverbeke.nl/fund/">FUND</a>
              </div>
            </div>
            <div class=actionsleft>
              Get the current version: <a href="http://codemirror.net/codemirror.zip">5.0</a>.<br>
              You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a> or<br>
              read the <a href="doc/releases.html">release notes</a>.<br>
              There is a <a href="doc/compress.html">minification helper</a>.
            </div>
            <div class=actionsright>
              Software needs maintenance,<br>
              maintainers need to subsist.<br>
              Current funding status = <img src="https://marijnhaverbeke.nl/fund/status_s.png" title="Current maintainer happiness" style="vertical-align: middle; height: 16px; width: 16px"><br>
              You can help <a href="https://marijnhaverbeke.nl/fund/" title="Set up a monthly contribution">per month</a> or
              <a title="Donate with Paypal" href="javascript:document.getElementById('paypal').submit();">once</a>.
              <form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
                <input type="hidden" name="cmd" value="_s-xclick"/>
                <input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>
              </form>
            </div>
          </div>
          
        </section>
        
        <section id=features>
          <h2>Features</h2>
          <ul>
            <li>Support for <a href="mode/index.html">over 90 languages</a> out of the box
            <li>A powerful, <a href="mode/htmlmixed/index.html">composable</a> language mode <a href="doc/manual.html#modeapi">system</a>
            <li><a href="doc/manual.html#addon_show-hint">Autocompletion</a> (<a href="demo/xmlcomplete.html">XML</a>)
            <li><a href="doc/manual.html#addon_foldcode">Code folding</a>
            <li><a href="doc/manual.html#option_extraKeys">Configurable</a> keybindings
            <li><a href="demo/vim.html">Vim</a>, <a href="demo/emacs.html">Emacs</a>, and <a href="demo/sublime.html">Sublime Text</a> bindings
            <li><a href="doc/manual.html#addon_search">Search and replace</a> interface
            <li><a href="doc/manual.html#addon_matchbrackets">Bracket</a> and <a href="doc/manual.html#addon_matchtags">tag</a> matching
            <li>Support for <a href="demo/buffers.html">split views</a>
            <li><a href="doc/manual.html#addon_lint">Linter integration</a>
            <li><a href="demo/variableheight.html">Mixing font sizes and styles</a>
            <li><a href="demo/theme.html">Various themes</a>
            <li>Able to <a href="demo/resize.html">resize to fit content</a>
            <li><a href="doc/manual.html#mark_replacedWith">Inline</a> and <a href="doc/manual.html#addLineWidget">block</a> widgets
            <li>Programmable <a href="demo/marker.html">gutters</a>
            <li>Making ranges of text <a href="doc/manual.html#markText">styled, read-only, or atomic</a>
            <li><a href="demo/bidi.html">Bi-directional text</a> support
            <li>Many other <a href="doc/manual.html#api">methods</a> and <a href="doc/manual.html#addons">addons</a>...
          </ul>
        </section>
        
        <section id=community>
          <h2>Community</h2>
        
          <p>CodeMirror is an open-source project shared under
          an <a href="LICENSE">MIT license</a>. It is the editor used in the
          dev tools for
          both <a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox</a>
          and <a href="https://developers.google.com/chrome-developer-tools/">Chrome</a>, <a href="http://www.lighttable.com/">Light
          Table</a>, <a href="http://brackets.io/">Adobe
          Brackets</a>, <a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a>,
          and <a href="doc/realworld.html">many other projects</a>.</p>
        
          <p>Development and bug tracking happens
          on <a href="https://github.com/codemirror/CodeMirror/">github</a>
          (<a href="http://marijnhaverbeke.nl/git/codemirror">alternate git
          repository</a>).
          Please <a href="http://codemirror.net/doc/reporting.html">read these
          pointers</a> before submitting a bug. Use pull requests to submit
          patches. All contributions must be released under the same MIT
          license that CodeMirror uses.</p>
        
          <p>Discussion around the project is done on
          a <a href="http://discuss.codemirror.net">discussion forum</a>.
          There is also
          the <a href="http://groups.google.com/group/codemirror-announce">codemirror-announce</a>
          list, which is only used for major announcements (such as new
          versions). If needed, you can
          contact <a href="mailto:marijnh@gmail.com">the maintainer</a>
          directly.</p>
        
          <p>A list of CodeMirror-related software that is not part of the
          main distribution is maintained
          on <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">our
          wiki</a>. Feel free to add your project.</p>
        </section>
        
        <section id=browsersupport>
          <h2>Browser support</h2>
          <p>The <em>desktop</em> versions of the following browsers,
          in <em>standards mode</em> (HTML5 <code>&lt;!doctype html></code>
          recommended) are supported:</p>
          <table style="margin-bottom: 1em">
            <tr><th>Firefox</th><td>version 4 and up</td></tr>
            <tr><th>Chrome</th><td>any version</td></tr>
            <tr><th>Safari</th><td>version 5.2 and up</td></tr>
            <tr><th style="padding-right: 1em;">Internet Explorer</th><td>version 8 and up</td></tr>
            <tr><th>Opera</th><td>version 9 and up</td></tr>
          </table>
          <p>Support for modern mobile browsers is experimental. Recent
          versions of the iOS browser and Chrome on Android should work
          pretty well.</p>
        </section>
        
        </article>
        
      • package.json
        {
            "name": "codemirror",
            "version":"5.0.1",
            "main": "lib/codemirror.js",
            "description": "In-browser code editing made bearable",
            "licenses": [{"type": "MIT",
                          "url": "http://codemirror.net/LICENSE"}],
            "directories": {"lib": "./lib"},
            "scripts": {"test": "node ./test/run.js"},
            "devDependencies": {"node-static": "0.6.0",
                                "phantomjs": "1.9.2-5",
                                "blint": ">=0.1.1"},
            "bugs": "http://github.com/codemirror/CodeMirror/issues",
            "keywords": ["JavaScript", "CodeMirror", "Editor"],
            "homepage": "http://codemirror.net",
            "maintainers":[{"name": "Marijn Haverbeke",
                            "email": "marijnh@gmail.com",
                            "web": "http://marijnhaverbeke.nl"}],
            "repository": {"type": "git",
                           "url": "https://github.com/codemirror/CodeMirror.git"}
        }
        
    • es5-shim
      • es5-sham.min.js
        /*!
         * https://github.com/es-shims/es5-shim
         * @license es5-shim Copyright 2009-2014 by contributors, MIT License
         * see https://github.com/es-shims/es5-shim/blob/v4.0.6/LICENSE
         */
        (function(e,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{e.returnExports=t()}})(this,function(){var e=Function.prototype.call;var t=Object.prototype;var r=e.bind(t.hasOwnProperty);var n;var o;var c;var i;var f=r(t,"__defineGetter__");if(f){n=e.bind(t.__defineGetter__);o=e.bind(t.__defineSetter__);c=e.bind(t.__lookupGetter__);i=e.bind(t.__lookupSetter__)}if(!Object.getPrototypeOf){Object.getPrototypeOf=function E(e){var r=e.__proto__;if(r||r===null){return r}else if(e.constructor){return e.constructor.prototype}else{return t}}}function l(e){try{e.sentinel=0;return Object.getOwnPropertyDescriptor(e,"sentinel").value===0}catch(t){}}if(Object.defineProperty){var u=l({});var a=typeof document==="undefined"||l(document.createElement("div"));if(!a||!u){var p=Object.getOwnPropertyDescriptor}}if(!Object.getOwnPropertyDescriptor||p){var b="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function g(e,n){if(typeof e!=="object"&&typeof e!=="function"||e===null){throw new TypeError(b+e)}if(p){try{return p.call(Object,e,n)}catch(o){}}var l;if(!r(e,n)){return l}l={enumerable:true,configurable:true};if(f){var u=e.__proto__;var a=e!==t;if(a){e.__proto__=t}var s=c(e,n);var O=i(e,n);if(a){e.__proto__=u}if(s||O){if(s){l.get=s}if(O){l.set=O}return l}}l.value=e[n];l.writable=true;return l}}if(!Object.getOwnPropertyNames){Object.getOwnPropertyNames=function T(e){return Object.keys(e)}}if(!Object.create){var s;var O=!({__proto__:null}instanceof Object);if(O||typeof document==="undefined"){s=function(){return{__proto__:null}}}else{s=function(){var e=document.createElement("iframe");var t=document.body||document.documentElement;e.style.display="none";t.appendChild(e);e.src="javascript:";var r=e.contentWindow.Object.prototype;t.removeChild(e);e=null;delete r.constructor;delete r.hasOwnProperty;delete r.propertyIsEnumerable;delete r.isPrototypeOf;delete r.toLocaleString;delete r.toString;delete r.valueOf;r.__proto__=null;function n(){}n.prototype=r;s=function(){return new n};return new n}}Object.create=function x(e,t){var r;function n(){}if(e===null){r=s()}else{if(typeof e!=="object"&&typeof e!=="function"){throw new TypeError("Object prototype may only be an Object or null")}n.prototype=e;r=new n;r.__proto__=e}if(t!==void 0){Object.defineProperties(r,t)}return r}}function j(e){try{Object.defineProperty(e,"sentinel",{});return"sentinel"in e}catch(t){}}if(Object.defineProperty){var d=j({});var y=typeof document==="undefined"||j(document.createElement("div"));if(!d||!y){var _=Object.defineProperty,v=Object.defineProperties}}if(!Object.defineProperty||_){var w="Property description must be an object: ";var P="Object.defineProperty called on non-object: ";var h="getters & setters can not be defined on this javascript engine";Object.defineProperty=function z(e,r,l){if(typeof e!=="object"&&typeof e!=="function"||e===null){throw new TypeError(P+e)}if(typeof l!=="object"&&typeof l!=="function"||l===null){throw new TypeError(w+l)}if(_){try{return _.call(Object,e,r,l)}catch(u){}}if("value"in l){if(f&&(c(e,r)||i(e,r))){var a=e.__proto__;e.__proto__=t;delete e[r];e[r]=l.value;e.__proto__=a}else{e[r]=l.value}}else{if(!f){throw new TypeError(h)}if("get"in l){n(e,r,l.get)}if("set"in l){o(e,r,l.set)}}return e}}if(!Object.defineProperties||v){Object.defineProperties=function S(e,t){if(v){try{return v.call(Object,e,t)}catch(n){}}for(var o in t){if(r(t,o)&&o!=="__proto__"){Object.defineProperty(e,o,t[o])}}return e}}if(!Object.seal){Object.seal=function D(e){if(Object(e)!==e){throw new TypeError("Object.seal can only be called on Objects.")}return e}}if(!Object.freeze){Object.freeze=function F(e){if(Object(e)!==e){throw new TypeError("Object.freeze can only be called on Objects.")}return e}}try{Object.freeze(function(){})}catch(m){Object.freeze=function k(e){return function t(r){if(typeof r==="function"){return r}else{return e(r)}}}(Object.freeze)}if(!Object.preventExtensions){Object.preventExtensions=function G(e){if(Object(e)!==e){throw new TypeError("Object.preventExtensions can only be called on Objects.")}return e}}if(!Object.isSealed){Object.isSealed=function C(e){if(Object(e)!==e){throw new TypeError("Object.isSealed can only be called on Objects.")}return false}}if(!Object.isFrozen){Object.isFrozen=function N(e){if(Object(e)!==e){throw new TypeError("Object.isFrozen can only be called on Objects.")}return false}}if(!Object.isExtensible){Object.isExtensible=function I(e){if(Object(e)!==e){throw new TypeError("Object.isExtensible can only be called on Objects.")}var t="";while(r(e,t)){t+="?"}e[t]=true;var n=r(e,t);delete e[t];return n}}});
        
      • es5-shim.min.js
        /*!
         * https://github.com/es-shims/es5-shim
         * @license es5-shim Copyright 2009-2014 by contributors, MIT License
         * see https://github.com/es-shims/es5-shim/blob/v4.0.6/LICENSE
         */
        (function(t,e){"use strict";if(typeof define==="function"&&define.amd){define(e)}else if(typeof exports==="object"){module.exports=e()}else{t.returnExports=e()}})(this,function(){var t=Array.prototype;var e=Object.prototype;var r=Function.prototype;var n=String.prototype;var i=Number.prototype;var a=t.slice;var o=t.splice;var u=t.push;var l=t.unshift;var s=r.call;var f=e.toString;var c=function(t){return f.call(t)==="[object Function]"};var p=function(t){return f.call(t)==="[object RegExp]"};var h=function ue(t){return f.call(t)==="[object Array]"};var v=function le(t){return f.call(t)==="[object String]"};var g=function se(t){var e=f.call(t);var r=e==="[object Arguments]";if(!r){r=!h(t)&&t!==null&&typeof t==="object"&&typeof t.length==="number"&&t.length>=0&&c(t.callee)}return r};var y=function(t){var e=Object.defineProperty&&function(){try{Object.defineProperty({},"x",{});return true}catch(t){return false}}();var r;if(e){r=function(t,e,r,n){if(!n&&e in t){return}Object.defineProperty(t,e,{configurable:true,enumerable:false,writable:true,value:r})}}else{r=function(t,e,r,n){if(!n&&e in t){return}t[e]=r}}return function n(e,i,a){for(var o in i){if(t.call(i,o)){r(e,o,i[o],a)}}}}(e.hasOwnProperty);function d(t){var e=+t;if(e!==e){e=0}else if(e!==0&&e!==1/0&&e!==-(1/0)){e=(e>0||-1)*Math.floor(Math.abs(e))}return e}function m(t){var e=typeof t;return t===null||e==="undefined"||e==="boolean"||e==="number"||e==="string"}function b(t){var e,r,n;if(m(t)){return t}r=t.valueOf;if(c(r)){e=r.call(t);if(m(e)){return e}}n=t.toString;if(c(n)){e=n.call(t);if(m(e)){return e}}throw new TypeError}var w={ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return Object(t)},ToUint32:function fe(t){return t>>>0}};var x=function ce(){};y(r,{bind:function pe(t){var e=this;if(!c(e)){throw new TypeError("Function.prototype.bind called on incompatible "+e)}var r=a.call(arguments,1);var n;var i=function(){if(this instanceof n){var i=e.apply(this,r.concat(a.call(arguments)));if(Object(i)===i){return i}return this}else{return e.apply(t,r.concat(a.call(arguments)))}};var o=Math.max(0,e.length-r.length);var u=[];for(var l=0;l<o;l++){u.push("$"+l)}n=Function("binder","return function ("+u.join(",")+"){ return binder.apply(this, arguments); }")(i);if(e.prototype){x.prototype=e.prototype;n.prototype=new x;x.prototype=null}return n}});var O=s.bind(e.hasOwnProperty);var T=function(){var t=[1,2];var e=t.splice();return t.length===2&&h(e)&&e.length===0}();y(t,{splice:function he(t,e){if(arguments.length===0){return[]}else{return o.apply(this,arguments)}}},!T);var j=function(){var e={};t.splice.call(e,0,0,1);return e.length===1}();y(t,{splice:function ve(t,e){if(arguments.length===0){return[]}var r=arguments;this.length=Math.max(d(this.length),0);if(arguments.length>0&&typeof e!=="number"){r=a.call(arguments);if(r.length<2){r.push(this.length-t)}else{r[1]=d(e)}}return o.apply(this,r)}},!j);var S=[].unshift(0)!==1;y(t,{unshift:function(){l.apply(this,arguments);return this.length}},S);y(Array,{isArray:h});var E=Object("a");var N=E[0]!=="a"||!(0 in E);var I=function ge(t){var e=true;var r=true;if(t){t.call("foo",function(t,r,n){if(typeof n!=="object"){e=false}});t.call([1],function(){"use strict";r=typeof this==="string"},"x")}return!!t&&e&&r};y(t,{forEach:function ye(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=arguments[1],i=-1,a=r.length>>>0;if(!c(t)){throw new TypeError}while(++i<a){if(i in r){t.call(n,r[i],i,e)}}}},!I(t.forEach));y(t,{map:function de(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=Array(n),a=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var o=0;o<n;o++){if(o in r){i[o]=t.call(a,r[o],o,e)}}return i}},!I(t.map));y(t,{filter:function me(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=[],a,o=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var u=0;u<n;u++){if(u in r){a=r[u];if(t.call(o,a,u,e)){i.push(a)}}}return i}},!I(t.filter));y(t,{every:function be(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&!t.call(i,r[a],a,e)){return false}}return true}},!I(t.every));y(t,{some:function we(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&t.call(i,r[a],a,e)){return true}}return false}},!I(t.some));var D=false;if(t.reduce){D=typeof t.reduce.call("es5",function(t,e,r,n){return n})==="object"}y(t,{reduce:function xe(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0;if(!c(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in r){a=r[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in r){a=t.call(void 0,a,r[i],i,e)}}return a}},!D);var M=false;if(t.reduceRight){M=typeof t.reduceRight.call("es5",function(t,e,r,n){return n})==="object"}y(t,{reduceRight:function Oe(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0;if(!c(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i,a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in r){i=r[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in r){i=t.call(void 0,i,r[a],a,e)}}while(a--);return i}},!M);var F=Array.prototype.indexOf&&[0,1].indexOf(1,2)!==-1;y(t,{indexOf:function Te(t){var e=N&&v(this)?this.split(""):w.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=0;if(arguments.length>1){n=d(arguments[1])}n=n>=0?n:Math.max(0,r+n);for(;n<r;n++){if(n in e&&e[n]===t){return n}}return-1}},F);var R=Array.prototype.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;y(t,{lastIndexOf:function je(t){var e=N&&v(this)?this.split(""):w.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=r-1;if(arguments.length>1){n=Math.min(n,d(arguments[1]))}n=n>=0?n:r-Math.abs(n);for(;n>=0;n--){if(n in e&&t===e[n]){return n}}return-1}},R);var U=!{toString:null}.propertyIsEnumerable("toString"),k=function(){}.propertyIsEnumerable("prototype"),C=!O("x","0"),A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],P=A.length;y(Object,{keys:function Se(t){var e=c(t),r=g(t),n=t!==null&&typeof t==="object",i=n&&v(t);if(!n&&!e&&!r){throw new TypeError("Object.keys called on a non-object")}var a=[];var o=k&&e;if(i&&C||r){for(var u=0;u<t.length;++u){a.push(String(u))}}if(!r){for(var l in t){if(!(o&&l==="prototype")&&O(t,l)){a.push(String(l))}}}if(U){var s=t.constructor,f=s&&s.prototype===t;for(var p=0;p<P;p++){var h=A[p];if(!(f&&h==="constructor")&&O(t,h)){a.push(h)}}}return a}});var Z=Object.keys&&function(){return Object.keys(arguments).length===2}(1,2);var J=Object.keys;y(Object,{keys:function Ee(e){if(g(e)){return J(t.slice.call(e))}else{return J(e)}}},!Z);var z=-621987552e5;var $="-000001";var B=Date.prototype.toISOString&&new Date(z).toISOString().indexOf($)===-1;y(Date.prototype,{toISOString:function Ne(){var t,e,r,n,i;if(!isFinite(this)){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}n=this.getUTCFullYear();i=this.getUTCMonth();n+=Math.floor(i/12);i=(i%12+12)%12;t=[i+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];n=(n<0?"-":n>9999?"+":"")+("00000"+Math.abs(n)).slice(0<=n&&n<=9999?-4:-6);e=t.length;while(e--){r=t[e];if(r<10){t[e]="0"+r}}return n+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"}},B);var H=false;try{H=Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(z).toJSON().indexOf($)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(L){}if(!H){Date.prototype.toJSON=function Ie(t){var e=Object(this),r=b(e),n;if(typeof r==="number"&&!isFinite(r)){return null}n=e.toISOString;if(typeof n!=="function"){throw new TypeError("toISOString property is not callable")}return n.call(e)}}var X=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var Y=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"));var q=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(!Date.parse||q||Y||!X){Date=function(t){function e(r,n,i,a,o,u,l){var s=arguments.length;if(this instanceof t){var f=s===1&&String(r)===r?new t(e.parse(r)):s>=7?new t(r,n,i,a,o,u,l):s>=6?new t(r,n,i,a,o,u):s>=5?new t(r,n,i,a,o):s>=4?new t(r,n,i,a):s>=3?new t(r,n,i):s>=2?new t(r,n):s>=1?new t(r):new t;f.constructor=e;return f}return t.apply(this,arguments)}var r=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];function i(t,e){var r=e>1?1:0;return n[e]+Math.floor((t-1969+r)/4)-Math.floor((t-1901+r)/100)+Math.floor((t-1601+r)/400)+365*(t-1970)}function a(e){return Number(new t(1970,0,1,0,0,0,e))}for(var o in t){e[o]=t[o]}e.now=t.now;e.UTC=t.UTC;e.prototype=t.prototype;e.prototype.constructor=e;e.parse=function u(e){var n=r.exec(e);if(n){var o=Number(n[1]),u=Number(n[2]||1)-1,l=Number(n[3]||1)-1,s=Number(n[4]||0),f=Number(n[5]||0),c=Number(n[6]||0),p=Math.floor(Number(n[7]||0)*1e3),h=Boolean(n[4]&&!n[8]),v=n[9]==="-"?1:-1,g=Number(n[10]||0),y=Number(n[11]||0),d;if(s<(f>0||c>0||p>0?24:25)&&f<60&&c<60&&p<1e3&&u>-1&&u<12&&g<24&&y<60&&l>-1&&l<i(o,u+1)-i(o,u)){d=((i(o,u)+l)*24+s+g*v)*60;d=((d+f+y*v)*60+c)*1e3+p;if(h){d=a(d)}if(-864e13<=d&&d<=864e13){return d}}return NaN}return t.parse.apply(this,arguments)};return e}(Date)}if(!Date.now){Date.now=function De(){return(new Date).getTime()}}var G=i.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128");var K={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function Me(t,e){var r=-1;while(++r<K.size){e+=t*K.data[r];K.data[r]=e%K.base;e=Math.floor(e/K.base)}},divide:function Fe(t){var e=K.size,r=0;while(--e>=0){r+=K.data[e];K.data[e]=Math.floor(r/t);r=r%t*K.base}},numToString:function Re(){var t=K.size;var e="";while(--t>=0){if(e!==""||t===0||K.data[t]!==0){var r=String(K.data[t]);if(e===""){e=r}else{e+="0000000".slice(0,7-r.length)+r}}}return e},pow:function Ue(t,e,r){return e===0?r:e%2===1?Ue(t,e-1,r*t):Ue(t*t,e/2,r)},log:function ke(t){var e=0;while(t>=4096){e+=12;t/=4096}while(t>=2){e+=1;t/=2}return e}};y(i,{toFixed:function Ce(t){var e,r,n,i,a,o,u,l;e=Number(t);e=e!==e?0:Math.floor(e);if(e<0||e>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}r=Number(this);if(r!==r){return"NaN"}if(r<=-1e21||r>=1e21){return String(r)}n="";if(r<0){n="-";r=-r}i="0";if(r>1e-21){a=K.log(r*K.pow(2,69,1))-69;o=a<0?r*K.pow(2,-a,1):r/K.pow(2,a,1);o*=4503599627370496;a=52-a;if(a>0){K.multiply(0,o);u=e;while(u>=7){K.multiply(1e7,0);u-=7}K.multiply(K.pow(10,u,1),0);u=a-1;while(u>=23){K.divide(1<<23);u-=23}K.divide(1<<u);K.multiply(1,1);K.divide(2);i=K.numToString()}else{K.multiply(0,o);K.multiply(1<<-a,0);i=K.numToString()+"0.00000000000000000000".slice(2,2+e)}}if(e>0){l=i.length;if(l<=e){i=n+"0.0000000000000000000".slice(0,e-l+2)+i}else{i=n+i.slice(0,l-e)+"."+i.slice(l-e)}}else{i=n+i}return i}},G);var Q=n.split;if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";n.split=function(e,r){var n=this;if(typeof e==="undefined"&&r===0){return[]}if(f.call(e)!=="[object RegExp]"){return Q.call(this,e,r)}var i=[],a=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":""),o=0,l,s,c,p;e=new RegExp(e.source,a+"g");n+="";if(!t){l=new RegExp("^"+e.source+"$(?!\\s)",a)}r=typeof r==="undefined"?-1>>>0:w.ToUint32(r);s=e.exec(n);while(s){c=s.index+s[0].length;if(c>o){i.push(n.slice(o,s.index));if(!t&&s.length>1){s[0].replace(l,function(){for(var t=1;t<arguments.length-2;t++){if(typeof arguments[t]==="undefined"){s[t]=void 0}}})}if(s.length>1&&s.index<n.length){u.apply(i,s.slice(1))}p=s[0].length;o=c;if(i.length>=r){break}}if(e.lastIndex===s.index){e.lastIndex++}s=e.exec(n)}if(o===n.length){if(p||!e.test("")){i.push("")}}else{i.push(n.slice(o))}return i.length>r?i.slice(0,r):i}})()}else if("0".split(void 0,0).length){n.split=function Ae(t,e){if(typeof t==="undefined"&&e===0){return[]}return Q.call(this,t,e)}}var V=n.replace;var W=function(){var t=[];"x".replace(/x(.)?/g,function(e,r){t.push(r)});return t.length===1&&typeof t[0]==="undefined"}();if(!W){n.replace=function Pe(t,e){var r=c(e);var n=p(t)&&/\)[*?]/.test(t.source);if(!r||!n){return V.call(this,t,e)}else{var i=function(r){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(r)||[];t.lastIndex=i;a.push(arguments[n-2],arguments[n-1]);return e.apply(this,a)};return V.call(this,t,i)}}}var _=n.substr;var te="".substr&&"0b".substr(-1)!=="b";y(n,{substr:function Ze(t,e){return _.call(this,t<0?(t=this.length+t)<0?0:t:t,e)}},te);var ee="	\n\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var re="\u200b";var ne="["+ee+"]";var ie=new RegExp("^"+ne+ne+"*");var ae=new RegExp(ne+ne+"*$");var oe=n.trim&&(ee.trim()||!re.trim());y(n,{trim:function Je(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return String(this).replace(ie,"").replace(ae,"")}},oe);if(parseInt(ee+"08")!==8||parseInt(ee+"0x16")!==22){parseInt=function(t){var e=/^0[xX]/;return function r(n,i){n=String(n).trim();if(!Number(i)){i=e.test(n)?16:10}return t(n,i)}}(parseInt)}});
        
    • github
      • github.js
        /*!
         * @overview  Github.js
         *
         * @copyright (c) 2013 Michael Aufreiter, Development Seed
         *            Github.js is freely distributable.
         *
         * @license   Licensed under MIT license
         *
         *            For all details and documentation:
         *            http://substance.io/michael/github
         */
        
        (function() {
        
          // Initial Setup
          // -------------
        
          var XMLHttpRequest,  _;
          if (typeof exports !== 'undefined') {
              XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
              _ = require('underscore');
              btoa = require('btoa');
          } else {
              _ = window._;
          }
          //prefer native XMLHttpRequest always
          if (typeof window !== 'undefined' && typeof window.XMLHttpRequest !== 'undefined'){
              XMLHttpRequest = window.XMLHttpRequest;
          }
        
        
          var API_URL = 'https://api.github.com';
        
          var Github = function(options) {
        
            // HTTP Request Abstraction
            // =======
            //
            // I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec.
        
            function _request(method, path, data, cb, raw, sync) {
              function getURL() {
                var url = path.indexOf('//') >= 0 ? path : API_URL + path;
                return url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime();
              }
        
              var xhr = new XMLHttpRequest();
              if (!raw) {xhr.dataType = "json";}
        
              xhr.open(method, getURL(), !sync);
              if (!sync) {
                xhr.onreadystatechange = function () {
                  if (this.readyState == 4) {
                    if (this.status >= 200 && this.status < 300 || this.status === 304) {
                      cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this);
                    } else {
                      cb({path: path, request: this, error: this.status});
                    }
                  }
                };
              }
              xhr.setRequestHeader('Accept','application/vnd.github.v3.raw+json');
              xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8');
              if ((options.token) || (options.username && options.password)) {
                var authorization = options.token ? 'token ' + options.token : 'Basic ' + btoa(options.username + ':' + options.password);
                xhr.setRequestHeader('Authorization', authorization);
              }
              if (data)
                xhr.send(JSON.stringify(data));
              else
                xhr.send();
              if (sync) return xhr.response;
            }
        
            function _requestAllPages(path, cb) {
              var results = [];
              (function iterate() {
                _request("GET", path, null, function(err, res, xhr) {
                  if (err) {
                    return cb(err);
                  }
        
                  results.push.apply(results, res);
        
                  var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g),
                      next = _.find(links, function(link) { return /rel="next"/.test(link); });
        
                  if (next) {
                    next = (/<(.*)>/.exec(next) || [])[1];
                  }
        
                  if (!next) {
                    cb(err, results);
                  } else {
                    path = next;
                    iterate();
                  }
                });
              })();
            }
        
        
            // User API
            // =======
        
            Github.User = function() {
              this.repos = function(cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/user/repos?type=all&per_page=1000&sort=updated", function(err, res) {
                  cb(err, res);
                });
              };
        
              // List user organizations
              // -------
        
              this.orgs = function(cb) {
                _request("GET", "/user/orgs", null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // List authenticated user's gists
              // -------
        
              this.gists = function(cb) {
                _request("GET", "/gists", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // List authenticated user's unread notifications
              // -------
        
              this.notifications = function(cb) {
                _request("GET", "/notifications", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // Show user information
              // -------
        
              this.show = function(username, cb) {
                var command = username ? "/users/"+username : "/user";
        
                _request("GET", command, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // List user repositories
              // -------
        
              this.userRepos = function(username, cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/users/"+username+"/repos?type=all&per_page=1000&sort=updated", function(err, res) {
                  cb(err, res);
                });
              };
        
              // List a user's gists
              // -------
        
              this.userGists = function(username, cb) {
                _request("GET", "/users/"+username+"/gists", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // List organization repositories
              // -------
        
              this.orgRepos = function(orgname, cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/orgs/"+orgname+"/repos?type=all&&page_num=1000&sort=updated&direction=desc", function(err, res) {
                  cb(err, res);
                });
              };
        
              // Follow user
              // -------
        
              this.follow = function(username, cb) {
                _request("PUT", "/user/following/"+username, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // Unfollow user
              // -------
        
              this.unfollow = function(username, cb) {
                _request("DELETE", "/user/following/"+username, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // Create a repo
              // -------
              this.createRepo = function(options, cb) {
                _request("POST", "/user/repos", options, cb);
              };
        
            };
        
            // Repository API
            // =======
        
            Github.Repository = function(options) {
              var repo = options.name;
              var user = options.user;
        
              var that = this;
              var repoPath = "/repos/" + user + "/" + repo;
        
              var currentTree = {
                "branch": null,
                "sha": null
              };
        
        
              // Delete a repo
              // --------
        
              this.deleteRepo = function(cb) {
                _request("DELETE", repoPath, options, cb);
              };
        
              // Uses the cache if branch has not been changed
              // -------
        
              function updateTree(branch, cb) {
                if (branch === currentTree.branch && currentTree.sha) return cb(null, currentTree.sha);
                that.getRef("heads/"+branch, function(err, sha) {
                  currentTree.branch = branch;
                  currentTree.sha = sha;
                  cb(err, sha);
                });
              }
        
              // Get a particular reference
              // -------
        
              this.getRef = function(ref, cb) {
                _request("GET", repoPath + "/git/refs/" + ref, null, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.object.sha);
                });
              };
        
              // Create a new reference
              // --------
              //
              // {
              //   "ref": "refs/heads/my-new-branch-name",
              //   "sha": "827efc6d56897b048c772eb4087f854f46256132"
              // }
        
              this.createRef = function(options, cb) {
                _request("POST", repoPath + "/git/refs", options, cb);
              };
        
              // Delete a reference
              // --------
              //
              // repo.deleteRef('heads/gh-pages')
              // repo.deleteRef('tags/v1.0')
        
              this.deleteRef = function(ref, cb) {
                _request("DELETE", repoPath + "/git/refs/"+ref, options, cb);
              };
        
              // Create a repo
              // -------
        
              this.createRepo = function(options, cb) {
                _request("POST", "/user/repos", options, cb);
              };
        
              // Delete a repo
              // --------
        
              this.deleteRepo = function(cb) {
                _request("DELETE", repoPath, options, cb);
              };
        
              // List all tags of a repository
              // -------
        
              this.listTags = function(cb) {
                _request("GET", repoPath + "/tags", null, function(err, tags) {
                  if (err) return cb(err);
                  cb(null, tags);
                });
              };
        
              // List all pull requests of a respository
              // -------
        
              this.listPulls = function(state, cb) {
                _request("GET", repoPath + "/pulls" + (state ? '?state=' + state : ''), null, function(err, pulls) {
                  if (err) return cb(err);
                  cb(null, pulls);
                });
              };
        
              // Gets details for a specific pull request
              // -------
        
              this.getPull = function(number, cb) {
                _request("GET", repoPath + "/pulls/" + number, null, function(err, pull) {
                  if (err) return cb(err);
                  cb(null, pull);
                });
              };
        
              // Retrieve the changes made between base and head
              // -------
        
              this.compare = function(base, head, cb) {
                _request("GET", repoPath + "/compare/" + base + "..." + head, null, function(err, diff) {
                  if (err) return cb(err);
                  cb(null, diff);
                });
              };
        
              // List all branches of a repository
              // -------
        
              this.listBranches = function(cb) {
                _request("GET", repoPath + "/git/refs/heads", null, function(err, heads) {
                  if (err) return cb(err);
                  cb(null, _.map(heads, function(head) { return _.last(head.ref.split('/')); }));
                });
              };
        
              // Retrieve the contents of a blob
              // -------
        
              this.getBlob = function(sha, cb) {
                _request("GET", repoPath + "/git/blobs/" + sha, null, cb, 'raw');
              };
        
              // For a given file path, get the corresponding sha (blob for files, tree for dirs)
              // -------
        
              this.getSha = function(branch, path, cb) {
                if (!path || path === "") return that.getRef("heads/"+branch, cb);
                _request("GET", repoPath + "/contents/"+path, {ref: branch}, function(err, pathContent) {
                  if (err) return cb(err);
                  cb(null, pathContent.sha);
                });
              };
        
              // Retrieve the tree a commit points to
              // -------
        
              this.getTree = function(tree, cb) {
                _request("GET", repoPath + "/git/trees/"+tree, null, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.tree);
                });
              };
        
              // Post a new blob object, getting a blob SHA back
              // -------
        
              this.postBlob = function(content, cb) {
                if (typeof(content) === "string") {
                  content = {
                    "content": content,
                    "encoding": "utf-8"
                  };
                } else {
                  	content = {
                      "content": btoa(String.fromCharCode.apply(null, new Uint8Array(content))),
                      "encoding": "base64"
                    };
                  }
        
                _request("POST", repoPath + "/git/blobs", content, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Update an existing tree adding a new blob object getting a tree SHA back
              // -------
        
              this.updateTree = function(baseTree, path, blob, cb) {
                var data = {
                  "base_tree": baseTree,
                  "tree": [
                    {
                      "path": path,
                      "mode": "100644",
                      "type": "blob",
                      "sha": blob
                    }
                  ]
                };
                _request("POST", repoPath + "/git/trees", data, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Post a new tree object having a file path pointer replaced
              // with a new blob SHA getting a tree SHA back
              // -------
        
              this.postTree = function(tree, cb) {
                _request("POST", repoPath + "/git/trees", { "tree": tree }, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Create a new commit object with the current commit SHA as the parent
              // and the new tree SHA, getting a commit SHA back
              // -------
        
              this.commit = function(parent, tree, message, cb) {
                var user = new Github.User();
                user.show(null, function(err, userData){
                  if (err) return cb(err);
                  var data = {
                    "message": message,
                    "author": {
                      "name": options.user,
                      "email": userData.email
                    },
                    "parents": [
                      parent
                    ],
                    "tree": tree
                  };
                  _request("POST", repoPath + "/git/commits", data, function(err, res) {
                    if (err) return cb(err);
                    currentTree.sha = res.sha; // update latest commit
                    cb(null, res.sha);
                  });
                });
              };
        
              // Update the reference of your head to point to the new commit SHA
              // -------
        
              this.updateHead = function(head, commit, cb) {
                _request("PATCH", repoPath + "/git/refs/heads/" + head, { "sha": commit }, function(err, res) {
                  cb(err);
                });
              };
        
              // Show repository information
              // -------
        
              this.show = function(cb) {
                _request("GET", repoPath, null, cb);
              };
        
              // Get contents
              // --------
        
              this.contents = function(ref, path, cb) {
                _request("GET", repoPath + "/contents/"+path, { ref: ref }, cb);
              };
        
              // Fork repository
              // -------
        
              this.fork = function(cb) {
                _request("POST", repoPath + "/forks", null, cb);
              };
        
              // Branch repository
              // --------
        
              this.branch = function(oldBranch,newBranch,cb) {
                if(arguments.length === 2 && typeof arguments[1] === "function") {
                  cb = newBranch;
                  newBranch = oldBranch;
                  oldBranch = "master";
                }
                this.getRef("heads/" + oldBranch, function(err,ref) {
                  if(err && cb) return cb(err);
                  that.createRef({
                    ref: "refs/heads/" + newBranch,
                    sha: ref
                  },cb);
                });
              };
        
              // Create pull request
              // --------
        
              this.createPullRequest = function(options, cb) {
                _request("POST", repoPath + "/pulls", options, cb);
              };
        
              // List hooks
              // --------
        
              this.listHooks = function(cb) {
                _request("GET", repoPath + "/hooks", null, cb);
              };
        
              // Get a hook
              // --------
        
              this.getHook = function(id, cb) {
                _request("GET", repoPath + "/hooks/" + id, null, cb);
              };
        
              // Create a hook
              // --------
        
              this.createHook = function(options, cb) {
                _request("POST", repoPath + "/hooks", options, cb);
              };
        
              // Edit a hook
              // --------
        
              this.editHook = function(id, options, cb) {
                _request("PATCH", repoPath + "/hooks/" + id, options, cb);
              };
        
              // Delete a hook
              // --------
        
              this.deleteHook = function(id, cb) {
                _request("DELETE", repoPath + "/hooks/" + id, null, cb);
              };
        
              // Read file at given path
              // -------
        
              this.read = function(branch, path, cb) {
                _request("GET", repoPath + "/contents/"+path, {ref: branch}, function(err, obj) {
                  if (err && err.error === 404) return cb("not found", null, null);
        
                  if (err) return cb(err);
                  cb(null, obj);
                }, true);
              };
        
        
              // Remove a file
              // -------
        
              this.remove = function(branch, path, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (err) return cb(err);
                  _request("DELETE", repoPath + "/contents/" + path, {
                    message: path + " is removed",
                    sha: sha,
                    branch: branch
                  }, cb);
                });
              };
        
              // Delete a file from the tree
              // -------
        
              this.delete = function(branch, path, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (!sha) return cb("not found", null);
                  var delPath = repoPath + "/contents/" + path;
                  var params = {
                    "message": "Deleted " + path,
                    "sha": sha
                  };
                  delPath += "?message=" + encodeURIComponent(params.message);
                  delPath += "&sha=" + encodeURIComponent(params.sha);
                  delPath += '&branch=' + encodeURIComponent(branch);
                  _request("DELETE", delPath, null, cb);
                });
              };
        
              // Move a file to a new location
              // -------
        
              this.move = function(branch, path, newPath, cb) {
                updateTree(branch, function(err, latestCommit) {
                  that.getTree(latestCommit+"?recursive=true", function(err, tree) {
                    // Update Tree
                    _.each(tree, function(ref) {
                      if (ref.path === path) ref.path = newPath;
                      if (ref.type === "tree") delete ref.sha;
                    });
        
                    that.postTree(tree, function(err, rootTree) {
                      that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) {
                        that.updateHead(branch, commit, function(err) {
                          cb(err);
                        });
                      });
                    });
                  });
                });
              };
        
              // Write file contents to a given branch and path
              // -------
        
              this.write = function(branch, path, content, message, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (err && err.error!=404) return cb(err);
                  _request("PUT", repoPath + "/contents/" + path, {
                    message: message,
                    content: btoa(content),
                    branch: branch,
                    sha: sha
                  }, cb);
                });
              };
        
              // List commits on a repository. Takes an object of optional paramaters:
              // sha: SHA or branch to start listing commits from
              // path: Only commits containing this file path will be returned
              // since: ISO 8601 date - only commits after this date will be returned
              // until: ISO 8601 date - only commits before this date will be returned
              // -------
        
              this.getCommits = function(options, cb) {
                  options = options || {};
                  var url = repoPath + "/commits";
                  var params = [];
                  if (options.sha) {
                      params.push("sha=" + encodeURIComponent(options.sha));
                  }
                  if (options.path) {
                      params.push("path=" + encodeURIComponent(options.path));
                  }
                  if (options.since) {
                      var since = options.since;
                      if (since.constructor === Date) {
                          since = since.toISOString();
                      }
                      params.push("since=" + encodeURIComponent(since));
                  }
                  if (options.until) {
                      var until = options.until;
                      if (until.constructor === Date) {
                          until = until.toISOString();
                      }
                      params.push("until=" + encodeURIComponent(until));
                  }
                  if (options.page) {
                      params.push("page=" + options.page);
                  }
                  if (options.perpage) {
                      params.push("per_page=" + options.perpage);
                  }
                  if (params.length > 0) {
                      url += "?" + params.join("&");
                  }
                  _request("GET", url, null, cb);
              };
            };
        
            // Gists API
            // =======
        
            Github.Gist = function(options) {
              var id = options.id;
              var gistPath = "/gists/"+id;
        
              // Read the gist
              // --------
        
              this.read = function(cb) {
                _request("GET", gistPath, null, function(err, gist) {
                  cb(err, gist);
                });
              };
        
              // Create the gist
              // --------
              // {
              //  "description": "the description for this gist",
              //    "public": true,
              //    "files": {
              //      "file1.txt": {
              //        "content": "String file contents"
              //      }
              //    }
              // }
        
              this.create = function(options, cb){
                _request("POST","/gists", options, cb);
              };
        
              // Delete the gist
              // --------
        
              this.delete = function(cb) {
                _request("DELETE", gistPath, null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Fork a gist
              // --------
        
              this.fork = function(cb) {
                _request("POST", gistPath+"/fork", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Update a gist with the new stuff
              // --------
        
              this.update = function(options, cb) {
                _request("PATCH", gistPath, options, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Star a gist
              // --------
        
              this.star = function(cb) {
                _request("PUT", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Untar a gist
              // --------
        
              this.unstar = function(cb) {
                _request("DELETE", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Check if a gist is starred
              // --------
        
              this.isStarred = function(cb) {
                _request("GET", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
            };
        
            // Issues API
            // ==========
        
            Github.Issue = function(options) {
              var path = "/repos/" + options.user + "/" + options.repo + "/issues";
        
              this.list = function(options, cb) {
                _request("GET", path, options, cb);
              };
            };
        
            // Top Level API
            // -------
        
            this.getIssues = function(user, repo) {
              return new Github.Issue({user: user, repo: repo});
            };
        
            this.getRepo = function(user, repo) {
              return new Github.Repository({user: user, name: repo});
            };
        
            this.getUser = function() {
              return new Github.User();
            };
        
            this.getGist = function(id) {
              return new Github.Gist({id: id});
            };
          };
        
        
          if (typeof exports !== 'undefined') {
            // Github = exports;
            module.exports = Github;
          } else {
            window.Github = Github;
          }
        }).call(this);
    • google-diff-match-patch
      • diff_match_patch.js
        (function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}
        diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,
        b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
        diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,
        d):this.diff_bisect_(a,b,d)};
        diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,""]);for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
        diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=
        u)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};
        diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
        diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf("\n",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]="";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};
        diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
        diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
        diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
        diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;
        var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
        diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];
        d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};
        diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);
        return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=
        h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
        diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};
        diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,""]);for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-
        g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,
        a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};
        diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case 1:b[g]='<ins style="background:#e6ffe6;">'+j+"</ins>";break;case -1:b[g]='<del style="background:#ffe6e6;">'+j+"</del>";break;case 0:b[g]="<span>"+j+"</span>"}}return b.join("")};
        diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
        diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]="+"+encodeURI(a[c][1]);break;case -1:b[c]="-"+a[c][1].length;break;case 0:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
        diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+
        f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
        diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+
        k)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};
        diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
        diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=
        c.length+d.length;a.length2+=c.length+d.length}};
        diff_match_patch.prototype.patch_make=function(a,b,c){var d;if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
        if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&
        e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
        diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);
        if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,
        j+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
        diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,
        c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
        diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),
        j=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&
        (h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
        diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
        parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push([-1,g]);else if("+"==e)f.diffs.push([1,g]);else if(" "==e)f.diffs.push([0,g]);else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
        diff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1;b=0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2;a=["@@ -"+a+" +"+b+" @@\n"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c="+";break;case -1:c="-";break;case 0:c=" "}a[b+1]=c+encodeURI(this.diffs[b][1])+"\n"}return a.join("").replace(/%20/g," ")};
        this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()
        
    • json3
      • json3.min.js
        (function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&'""'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&'{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'==c({a:[e,!0,!1,null,"\x00\b\n\f\r\t"]})&&"1"===c(null,e)&&"[\n 1,\n 2\n]"==c([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==c(new C(-864E13))&&'"+275760-09-13T00:00:00.000Z"'==c(new C(864E13))&&'"-000001-01-01T00:00:00.000Z"'==c(new C(-621987552E5))&&'"1969-12-31T23:59:59.999Z"'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c('{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c('"\t"')}catch(d){}if(n)try{n=1!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&&10==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__=c;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||!(e[f]=1)||!v.call(a,f)||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"==b||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};if(!q("json-stringify")){var U={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c='"',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+'"'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g,"toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds();g=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null":m);a=q.length?f?"[\n"+n+q.join(",\n"+n)+"\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\n"+n+q.join(",\n"+n)+"\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"==(d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\",34:'"',47:"/",98:"\b",116:"\t",110:"\n",102:"\f",114:"\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e=D?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h=b;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b,b+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e===w?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&&window||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this);
    • knockout
      • knockout-3.2.0.js
        (function(){(function(p){var s=this||(0,eval)("this"),v=s.document,L=s.navigator,w=s.jQuery,D=s.JSON;(function(p){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?p(module.exports||exports,require):"function"===typeof define&&define.amd?define(["exports","require"],p):p(s.ko={})})(function(M,N){function H(a,d){return null===a||typeof a in R?a===d:!1}function S(a,d){var c;return function(){c||(c=setTimeout(function(){c=p;a()},d))}}function T(a,d){var c;return function(){clearTimeout(c);c=setTimeout(a,d)}}function I(b,d,c,e){a.d[b]={init:function(b,h,k,f,m){var l,q;a.s(function(){var f=a.a.c(h()),k=!c!==!f,z=!q;if(z||d||k!==l)z&&a.Y.la()&&(q=a.a.ia(a.f.childNodes(b),!0)),k?(z||a.f.T(b,a.a.ia(q)),a.Ca(e?e(m,f):m,b)):a.f.ja(b),l=k},null,{o:b});return{controlsDescendantBindings:!0}}};a.h.ha[b]=!1;a.f.Q[b]=!0}var a="undefined"!==typeof M?M:{};a.b=function(b,d){for(var c=b.split("."),e=a,g=0;g<c.length-1;g++)e=e[c[g]];e[c[c.length-1]]=d};a.A=function(a,d,c){a[d]=c};a.version="3.2.0";a.b("version",a.version);a.a=function(){function b(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])}function d(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function c(a,b){a.__proto__=b;return a}var e={__proto__:[]}instanceof Array,g={},h={};g[L&&/Firefox\/2/i.test(L.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];g.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(g,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)h[b[c]]=a});var k={propertychange:!0},f=v&&function(){for(var a=3,b=v.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:p}();return{vb:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],u:function(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c],c)},m:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},qb:function(a,b,c){for(var d=0,f=a.length;d<f;d++)if(b.call(c,a[d],d))return a[d];return null},ua:function(m,b){var c=a.a.m(m,b);0<c?m.splice(c,1):0===c&&m.shift()},rb:function(m){m=m||[];for(var b=[],c=0,d=m.length;c<d;c++)0>a.a.m(b,m[c])&&b.push(m[c]);return b},Da:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)c.push(b(a[d],d));return c},ta:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)b(a[d],d)&&c.push(a[d]);return c},ga:function(a,b){if(b instanceof
        Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},ea:function(b,c,d){var f=a.a.m(a.a.Xa(b),c);0>f?d&&b.push(c):d||b.splice(f,1)},xa:e,extend:d,za:c,Aa:e?c:d,G:b,na:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},Ka:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},oc:function(b){b=a.a.S(b);for(var c=v.createElement("div"),d=0,f=b.length;d<f;d++)c.appendChild(a.R(b[d]));return c},ia:function(b,c){for(var d=0,f=b.length,e=[];d<f;d++){var k=b[d].cloneNode(!0);e.push(c?a.R(k):k)}return e},T:function(b,c){a.a.Ka(b);if(c)for(var d=0,f=c.length;d<f;d++)b.appendChild(c[d])},Lb:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var f=d[0],e=f.parentNode,k=0,g=c.length;k<g;k++)e.insertBefore(c[k],f);k=0;for(g=d.length;k<g;k++)a.removeNode(d[k])}},ka:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.shift();if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=0;c!==d;)if(a.push(c),c=c.nextSibling,!c)return;a.push(d)}}return a},Nb:function(a,b){7>f?a.setAttribute("selected",b):a.selected=b},cb:function(a){return null===a||a===p?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},vc:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},cc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Ja:function(b){return a.a.cc(b,b.ownerDocument.documentElement)},ob:function(b){return!!a.a.qb(b,a.a.Ja)},t:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,c,d){var e=f&&k[c];if(!e&&w)w(b).bind(c,d);else if(e||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var g=function(a){d.call(b,a)},h="on"+c;b.attachEvent(h,g);a.a.w.da(b,function(){b.detachEvent(h,g)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,d,!1)},oa:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.t(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(w&&!d)w(b).trigger(c);else if("function"==typeof v.createEvent)if("function"==typeof b.dispatchEvent)d=v.createEvent(h[c]||"HTMLEvents"),d.initEvent(c,!0,!0,s,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");},c:function(b){return a.C(b)?b():b},Xa:function(b){return a.C(b)?b.v():b},Ba:function(b,c,d){if(c){var f=/\S+/g,e=b.className.match(f)||[];a.a.u(c.match(f),function(b){a.a.ea(e,b,d)});b.className=e.join(" ")}},bb:function(b,c){var d=a.a.c(c);if(null===d||d===p)d="";var f=a.f.firstChild(b);!f||3!=f.nodeType||a.f.nextSibling(f)?a.f.T(b,[b.ownerDocument.createTextNode(d)]):f.data=d;a.a.fc(b)},Mb:function(a,b){a.name=b;if(7>=f)try{a.mergeAttributes(v.createElement("<input name='"+a.name+"'/>"),!1)}catch(c){}},fc:function(a){9<=f&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},dc:function(a){if(f){var b=a.style.width;a.style.width=0;a.style.width=b}},sc:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],f=b;f<=c;f++)d.push(f);return d},S:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},yc:6===f,zc:7===f,L:f,xb:function(b,c){for(var d=a.a.S(b.getElementsByTagName("input")).concat(a.a.S(b.getElementsByTagName("textarea"))),f="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],k=d.length-1;0<=k;k--)f(d[k])&&e.push(d[k]);return e},pc:function(b){return"string"==typeof b&&(b=a.a.cb(b))?D&&D.parse?D.parse(b):(new Function("return "+b))():null},eb:function(b,c,d){if(!D||!D.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");return D.stringify(a.a.c(b),c,d)},qc:function(c,d,f){f=f||{};var e=f.params||{},k=f.includeFields||this.vb,g=c;if("object"==typeof c&&"form"===a.a.t(c))for(var g=c.action,h=k.length-1;0<=h;h--)for(var r=a.a.xb(c,k[h]),E=r.length-1;0<=E;E--)e[r[E].name]=r[E].value;d=a.a.c(d);var y=v.createElement("form");y.style.display="none";y.action=g;y.method="post";for(var p in d)c=v.createElement("input"),c.type="hidden",c.name=p,c.value=a.a.eb(a.a.c(d[p])),y.appendChild(c);b(e,function(a,b){var c=v.createElement("input");c.type="hidden";c.name=a;c.value=b;y.appendChild(c)});v.body.appendChild(y);f.submitter?f.submitter(y):y.submit();setTimeout(function(){y.parentNode.removeChild(y)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.u);a.b("utils.arrayFirst",a.a.qb);a.b("utils.arrayFilter",a.a.ta);a.b("utils.arrayGetDistinctValues",a.a.rb);a.b("utils.arrayIndexOf",a.a.m);a.b("utils.arrayMap",a.a.Da);a.b("utils.arrayPushAll",a.a.ga);a.b("utils.arrayRemoveItem",a.a.ua);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.vb);a.b("utils.getFormFields",a.a.xb);a.b("utils.peekObservable",a.a.Xa);a.b("utils.postJson",a.a.qc);a.b("utils.parseJson",a.a.pc);a.b("utils.registerEventHandler",a.a.n);a.b("utils.stringifyJson",a.a.eb);a.b("utils.range",a.a.sc);a.b("utils.toggleDomNodeCssClass",a.a.Ba);a.b("utils.triggerEvent",a.a.oa);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.G);a.b("utils.addOrRemoveItem",a.a.ea);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var d=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return d.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});a.a.e=new function(){function a(b,h){var k=b[c];if(!k||"null"===k||!e[k]){if(!h)return p;k=b[c]="ko"+d++;e[k]={}}return e[k]}var d=0,c="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===p?p:e[d]},set:function(c,d,e){if(e!==p||a(c,!1)!==p)a(c,!0)[d]=e},clear:function(a){var b=a[c];return b?(delete e[b],a[c]=null,!0):!1},F:function(){return d++ +c}}};a.b("utils.domData",a.a.e);a.b("utils.domData.clear",a.a.e.clear);a.a.w=new function(){function b(b,d){var f=a.a.e.get(b,c);f===p&&d&&(f=[],a.a.e.set(b,c,f));return f}function d(c){var e=b(c,!1);if(e)for(var e=e.slice(0),f=0;f<e.length;f++)e[f](c);a.a.e.clear(c);a.a.w.cleanExternalData(c);if(g[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}var c=a.a.e.F(),e={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{da:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},Kb:function(d,e){var f=b(d,!1);f&&(a.a.ua(f,e),0==f.length&&a.a.e.set(d,c,p))},R:function(b){if(e[b.nodeType]&&(d(b),g[b.nodeType])){var c=[];a.a.ga(c,b.getElementsByTagName("*"));for(var f=0,m=c.length;f<m;f++)d(c[f])}return b},removeNode:function(b){a.R(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){w&&"function"==typeof w.cleanData&&w.cleanData([a])}}};a.R=a.a.w.R;a.removeNode=a.a.w.removeNode;a.b("cleanNode",a.R);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.w);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.w.da);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.w.Kb);(function(){a.a.ba=function(b){var d;if(w)if(w.parseHTML)d=w.parseHTML(b)||[];else{if((d=w.clean([b]))&&d[0]){for(b=d[0];b.parentNode&&11!==b.parentNode.nodeType;)b=b.parentNode;b.parentNode&&b.parentNode.removeChild(b)}}else{var c=a.a.cb(b).toLowerCase();d=v.createElement("div");c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];b="ignored<div>"+c[1]+b+c[2]+"</div>";for("function"==typeof s.innerShiv?d.appendChild(s.innerShiv(b)):d.innerHTML=b;c[0]--;)d=d.lastChild;d=a.a.S(d.lastChild.childNodes)}return d};a.a.$a=function(b,d){a.a.Ka(b);d=a.a.c(d);if(null!==d&&d!==p)if("string"!=typeof d&&(d=d.toString()),w)w(b).html(d);else for(var c=a.a.ba(d),e=0;e<c.length;e++)b.appendChild(c[e])}})();a.b("utils.parseHtmlFragment",a.a.ba);a.b("utils.setHtml",a.a.$a);a.D=function(){function b(c,d){if(c)if(8==c.nodeType){var g=a.D.Gb(c.nodeValue);null!=g&&d.push({bc:c,mc:g})}else if(1==c.nodeType)for(var g=0,h=c.childNodes,k=h.length;g<k;g++)b(h[g],d)}var d={};return{Ua:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);d[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},Rb:function(a,b){var g=d[a];if(g===p)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return g.apply(null,b||[]),!0}finally{delete d[a]}},Sb:function(c,d){var g=[];b(c,g);for(var h=0,k=g.length;h<k;h++){var f=g[h].bc,m=[f];d&&a.a.ga(m,d);a.D.Rb(g[h].mc,m);f.nodeValue="";f.parentNode&&f.parentNode.removeChild(f)}},Gb:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.D);a.b("memoization.memoize",a.D.Ua);a.b("memoization.unmemoize",a.D.Rb);a.b("memoization.parseMemoText",a.D.Gb);a.b("memoization.unmemoizeDomNodeAndDescendants",a.D.Sb);a.La={throttle:function(b,d){b.throttleEvaluation=d;var c=null;return a.j({read:b,write:function(a){clearTimeout(c);c=setTimeout(function(){b(a)},d)}})},rateLimit:function(a,d){var c,e,g;"number"==typeof d?c=d:(c=d.timeout,e=d.method);g="notifyWhenChangesStop"==e?T:S;a.Ta(function(a){return g(a,c)})},notify:function(a,d){a.equalityComparer="always"==d?null:H}};var R={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.La);a.Pb=function(b,d,c){this.target=b;this.wa=d;this.ac=c;this.Cb=!1;a.A(this,"dispose",this.K)};a.Pb.prototype.K=function(){this.Cb=!0;this.ac()};a.P=function(){a.a.Aa(this,a.P.fn);this.M={}};var G="change",A={U:function(b,d,c){var e=this;c=c||G;var g=new a.Pb(e,d?b.bind(d):b,function(){a.a.ua(e.M[c],g);e.nb&&e.nb()});e.va&&e.va(c);e.M[c]||(e.M[c]=[]);e.M[c].push(g);return g},notifySubscribers:function(b,d){d=d||G;if(this.Ab(d))try{a.k.Ea();for(var c=this.M[d].slice(0),e=0,g;g=c[e];++e)g.Cb||g.wa(b)}finally{a.k.end()}},Ta:function(b){var d=this,c=a.C(d),e,g,h;d.qa||(d.qa=d.notifySubscribers,d.notifySubscribers=function(a,b){b&&b!==G?"beforeChange"===b?d.kb(a):d.qa(a,b):d.lb(a)});var k=b(function(){c&&h===d&&(h=d());e=!1;d.Pa(g,h)&&d.qa(g=h)});d.lb=function(a){e=!0;h=a;k()};d.kb=function(a){e||(g=a,d.qa(a,"beforeChange"))}},Ab:function(a){return this.M[a]&&this.M[a].length},yb:function(){var b=0;a.a.G(this.M,function(a,c){b+=c.length});return b},Pa:function(a,d){return!this.equalityComparer||!this.equalityComparer(a,d)},extend:function(b){var d=this;b&&a.a.G(b,function(b,e){var g=a.La[b];"function"==typeof g&&(d=g(d,e)||d)});return d}};a.A(A,"subscribe",A.U);a.A(A,"extend",A.extend);a.A(A,"getSubscriptionsCount",A.yb);a.a.xa&&a.a.za(A,Function.prototype);a.P.fn=A;a.Db=function(a){return null!=a&&"function"==typeof a.U&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.P);a.b("isSubscribable",a.Db);a.Y=a.k=function(){function b(a){c.push(e);e=a}function d(){e=c.pop()}var c=[],e,g=0;return{Ea:b,end:d,Jb:function(b){if(e){if(!a.Db(b))throw Error("Only subscribable things can act as dependencies");e.wa(b,b.Vb||(b.Vb=++g))}},B:function(a,c,f){try{return b(),a.apply(c,f||[])}finally{d()}},la:function(){if(e)return e.s.la()},ma:function(){if(e)return e.ma}}}();a.b("computedContext",a.Y);a.b("computedContext.getDependenciesCount",a.Y.la);a.b("computedContext.isInitial",a.Y.ma);a.b("computedContext.isSleeping",a.Y.Ac);a.p=function(b){function d(){if(0<arguments.length)return d.Pa(c,arguments[0])&&(d.X(),c=arguments[0],d.W()),this;a.k.Jb(d);return c}var c=b;a.P.call(d);a.a.Aa(d,a.p.fn);d.v=function(){return c};d.W=function(){d.notifySubscribers(c)};d.X=function(){d.notifySubscribers(c,"beforeChange")};a.A(d,"peek",d.v);a.A(d,"valueHasMutated",d.W);a.A(d,"valueWillMutate",d.X);return d};a.p.fn={equalityComparer:H};var F=a.p.rc="__ko_proto__";a.p.fn[F]=a.p;a.a.xa&&a.a.za(a.p.fn,a.P.fn);a.Ma=function(b,d){return null===b||b===p||b[F]===p?!1:b[F]===d?!0:a.Ma(b[F],d)};a.C=function(b){return a.Ma(b,a.p)};a.Ra=function(b){return"function"==typeof b&&b[F]===a.p||"function"==typeof b&&b[F]===a.j&&b.hc?!0:!1};a.b("observable",a.p);a.b("isObservable",a.C);a.b("isWriteableObservable",a.Ra);a.b("isWritableObservable",a.Ra);a.aa=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.p(b);a.a.Aa(b,a.aa.fn);return b.extend({trackArrayChanges:!0})};a.aa.fn={remove:function(b){for(var d=this.v(),c=[],e="function"!=typeof b||a.C(b)?function(a){return a===b}:b,g=0;g<d.length;g++){var h=d[g];e(h)&&(0===c.length&&this.X(),c.push(h),d.splice(g,1),g--)}c.length&&this.W();return c},removeAll:function(b){if(b===p){var d=this.v(),c=d.slice(0);this.X();d.splice(0,d.length);this.W();return c}return b?this.remove(function(c){return 0<=a.a.m(b,c)}):[]},destroy:function(b){var d=this.v(),c="function"!=typeof b||a.C(b)?function(a){return a===b}:b;this.X();for(var e=d.length-1;0<=e;e--)c(d[e])&&(d[e]._destroy=!0);this.W()},destroyAll:function(b){return b===p?this.destroy(function(){return!0}):b?this.destroy(function(d){return 0<=a.a.m(b,d)}):[]},indexOf:function(b){var d=this();return a.a.m(d,b)},replace:function(a,d){var c=this.indexOf(a);0<=c&&(this.X(),this.v()[c]=d,this.W())}};a.a.u("pop push reverse shift sort splice unshift".split(" "),function(b){a.aa.fn[b]=function(){var a=this.v();this.X();this.sb(a,b,arguments);a=a[b].apply(a,arguments);this.W();return a}});a.a.u(["slice"],function(b){a.aa.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.a.xa&&a.a.za(a.aa.fn,a.p.fn);a.b("observableArray",a.aa);var J="arrayChange";a.La.trackArrayChanges=function(b){function d(){if(!c){c=!0;var d=b.notifySubscribers;b.notifySubscribers=function(a,b){b&&b!==G||++g;return d.apply(this,arguments)};var f=[].concat(b.v()||[]);e=null;b.U(function(c){c=[].concat(c||[]);if(b.Ab(J)){var d;if(!e||1<g)e=a.a.Fa(f,c,{sparse:!0});d=e;d.length&&b.notifySubscribers(d,J)}f=c;e=null;g=0})}}if(!b.sb){var c=!1,e=null,g=0,h=b.U;b.U=b.subscribe=function(a,b,c){c===J&&d();return h.apply(this,arguments)};b.sb=function(b,d,m){function l(a,b,c){return q[q.length]={status:a,value:b,index:c}}if(c&&!g){var q=[],h=b.length,t=m.length,z=0;switch(d){case"push":z=h;case"unshift":for(d=0;d<t;d++)l("added",m[d],z+d);break;case"pop":z=h-1;case"shift":h&&l("deleted",b[z],z);break;case"splice":d=Math.min(Math.max(0,0>m[0]?h+m[0]:m[0]),h);for(var h=1===t?h:Math.min(d+(m[1]||0),h),t=d+t-2,z=Math.max(h,t),u=[],r=[],E=2;d<z;++d,++E)d<h&&r.push(l("deleted",b[d],d)),d<t&&u.push(l("added",m[E],d));a.a.wb(r,u);break;default:return}e=q}}}};a.s=a.j=function(b,d,c){function e(){a.a.G(v,function(a,b){b.K()});v={}}function g(){e();C=0;u=!0;n=!1}function h(){var a=f.throttleEvaluation;a&&0<=a?(clearTimeout(P),P=setTimeout(k,a)):f.ib?f.ib():k()}function k(b){if(t){if(E)throw Error("A 'pure' computed must not be called recursively");}else if(!u){if(w&&w()){if(!z){s();return}}else z=!1;t=!0;if(y)try{var c={};a.k.Ea({wa:function(a,b){c[b]||(c[b]=1,++C)},s:f,ma:p});C=0;q=r.call(d)}finally{a.k.end(),t=!1}else try{var e=v,m=C;a.k.Ea({wa:function(a,b){u||(m&&e[b]?(v[b]=e[b],++C,delete e[b],--m):v[b]||(v[b]=a.U(h),++C))},s:f,ma:E?p:!C});v={};C=0;try{var l=d?r.call(d):r()}finally{a.k.end(),m&&a.a.G(e,function(a,b){b.K()}),n=!1}f.Pa(q,l)&&(f.notifySubscribers(q,"beforeChange"),q=l,!0!==b&&f.notifySubscribers(q))}finally{t=!1}C||s()}}function f(){if(0<arguments.length){if("function"===typeof O)O.apply(d,arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return this}a.k.Jb(f);n&&k(!0);return q}function m(){n&&!C&&k(!0);return q}function l(){return n||0<C}var q,n=!0,t=!1,z=!1,u=!1,r=b,E=!1,y=!1;r&&"object"==typeof r?(c=r,r=c.read):(c=c||{},r||(r=c.read));if("function"!=typeof r)throw Error("Pass a function that returns the value of the ko.computed");var O=c.write,x=c.disposeWhenNodeIsRemoved||c.o||null,B=c.disposeWhen||c.Ia,w=B,s=g,v={},C=0,P=null;d||(d=c.owner);a.P.call(f);a.a.Aa(f,a.j.fn);f.v=m;f.la=function(){return C};f.hc="function"===typeof c.write;f.K=function(){s()};f.Z=l;var A=f.Ta;f.Ta=function(a){A.call(f,a);f.ib=function(){f.kb(q);n=!0;f.lb(f)}};c.pure?(y=E=!0,f.va=function(){y&&(y=!1,k(!0))},f.nb=function(){f.yb()||(e(),y=n=!0)}):c.deferEvaluation&&(f.va=function(){m();delete f.va});a.A(f,"peek",f.v);a.A(f,"dispose",f.K);a.A(f,"isActive",f.Z);a.A(f,"getDependenciesCount",f.la);x&&(z=!0,x.nodeType&&(w=function(){return!a.a.Ja(x)||B&&B()}));y||c.deferEvaluation||k();x&&l()&&x.nodeType&&(s=function(){a.a.w.Kb(x,s);g()},a.a.w.da(x,s));return f};a.jc=function(b){return a.Ma(b,a.j)};A=a.p.rc;a.j[A]=a.p;a.j.fn={equalityComparer:H};a.j.fn[A]=a.j;a.a.xa&&a.a.za(a.j.fn,a.P.fn);a.b("dependentObservable",a.j);a.b("computed",a.j);a.b("isComputed",a.jc);a.Ib=function(b,d){if("function"===typeof b)return a.s(b,d,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.s(b,d)};a.b("pureComputed",a.Ib);(function(){function b(a,g,h){h=h||new c;a=g(a);if("object"!=typeof a||null===a||a===p||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var k=a instanceof Array?[]:{};h.save(a,k);d(a,function(c){var d=g(a[c]);switch(typeof d){case"boolean":case"number":case"string":case"function":k[c]=d;break;case"object":case"undefined":var l=h.get(d);k[c]=l!==p?l:b(d,g,h)}});return k}function d(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function c(){this.keys=[];this.hb=[]}a.Qb=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.C(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.Qb(b);return a.a.eb(b,c,d)};c.prototype={save:function(b,c){var d=a.a.m(this.keys,b);0<=d?this.hb[d]=c:(this.keys.push(b),this.hb.push(c))},get:function(b){b=a.a.m(this.keys,b);return 0<=b?this.hb[b]:p}}})();a.b("toJS",a.Qb);a.b("toJSON",a.toJSON);(function(){a.i={q:function(b){switch(a.a.t(b)){case"option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.Va):7>=a.a.L?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case"select":return 0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex]):p;default:return b.value}},ca:function(b,d,c){switch(a.a.t(b)){case"option":switch(typeof d){case"string":a.a.e.set(b,a.d.options.Va,p);"__ko__hasDomDataOptionValue__"in
        b&&delete b.__ko__hasDomDataOptionValue__;b.value=d;break;default:a.a.e.set(b,a.d.options.Va,d),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof d?d:""}break;case"select":if(""===d||null===d)d=p;for(var e=-1,g=0,h=b.options.length,k;g<h;++g)if(k=a.i.q(b.options[g]),k==d||""==k&&d===p){e=g;break}if(c||0<=e||d===p&&1<b.size)b.selectedIndex=e;break;default:if(null===d||d===p)d="";b.value=d}}}})();a.b("selectExtensions",a.i);a.b("selectExtensions.readValue",a.i.q);a.b("selectExtensions.writeValue",a.i.ca);a.h=function(){function b(b){b=a.a.cb(b);123===b.charCodeAt(0)&&(b=b.slice(1,-1));var c=[],d=b.match(e),k,n,t=0;if(d){d.push(",");for(var z=0,u;u=d[z];++z){var r=u.charCodeAt(0);if(44===r){if(0>=t){k&&c.push(n?{key:k,value:n.join("")}:{unknown:k});k=n=t=0;continue}}else if(58===r){if(!n)continue}else if(47===r&&z&&1<u.length)(r=d[z-1].match(g))&&!h[r[0]]&&(b=b.substr(b.indexOf(u)+1),d=b.match(e),d.push(","),z=-1,u="/");else if(40===r||123===r||91===r)++t;else if(41===r||125===r||93===r)--t;else if(!k&&!n){k=34===r||39===r?u.slice(1,-1):u;continue}n?n.push(u):n=[u]}}return c}var d=["true","false","null","undefined"],c=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]","g"),g=/[\])"'A-Za-z0-9_$]+$/,h={"in":1,"return":1,"typeof":1},k={};return{ha:[],V:k,Wa:b,ya:function(f,m){function e(b,m){var f;if(!z){var u=a.getBindingHandler(b);if(u&&u.preprocess&&!(m=u.preprocess(m,b,e)))return;if(u=k[b])f=m,0<=a.a.m(d,f)?f=!1:(u=f.match(c),f=null===u?!1:u[1]?"Object("+u[1]+")"+u[2]:f),u=f;u&&h.push("'"+b+"':function(_z){"+f+"=_z}")}t&&(m="function(){return "+m+" }");g.push("'"+b+"':"+m)}m=m||{};var g=[],h=[],t=m.valueAccessors,z=m.bindingParams,u="string"===typeof f?b(f):f;a.a.u(u,function(a){e(a.key||a.unknown,a.value)});h.length&&e("_ko_property_writers","{"+h.join(",")+" }");return g.join(",")},lc:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},pa:function(b,c,d,e,k){if(b&&a.C(b))!a.Ra(b)||k&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.h);a.b("expressionRewriting.bindingRewriteValidators",a.h.ha);a.b("expressionRewriting.parseObjectLiteral",a.h.Wa);a.b("expressionRewriting.preProcessBindings",a.h.ya);a.b("expressionRewriting._twoWayBindings",a.h.V);a.b("jsonExpressionRewriting",a.h);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.h.ya);(function(){function b(a){return 8==a.nodeType&&h.test(g?a.text:a.nodeValue)}function d(a){return 8==a.nodeType&&k.test(g?a.text:a.nodeValue)}function c(a,c){for(var f=a,e=1,k=[];f=f.nextSibling;){if(d(f)&&(e--,0===e))return k;k.push(f);b(f)&&e++}if(!c)throw Error("Cannot find closing comment tag to match: "+a.nodeValue);return null}function e(a,b){var d=c(a,b);return d?0<d.length?d[d.length-1].nextSibling:a.nextSibling:null}var g=v&&"\x3c!--test--\x3e"===v.createComment("test").text,h=g?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,k=g?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,f={ul:!0,ol:!0};a.f={Q:{},childNodes:function(a){return b(a)?c(a):a.childNodes},ja:function(c){if(b(c)){c=a.f.childNodes(c);for(var d=0,f=c.length;d<f;d++)a.removeNode(c[d])}else a.a.Ka(c)},T:function(c,d){if(b(c)){a.f.ja(c);for(var f=c.nextSibling,e=0,k=d.length;e<k;e++)f.parentNode.insertBefore(d[e],f)}else a.a.T(c,d)},Hb:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},Bb:function(c,d,f){f?b(c)?c.parentNode.insertBefore(d,f.nextSibling):f.nextSibling?c.insertBefore(d,f.nextSibling):c.appendChild(d):a.f.Hb(c,d)},firstChild:function(a){return b(a)?!a.nextSibling||d(a.nextSibling)?null:a.nextSibling:a.firstChild},nextSibling:function(a){b(a)&&(a=e(a));return a.nextSibling&&d(a.nextSibling)?null:a.nextSibling},gc:b,xc:function(a){return(a=(g?a.text:a.nodeValue).match(h))?a[1]:null},Fb:function(c){if(f[a.a.t(c)]){var k=c.firstChild;if(k){do if(1===k.nodeType){var g;g=k.firstChild;var h=null;if(g){do if(h)h.push(g);else if(b(g)){var t=e(g,!0);t?g=t:h=[g]}else d(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h)for(h=k.nextSibling,t=0;t<g.length;t++)h?c.insertBefore(g[t],h):c.appendChild(g[t])}while(k=k.nextSibling)}}}}})();a.b("virtualElements",a.f);a.b("virtualElements.allowedBindings",a.f.Q);a.b("virtualElements.emptyNode",a.f.ja);a.b("virtualElements.insertAfter",a.f.Bb);a.b("virtualElements.prepend",a.f.Hb);a.b("virtualElements.setDomNodeChildren",a.f.T);(function(){a.J=function(){this.Yb={}};a.a.extend(a.J.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=b.getAttribute("data-bind")||a.g.getComponentNameForNode(b);case 8:return a.f.gc(b);default:return!1}},getBindings:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b):null;return a.g.mb(c,b,d,!1)},getBindingAccessors:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b,{valueAccessors:!0}):null;return a.g.mb(c,b,d,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.f.xc(b);default:return null}},parseBindingsString:function(b,d,c,e){try{var g=this.Yb,h=b+(e&&e.valueAccessors||""),k;if(!(k=g[h])){var f,m="with($context){with($data||{}){return{"+a.h.ya(b,e)+"}}}";f=new Function("$context","$element",m);k=g[h]=f}return k(d,c)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.J.instance=new a.J})();a.b("bindingProvider",a.J);(function(){function b(a){return function(){return a}}function d(a){return a()}
        function c(b){return a.a.na(a.k.B(b),function(a,c){return function(){return b()[c]}})}function e(a,b){return c(this.getBindings.bind(this,a,b))}function g(b,c,d){var f,e=a.f.firstChild(c),k=a.J.instance,g=k.preprocessNode;if(g){for(;f=e;)e=a.f.nextSibling(f),g.call(k,f);e=a.f.firstChild(c)}for(;f=e;)e=a.f.nextSibling(f),h(b,f,d)}function h(b,c,d){var e=!0,k=1===c.nodeType;k&&a.f.Fb(c);if(k&&d||a.J.instance.nodeHasBindings(c))e=f(c,null,b,d).shouldBindDescendants;e&&!l[a.a.t(c)]&&g(b,c,!k)}function k(b){var c=[],d={},f=[];a.a.G(b,function y(e){if(!d[e]){var k=a.getBindingHandler(e);k&&(k.after&&(f.push(e),a.a.u(k.after,function(c){if(b[c]){if(-1!==a.a.m(f,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+f.join(", "));y(c)}}),f.length--),c.push({key:e,zb:k}));d[e]=!0}});return c}function f(b,c,f,g){var m=a.a.e.get(b,q);if(!c){if(m)throw Error("You cannot apply bindings multiple times to the same element.");a.a.e.set(b,q,!0)}!m&&g&&a.Ob(b,f);var l;if(c&&"function"!==typeof c)l=c;else{var h=a.J.instance,n=h.getBindingAccessors||e,s=a.j(function(){(l=c?c(f,b):n.call(h,b,f))&&f.I&&f.I();return l},null,{o:b});l&&s.Z()||(s=null)}var v;if(l){var w=s?function(a){return function(){return d(s()[a])}}:function(a){return l[a]},A=function(){return a.a.na(s?s():l,d)};A.get=function(a){return l[a]&&d(w(a))};A.has=function(a){return a in l};g=k(l);a.a.u(g,function(c){var d=c.zb.init,e=c.zb.update,k=c.key;if(8===b.nodeType&&!a.f.Q[k])throw Error("The binding '"+k+"' cannot be used with virtual elements");try{"function"==typeof d&&a.k.B(function(){var a=d(b,w(k),A,f.$data,f);if(a&&a.controlsDescendantBindings){if(v!==p)throw Error("Multiple bindings ("+v+" and "+k+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");v=k}}),"function"==typeof e&&a.j(function(){e(b,w(k),A,f.$data,f)},null,{o:b})}catch(g){throw g.message='Unable to process binding "'+k+": "+l[k]+'"\nMessage: '+g.message,g;}})}return{shouldBindDescendants:v===p}}
        function m(b){return b&&b instanceof a.N?b:new a.N(b)}a.d={};var l={script:!0};a.getBindingHandler=function(b){return a.d[b]};a.N=function(b,c,d,f){var e=this,k="function"==typeof b&&!a.C(b),g,m=a.j(function(){var g=k?b():b,l=a.a.c(g);c?(c.I&&c.I(),a.a.extend(e,c),m&&(e.I=m)):(e.$parents=[],e.$root=l,e.ko=a);e.$rawData=g;e.$data=l;d&&(e[d]=l);f&&f(e,c,l);return e.$data},null,{Ia:function(){return g&&!a.a.ob(g)},o:!0});m.Z()&&(e.I=m,m.equalityComparer=null,g=[],m.Tb=function(b){g.push(b);a.a.w.da(b,function(b){a.a.ua(g,b);g.length||(m.K(),e.I=m=p)})})};a.N.prototype.createChildContext=function(b,c,d){return new a.N(b,this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)})};a.N.prototype.extend=function(b){return new a.N(this.I||this.$data,this,null,function(c,d){c.$rawData=d.$rawData;a.a.extend(c,"function"==typeof b?b():b)})};var q=a.a.e.F(),n=a.a.e.F();a.Ob=function(b,c){if(2==arguments.length)a.a.e.set(b,n,c),c.I&&c.I.Tb(b);else return a.a.e.get(b,n)};a.ra=function(b,c,d){1===b.nodeType&&a.f.Fb(b);return f(b,c,m(d),!0)};a.Wb=function(d,f,e){e=m(e);return a.ra(d,"function"===typeof f?c(f.bind(null,e,d)):a.a.na(f,b),e)};a.Ca=function(a,b){1!==b.nodeType&&8!==b.nodeType||g(m(a),b,!0)};a.pb=function(a,b){!w&&s.jQuery&&(w=s.jQuery);if(b&&1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");b=b||s.document.body;h(m(a),b,!0)};a.Ha=function(b){switch(b.nodeType){case 1:case 8:var c=a.Ob(b);if(c)return c;if(b.parentNode)return a.Ha(b.parentNode)}return p};a.$b=function(b){return(b=a.Ha(b))?b.$data:p};a.b("bindingHandlers",a.d);a.b("applyBindings",a.pb);a.b("applyBindingsToDescendants",a.Ca);a.b("applyBindingAccessorsToNode",a.ra);a.b("applyBindingsToNode",a.Wb);a.b("contextFor",a.Ha);a.b("dataFor",a.$b)})();(function(b){function d(d,f){var e=g.hasOwnProperty(d)?g[d]:b,l;e||(e=g[d]=new a.P,c(d,function(a){h[d]=a;delete g[d];l?e.notifySubscribers(a):setTimeout(function(){e.notifySubscribers(a)},0)}),l=!0);e.U(f)}function c(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a)}):b(null)})}function e(c,d,g,l){l||(l=a.g.loaders.slice(0));var h=l.shift();if(h){var n=h[c];if(n){var t=!1;if(n.apply(h,d.concat(function(a){t?g(null):null!==a?g(a):e(c,d,g,l)}))!==b&&(t=!0,!h.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,g,l)}else g(null)}var g={},h={};a.g={get:function(a,c){var e=h.hasOwnProperty(a)?h[a]:b;e?setTimeout(function(){c(e)},0):d(a,c)},tb:function(a){delete h[a]},jb:e};a.g.loaders=[];a.b("components",a.g);a.b("components.get",a.g.get);a.b("components.clearCachedDefinition",a.g.tb)})();(function(){function b(b,c,d,e){function k(){0===--u&&e(h)}var h={},u=2,r=d.template;d=d.viewModel;r?g(c,r,function(c){a.g.jb("loadTemplate",[b,c],function(a){h.template=a;k()})}):k();d?g(c,d,function(c){a.g.jb("loadViewModel",[b,c],function(a){h[f]=a;k()})}):k()}function d(a,b,c){if("function"===typeof b)c(function(a){return new b(a)});else if("function"===typeof b[f])c(b[f]);else if("instance"in b){var e=b.instance;c(function(){return e})}else"viewModel"in b?d(a,b.viewModel,c):a("Unknown viewModel value: "+b)}function c(b){switch(a.a.t(b)){case"script":return a.a.ba(b.text);case"textarea":return a.a.ba(b.value);case"template":if(e(b.content))return a.a.ia(b.content.childNodes)}return a.a.ia(b.childNodes)}function e(a){return s.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function g(a,b,c){"string"===typeof b.require?N||s.require?(N||s.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function h(a){return function(b){throw Error("Component '"+a+"': "+b);}}var k={};a.g.tc=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.g.Qa(b))throw Error("Component "+b+" is already registered");k[b]=c};a.g.Qa=function(a){return a in k};a.g.wc=function(b){delete k[b];a.g.tb(b)};a.g.ub={getConfig:function(a,b){b(k.hasOwnProperty(a)?k[a]:null)},loadComponent:function(a,c,d){var e=h(a);g(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,d,f){b=h(b);if("string"===typeof d)f(a.a.ba(d));else if(d instanceof Array)f(d);else if(e(d))f(a.a.S(d.childNodes));else if(d.element)if(d=d.element,s.HTMLElement?d instanceof HTMLElement:d&&d.tagName&&1===d.nodeType)f(c(d));else if("string"===typeof d){var k=v.getElementById(d);k?f(c(k)):b("Cannot find element with ID "+d)}else b("Unknown element type: "+d);else b("Unknown template value: "+d)},loadViewModel:function(a,b,c){d(h(a),b,c)}};var f="createViewModel";a.b("components.register",a.g.tc);a.b("components.isRegistered",a.g.Qa);a.b("components.unregister",a.g.wc);a.b("components.defaultLoader",a.g.ub);a.g.loaders.push(a.g.ub);a.g.Ub=k})();(function(){function b(b,e){var g=b.getAttribute("params");if(g){var g=d.parseBindingsString(g,e,b,{valueAccessors:!0,bindingParams:!0}),g=a.a.na(g,function(d){return a.s(d,null,{o:b})}),h=a.a.na(g,function(d){return d.Z()?a.s(function(){return a.a.c(d())},null,{o:b}):d.v()});h.hasOwnProperty("$raw")||(h.$raw=g);return h}return{$raw:{}}}a.g.getComponentNameForNode=function(b){b=a.a.t(b);return a.g.Qa(b)&&b};a.g.mb=function(c,d,g,h){if(1===d.nodeType){var k=a.g.getComponentNameForNode(d);if(k){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var f={name:k,params:b(d,g)};c.component=h?function(){return f}:f}}return c};var d=new a.J;9>a.a.L&&(a.g.register=function(a){return function(b){v.createElement(b);return a.apply(this,arguments)}}(a.g.register),v.createDocumentFragment=function(b){return function(){var d=b(),g=a.g.Ub,h;for(h in g)g.hasOwnProperty(h)&&d.createElement(h);return d}}(v.createDocumentFragment))})();(function(){var b=0;a.d.component={init:function(d,c,e,g,h){function k(){var a=f&&f.dispose;"function"===typeof a&&a.call(f);m=null}var f,m;a.a.w.da(d,k);a.s(function(){var e=a.a.c(c()),g,n;"string"===typeof e?g=e:(g=a.a.c(e.name),n=a.a.c(e.params));if(!g)throw Error("No component name specified");var t=m=++b;a.g.get(g,function(b){if(m===t){k();if(!b)throw Error("Unknown component '"+g+"'");var c=b.template;if(!c)throw Error("Component '"+g+"' has no template");c=a.a.ia(c);a.f.T(d,c);var c=n,e=b.createViewModel;b=e?e.call(b,c,{element:d}):c;c=h.createChildContext(b);f=b;a.Ca(c,d)}})},null,{o:d});return{controlsDescendantBindings:!0}}};a.f.Q.component=!0})();var Q={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,d){var c=a.a.c(d())||{};a.a.G(c,function(c,d){d=a.a.c(d);var h=!1===d||null===d||d===p;h&&b.removeAttribute(c);8>=a.a.L&&c in Q?(c=Q[c],h?b.removeAttribute(c):b[c]=d):h||b.setAttribute(c,d.toString());"name"===c&&a.a.Mb(b,h?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,d,c){function e(){var e=b.checked,k=q?h():e;if(!a.Y.ma()&&(!f||e)){var g=a.k.B(d);m?l!==k?(e&&(a.a.ea(g,k,!0),a.a.ea(g,l,!1)),l=k):a.a.ea(g,k,e):a.h.pa(g,c,"checked",k,!0)}}function g(){var c=a.a.c(d());b.checked=m?0<=a.a.m(c,h()):k?c:h()===c}var h=a.Ib(function(){return c.has("checkedValue")?a.a.c(c.get("checkedValue")):c.has("value")?a.a.c(c.get("value")):b.value}),k="checkbox"==b.type,f="radio"==b.type;if(k||f){var m=k&&a.a.c(d())instanceof Array,l=m?h():p,q=f||m;f&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.s(e,null,{o:b});a.a.n(b,"click",e);a.s(g,null,{o:b})}}};a.h.V.checked=!0;a.d.checkedValue={update:function(b,d){b.value=a.a.c(d())}}})();a.d.css={update:function(b,d){var c=a.a.c(d());"object"==typeof c?a.a.G(c,function(c,d){d=a.a.c(d);a.a.Ba(b,c,d)}):(c=String(c||""),a.a.Ba(b,b.__ko__cssValue,!1),b.__ko__cssValue=c,a.a.Ba(b,c,!0))}};a.d.enable={update:function(b,d){var c=a.a.c(d());c&&b.disabled?b.removeAttribute("disabled"):c||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,d){a.d.enable.update(b,function(){return!a.a.c(d())})}};a.d.event={init:function(b,d,c,e,g){var h=d()||{};a.a.G(h,function(k){"string"==typeof k&&a.a.n(b,k,function(b){var h,l=d()[k];if(l){try{var q=a.a.S(arguments);e=g.$data;q.unshift(e);h=l.apply(e,q)}finally{!0!==h&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===c.get(k+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={Eb:function(b){return function(){var d=b(),c=a.a.Xa(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:a.O.Oa};a.a.c(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:a.O.Oa}}},init:function(b,d){return a.d.template.init(b,a.d.foreach.Eb(d))},update:function(b,d,c,e,g){return a.d.template.update(b,a.d.foreach.Eb(d),c,e,g)}};a.h.ha.foreach=!1;a.f.Q.foreach=!0;a.d.hasfocus={init:function(b,d,c){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(h){g=f.body}e=g===b}f=d();a.h.pa(f,c,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var g=e.bind(null,!0),h=e.bind(null,!1);a.a.n(b,"focus",g);a.a.n(b,"focusin",g);a.a.n(b,"blur",h);a.a.n(b,"focusout",h)},update:function(b,d){var c=!!a.a.c(d());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===c||(c?b.focus():b.blur(),a.k.B(a.a.oa,null,[b,c?"focusin":"focusout"]))}};a.h.V.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.V.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.$a(b,d())}};I("if");I("ifnot",!1,!0);I("with",!0,!1,function(a,d){return a.createChildContext(d)});var K={};a.d.options={init:function(b){if("select"!==a.a.t(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,d,c){function e(){return a.a.ta(b.options,function(a){return a.selected})}function g(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function h(c,d){if(q.length){var e=0<=a.a.m(q,a.i.q(d[0]));a.a.Nb(d[0],e);n&&!e&&a.k.B(a.a.oa,null,[b,"change"])}}var k=0!=b.length&&b.multiple?b.scrollTop:null,f=a.a.c(d()),m=c.get("optionsIncludeDestroyed");d={};var l,q;q=b.multiple?a.a.Da(e(),a.i.q):0<=b.selectedIndex?[a.i.q(b.options[b.selectedIndex])]:[];f&&("undefined"==typeof f.length&&(f=[f]),l=a.a.ta(f,function(b){return m||b===p||null===b||!a.a.c(b._destroy)}),c.has("optionsCaption")&&(f=a.a.c(c.get("optionsCaption")),null!==f&&f!==p&&l.unshift(K)));var n=!1;d.beforeRemove=function(a){b.removeChild(a)};f=h;c.has("optionsAfterRender")&&(f=function(b,d){h(0,d);a.k.B(c.get("optionsAfterRender"),null,[d[0],b!==K?b:p])});a.a.Za(b,l,function(d,e,f){f.length&&(q=f[0].selected?[a.i.q(f[0])]:[],n=!0);e=b.ownerDocument.createElement("option");d===K?(a.a.bb(e,c.get("optionsCaption")),a.i.ca(e,p)):(f=g(d,c.get("optionsValue"),d),a.i.ca(e,a.a.c(f)),d=g(d,c.get("optionsText"),f),a.a.bb(e,d));return[e]},d,f);a.k.B(function(){c.get("valueAllowUnset")&&c.has("value")?a.i.ca(b,a.a.c(c.get("value")),!0):(b.multiple?q.length&&e().length<q.length:q.length&&0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex])!==q[0]:q.length||0<=b.selectedIndex)&&a.a.oa(b,"change")});a.a.dc(b);k&&20<Math.abs(k-b.scrollTop)&&(b.scrollTop=k)}};a.d.options.Va=a.a.e.F();a.d.selectedOptions={after:["options","foreach"],init:function(b,d,c){a.a.n(b,"change",function(){var e=d(),g=[];a.a.u(b.getElementsByTagName("option"),function(b){b.selected&&g.push(a.i.q(b))});a.h.pa(e,c,"selectedOptions",g)})},update:function(b,d){if("select"!=a.a.t(b))throw Error("values binding applies only to SELECT elements");var c=a.a.c(d());c&&"number"==typeof c.length&&a.a.u(b.getElementsByTagName("option"),function(b){var d=0<=a.a.m(c,a.i.q(b));a.a.Nb(b,d)})}};a.h.V.selectedOptions=!0;a.d.style={update:function(b,d){var c=a.a.c(d()||{});a.a.G(c,function(c,d){d=a.a.c(d);if(null===d||d===p||!1===d)d="";b.style[c]=d})}};a.d.submit={init:function(b,d,c,e,g){if("function"!=typeof d())throw Error("The value for a submit binding must be a function");a.a.n(b,"submit",function(a){var c,e=d();try{c=e.call(g.$data,b)}finally{!0!==c&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.d.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.bb(b,d())}};a.f.Q.text=!0;(function(){if(s&&s.navigator)var b=function(a){if(a)return parseFloat(a[1])},d=s.opera&&s.opera.version&&parseInt(s.opera.version()),c=s.navigator.userAgent,e=b(c.match(/^(?:(?!chrome).)*version\/([^ ]*) safari/i)),g=b(c.match(/Firefox\/([^ ]*)/));if(10>a.a.L)var h=a.a.e.F(),k=a.a.e.F(),f=function(b){var c=this.activeElement;(c=c&&a.a.e.get(c,k))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,h)||(a.a.e.set(d,h,!0),a.a.n(d,"selectionchange",f));a.a.e.set(b,k,c)};a.d.textInput={init:function(b,c,f){function k(c,d){a.a.n(b,c,d)}function h(){var d=a.a.c(c());if(null===d||d===p)d="";v!==p&&d===v?setTimeout(h,4):b.value!==d&&(s=d,b.value=d)}function u(){y||(v=b.value,y=setTimeout(r,4))}function r(){clearTimeout(y);v=y=p;var d=b.value;s!==d&&(s=d,a.h.pa(c(),f,"textInput",d))}var s=b.value,y,v;10>a.a.L?(k("propertychange",function(a){"value"===a.propertyName&&r()}),8==a.a.L&&(k("keyup",r),k("keydown",r)),8<=a.a.L&&(m(b,r),k("dragend",u))):(k("input",r),5>e&&"textarea"===a.a.t(b)?(k("keydown",u),k("paste",u),k("cut",u)):11>d?k("keydown",u):4>g&&(k("DOMAutoComplete",r),k("dragdrop",r),k("drop",r)));k("change",r);a.s(h,null,{o:b})}};a.h.V.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.d.uniqueName={init:function(b,d){if(d()){var c="ko_unique_"+ ++a.d.uniqueName.Zb;a.a.Mb(b,c)}}};a.d.uniqueName.Zb=0;a.d.value={after:["options","foreach"],init:function(b,d,c){if("input"!=b.tagName.toLowerCase()||"checkbox"!=b.type&&"radio"!=b.type){var e=["change"],g=c.get("valueUpdate"),h=!1,k=null;g&&("string"==typeof g&&(g=[g]),a.a.ga(e,g),e=a.a.rb(e));var f=function(){k=null;h=!1;var e=d(),f=a.i.q(b);a.h.pa(e,c,"value",f)};!a.a.L||"input"!=b.tagName.toLowerCase()||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.m(e,"propertychange")||(a.a.n(b,"propertychange",function(){h=!0}),a.a.n(b,"focus",function(){h=!1}),a.a.n(b,"blur",function(){h&&f()}));a.a.u(e,function(c){var d=f;a.a.vc(c,"after")&&(d=function(){k=a.i.q(b);setTimeout(f,0)},c=c.substring(5));a.a.n(b,c,d)});var m=function(){var e=a.a.c(d()),f=a.i.q(b);if(null!==k&&e===k)setTimeout(m,0);else if(e!==f)if("select"===a.a.t(b)){var g=c.get("valueAllowUnset"),f=function(){a.i.ca(b,e,g)};f();g||e===a.i.q(b)?setTimeout(f,0):a.k.B(a.a.oa,null,[b,"change"])}else a.i.ca(b,e)};a.s(m,null,{o:b})}else a.ra(b,{checkedValue:d})},update:function(){}};a.h.V.value=!0;a.d.visible={update:function(b,d){var c=a.a.c(d()),e="none"!=b.style.display;c&&!e?b.style.display="":!c&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(d,c,e,g,h){return a.d.event.init.call(this,d,function(){var a={};a[b]=c();return a},e,g,h)}}})("click");a.H=function(){};a.H.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.H.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.H.prototype.makeTemplateSource=function(b,d){if("string"==typeof b){d=d||v;var c=d.getElementById(b);if(!c)throw Error("Cannot find template with ID "+b);return new a.r.l(c)}if(1==b.nodeType||8==b.nodeType)return new a.r.fa(b);throw Error("Unknown template type: "+b);};a.H.prototype.renderTemplate=function(a,d,c,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,d,c)};a.H.prototype.isTemplateRewritten=function(a,d){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,d).data("isRewritten")};a.H.prototype.rewriteTemplate=function(a,d,c){a=this.makeTemplateSource(a,c);d=d(a.text());a.text(d);a.data("isRewritten",!0)};a.b("templateEngine",a.H);a.fb=function(){function b(b,c,d,k){b=a.h.Wa(b);for(var f=a.h.ha,m=0;m<b.length;m++){var l=b[m].key;if(f.hasOwnProperty(l)){var q=f[l];if("function"===typeof q){if(l=q(b[m].value))throw Error(l);}else if(!q)throw Error("This template engine does not support the '"+l+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.h.ya(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return k.createJavaScriptEvaluatorBlock(d)+c}var d=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,c=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{ec:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.fb.nc(b,c)},d)},nc:function(a,g){return a.replace(d,function(a,c,d,e,l){return b(l,c,d,g)}).replace(c,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",g)})},Xb:function(b,c){return a.D.Ua(function(d,k){var f=d.nextSibling;f&&f.nodeName.toLowerCase()===c&&a.ra(f,b,k)})}}}();a.b("__tr_ambtns",a.fb.Xb);(function(){a.r={};a.r.l=function(a){this.l=a};a.r.l.prototype.text=function(){var b=a.a.t(this.l),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.l[b];var d=arguments[0];"innerHTML"===b?a.a.$a(this.l,d):this.l[b]=d};var b=a.a.e.F()+"_";a.r.l.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.l,b+c);a.a.e.set(this.l,b+c,arguments[1])};var d=a.a.e.F();a.r.fa=function(a){this.l=a};a.r.fa.prototype=new a.r.l;a.r.fa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.l,d)||{};b.gb===p&&b.Ga&&(b.gb=b.Ga.innerHTML);return b.gb}a.a.e.set(this.l,d,{gb:arguments[0]})};a.r.l.prototype.nodes=function(){if(0==arguments.length)return(a.a.e.get(this.l,d)||{}).Ga;a.a.e.set(this.l,d,{Ga:arguments[0]})};a.b("templateSources",a.r);a.b("templateSources.domElement",a.r.l);a.b("templateSources.anonymousTemplate",a.r.fa)})();(function(){function b(b,c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),d(e,b)}function d(c,d){if(c.length){var e=c[0],g=c[c.length-1],h=e.parentNode,n=a.J.instance,t=n.preprocessNode;if(t){b(e,g,function(a,b){var c=a.previousSibling,d=t.call(n,a);d&&(a===e&&(e=d[0]||b),a===g&&(g=d[d.length-1]||c))});c.length=0;if(!e)return;e===g?c.push(e):(c.push(e,g),a.a.ka(c,h))}b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.pb(d,b)});b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.D.Sb(b,[d])});a.a.ka(c,h)}}function c(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,h,l,q){q=q||{};var n=b&&c(b),n=n&&n.ownerDocument,t=q.templateEngine||g;a.fb.ec(h,t,n);h=t.renderTemplate(h,l,q,n);if("number"!=typeof h.length||0<h.length&&"number"!=typeof h[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case"replaceChildren":a.f.T(b,h);n=!0;break;case"replaceNode":a.a.Lb(b,h);n=!0;break;case"ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}n&&(d(h,l),q.afterRender&&a.k.B(q.afterRender,null,[h,l.$data]));return h}var g;a.ab=function(b){if(b!=p&&!(b instanceof a.H))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.Ya=function(b,d,h,l,q){h=h||{};if((h.templateEngine||g)==p)throw Error("Set a template engine before calling renderTemplate");q=q||"replaceChildren";if(l){var n=c(l);return a.j(function(){var g=d&&d instanceof a.N?d:new a.N(a.a.c(d)),p=a.C(b)?b():"function"===typeof b?b(g.$data,g):b,g=e(l,q,p,g,h);"replaceNode"==q&&(l=g,n=c(l))},null,{Ia:function(){return!n||!a.a.Ja(n)},o:n&&"replaceNode"==q?n.parentNode:n})}return a.D.Ua(function(c){a.Ya(b,d,h,c,"replaceNode")})};a.uc=function(b,c,g,h,q){function n(a,b){d(b,s);g.afterRender&&g.afterRender(b,a)}function t(c,d){s=q.createChildContext(c,g.as,function(a){a.$index=d});var f=a.C(b)?b():"function"===typeof b?b(c,s):b;return e(null,"ignoreTargetNode",f,s,g)}var s;return a.j(function(){var b=a.a.c(c)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.ta(b,function(b){return g.includeDestroyed||b===p||null===b||!a.a.c(b._destroy)});a.k.B(a.a.Za,null,[h,b,t,g,n])},null,{o:h})};var h=a.a.e.F();a.d.template={init:function(b,c){var d=a.a.c(c());"string"==typeof d||d.name?a.f.ja(b):(d=a.f.childNodes(b),d=a.a.oc(d),(new a.r.fa(b)).nodes(d));return{controlsDescendantBindings:!0}},update:function(b,c,d,e,g){var n=c(),t;c=a.a.c(n);d=!0;e=null;"string"==typeof c?c={}:(n=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)),t=a.a.c(c.data));"foreach"in c?e=a.uc(n||b,d&&c.foreach||[],c,b,g):d?(g="data"in c?g.createChildContext(t,c.as):g,e=a.Ya(n||b,g,c,b)):a.f.ja(b);g=e;(t=a.a.e.get(b,h))&&"function"==typeof t.K&&t.K();a.a.e.set(b,h,g&&g.Z()?g:p)}};a.h.ha.template=function(b){b=a.h.Wa(b);return 1==b.length&&b[0].unknown||a.h.lc(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.f.Q.template=!0})();a.b("setTemplateEngine",a.ab);a.b("renderTemplate",a.Ya);a.a.wb=function(a,d,c){if(a.length&&d.length){var e,g,h,k,f;for(e=g=0;(!c||e<c)&&(k=a[g]);++g){for(h=0;f=d[h];++h)if(k.value===f.value){k.moved=f.index;f.moved=k.index;d.splice(h,1);e=h=0;break}e+=h}}};a.a.Fa=function(){function b(b,c,e,g,h){var k=Math.min,f=Math.max,m=[],l,q=b.length,n,p=c.length,s=p-q||1,u=q+p+1,r,v,w;for(l=0;l<=q;l++)for(v=r,m.push(r=[]),w=k(p,l+s),n=f(0,l-1);n<=w;n++)r[n]=n?l?b[l-1]===c[n-1]?v[n-1]:k(v[n]||u,r[n-1]||u)+1:n+1:l+1;k=[];f=[];s=[];l=q;for(n=p;l||n;)p=m[l][n]-1,n&&p===m[l][n-1]?f.push(k[k.length]={status:e,value:c[--n],index:n}):l&&p===m[l-1][n]?s.push(k[k.length]={status:g,value:b[--l],index:l}):(--n,--l,h.sparse||k.push({status:"retained",value:c[n]}));a.a.wb(f,s,10*q);return k.reverse()}return function(a,c,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];c=c||[];return a.length<=c.length?b(a,c,"added","deleted",e):b(c,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Fa);(function(){function b(b,d,g,h,k){var f=[],m=a.j(function(){var l=d(g,k,a.a.ka(f,b))||[];0<f.length&&(a.a.Lb(f,l),h&&a.k.B(h,null,[g,l,k]));f.length=0;a.a.ga(f,l)},null,{o:b,Ia:function(){return!a.a.ob(f)}});return{$:f,j:m.Z()?m:p}}var d=a.a.e.F();a.a.Za=function(c,e,g,h,k){function f(b,d){x=q[d];r!==d&&(A[b]=x);x.Na(r++);a.a.ka(x.$,c);s.push(x);w.push(x)}function m(b,c){if(b)for(var d=0,e=c.length;d<e;d++)c[d]&&a.a.u(c[d].$,function(a){b(a,d,c[d].sa)})}e=e||[];h=h||{};var l=a.a.e.get(c,d)===p,q=a.a.e.get(c,d)||[],n=a.a.Da(q,function(a){return a.sa}),t=a.a.Fa(n,e,h.dontLimitMoves),s=[],u=0,r=0,v=[],w=[];e=[];for(var A=[],n=[],x,B=0,D,F;D=t[B];B++)switch(F=D.moved,D.status){case"deleted":F===p&&(x=q[u],x.j&&x.j.K(),v.push.apply(v,a.a.ka(x.$,c)),h.beforeRemove&&(e[B]=x,w.push(x)));u++;break;case"retained":f(B,u++);break;case"added":F!==p?f(B,F):(x={sa:D.value,Na:a.p(r++)},s.push(x),w.push(x),l||(n[B]=x))}m(h.beforeMove,A);a.a.u(v,h.beforeRemove?a.R:a.removeNode);for(var B=0,l=a.f.firstChild(c),G;x=w[B];B++){x.$||a.a.extend(x,b(c,g,x.sa,k,x.Na));for(u=0;t=x.$[u];l=t.nextSibling,G=t,u++)t!==l&&a.f.Bb(c,t,G);!x.ic&&k&&(k(x.sa,x.$,x.Na),x.ic=!0)}m(h.beforeRemove,e);m(h.afterMove,A);m(h.afterAdd,n);a.a.e.set(c,d,s)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Za);a.O=function(){this.allowTemplateRewriting=!1};a.O.prototype=new a.H;a.O.prototype.renderTemplateSource=function(b){var d=(9>a.a.L?0:b.nodes)?b.nodes():null;if(d)return a.a.S(d.cloneNode(!0).childNodes);b=b.text();return a.a.ba(b)};a.O.Oa=new a.O;a.ab(a.O.Oa);a.b("nativeTemplateEngine",a.O);(function(){a.Sa=function(){var a=this.kc=function(){if(!w||!w.tmpl)return 0;try{if(0<=w.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,g){g=g||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=w.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=w.extend({koBindingContext:e},g.templateOptions);e=w.tmpl(h,b,e);e.appendTo(v.createElement("div"));w.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){v.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(w.tmpl.tag.ko_code={open:"__.push($1 || '');"},w.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.Sa.prototype=new a.H;var b=new a.Sa;0<b.kc&&a.ab(b);a.b("jqueryTmplTemplateEngine",a.Sa)})()})})();})();
    • marked
      • marked.js
        /**
         * marked - a markdown parser
         * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
         * https://github.com/chjj/marked
         */
        
        ;(function() {
        
        /**
         * Block-Level Grammar
         */
        
        var block = {
          newline: /^\n+/,
          code: /^( {4}[^\n]+\n*)+/,
          fences: noop,
          hr: /^( *[-*_]){3,} *(?:\n+|$)/,
          heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
          nptable: noop,
          lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
          blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
          list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
          html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
          def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
          table: noop,
          paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
          text: /^[^\n]+/
        };
        
        block.bullet = /(?:[*+-]|\d+\.)/;
        block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
        block.item = replace(block.item, 'gm')
          (/bull/g, block.bullet)
          ();
        
        block.list = replace(block.list)
          (/bull/g, block.bullet)
          ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
          ('def', '\\n+(?=' + block.def.source + ')')
          ();
        
        block.blockquote = replace(block.blockquote)
          ('def', block.def)
          ();
        
        block._tag = '(?!(?:'
          + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
          + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
          + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
        
        block.html = replace(block.html)
          ('comment', /<!--[\s\S]*?-->/)
          ('closed', /<(tag)[\s\S]+?<\/\1>/)
          ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
          (/tag/g, block._tag)
          ();
        
        block.paragraph = replace(block.paragraph)
          ('hr', block.hr)
          ('heading', block.heading)
          ('lheading', block.lheading)
          ('blockquote', block.blockquote)
          ('tag', '<' + block._tag)
          ('def', block.def)
          ();
        
        /**
         * Normal Block Grammar
         */
        
        block.normal = merge({}, block);
        
        /**
         * GFM Block Grammar
         */
        
        block.gfm = merge({}, block.normal, {
          fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
          paragraph: /^/
        });
        
        block.gfm.paragraph = replace(block.paragraph)
          ('(?!', '(?!'
            + block.gfm.fences.source.replace('\\1', '\\2') + '|'
            + block.list.source.replace('\\1', '\\3') + '|')
          ();
        
        /**
         * GFM + Tables Block Grammar
         */
        
        block.tables = merge({}, block.gfm, {
          nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
          table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
        });
        
        /**
         * Block Lexer
         */
        
        function Lexer(options) {
          this.tokens = [];
          this.tokens.links = {};
          this.options = options || marked.defaults;
          this.rules = block.normal;
        
          if (this.options.gfm) {
            if (this.options.tables) {
              this.rules = block.tables;
            } else {
              this.rules = block.gfm;
            }
          }
        }
        
        /**
         * Expose Block Rules
         */
        
        Lexer.rules = block;
        
        /**
         * Static Lex Method
         */
        
        Lexer.lex = function(src, options) {
          var lexer = new Lexer(options);
          return lexer.lex(src);
        };
        
        /**
         * Preprocessing
         */
        
        Lexer.prototype.lex = function(src) {
          src = src
            .replace(/\r\n|\r/g, '\n')
            .replace(/\t/g, '    ')
            .replace(/\u00a0/g, ' ')
            .replace(/\u2424/g, '\n');
        
          return this.token(src, true);
        };
        
        /**
         * Lexing
         */
        
        Lexer.prototype.token = function(src, top, bq) {
          var src = src.replace(/^ +$/gm, '')
            , next
            , loose
            , cap
            , bull
            , b
            , item
            , space
            , i
            , l;
        
          while (src) {
            // newline
            if (cap = this.rules.newline.exec(src)) {
              src = src.substring(cap[0].length);
              if (cap[0].length > 1) {
                this.tokens.push({
                  type: 'space'
                });
              }
            }
        
            // code
            if (cap = this.rules.code.exec(src)) {
              src = src.substring(cap[0].length);
              cap = cap[0].replace(/^ {4}/gm, '');
              this.tokens.push({
                type: 'code',
                text: !this.options.pedantic
                  ? cap.replace(/\n+$/, '')
                  : cap
              });
              continue;
            }
        
            // fences (gfm)
            if (cap = this.rules.fences.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'code',
                lang: cap[2],
                text: cap[3]
              });
              continue;
            }
        
            // heading
            if (cap = this.rules.heading.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'heading',
                depth: cap[1].length,
                text: cap[2]
              });
              continue;
            }
        
            // table no leading pipe (gfm)
            if (top && (cap = this.rules.nptable.exec(src))) {
              src = src.substring(cap[0].length);
        
              item = {
                type: 'table',
                header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                cells: cap[3].replace(/\n$/, '').split('\n')
              };
        
              for (i = 0; i < item.align.length; i++) {
                if (/^ *-+: *$/.test(item.align[i])) {
                  item.align[i] = 'right';
                } else if (/^ *:-+: *$/.test(item.align[i])) {
                  item.align[i] = 'center';
                } else if (/^ *:-+ *$/.test(item.align[i])) {
                  item.align[i] = 'left';
                } else {
                  item.align[i] = null;
                }
              }
        
              for (i = 0; i < item.cells.length; i++) {
                item.cells[i] = item.cells[i].split(/ *\| */);
              }
        
              this.tokens.push(item);
        
              continue;
            }
        
            // lheading
            if (cap = this.rules.lheading.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'heading',
                depth: cap[2] === '=' ? 1 : 2,
                text: cap[1]
              });
              continue;
            }
        
            // hr
            if (cap = this.rules.hr.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'hr'
              });
              continue;
            }
        
            // blockquote
            if (cap = this.rules.blockquote.exec(src)) {
              src = src.substring(cap[0].length);
        
              this.tokens.push({
                type: 'blockquote_start'
              });
        
              cap = cap[0].replace(/^ *> ?/gm, '');
        
              // Pass `top` to keep the current
              // "toplevel" state. This is exactly
              // how markdown.pl works.
              this.token(cap, top, true);
        
              this.tokens.push({
                type: 'blockquote_end'
              });
        
              continue;
            }
        
            // list
            if (cap = this.rules.list.exec(src)) {
              src = src.substring(cap[0].length);
              bull = cap[2];
        
              this.tokens.push({
                type: 'list_start',
                ordered: bull.length > 1
              });
        
              // Get each top-level item.
              cap = cap[0].match(this.rules.item);
        
              next = false;
              l = cap.length;
              i = 0;
        
              for (; i < l; i++) {
                item = cap[i];
        
                // Remove the list item's bullet
                // so it is seen as the next token.
                space = item.length;
                item = item.replace(/^ *([*+-]|\d+\.) +/, '');
        
                // Outdent whatever the
                // list item contains. Hacky.
                if (~item.indexOf('\n ')) {
                  space -= item.length;
                  item = !this.options.pedantic
                    ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
                    : item.replace(/^ {1,4}/gm, '');
                }
        
                // Determine whether the next list item belongs here.
                // Backpedal if it does not belong in this list.
                if (this.options.smartLists && i !== l - 1) {
                  b = block.bullet.exec(cap[i + 1])[0];
                  if (bull !== b && !(bull.length > 1 && b.length > 1)) {
                    src = cap.slice(i + 1).join('\n') + src;
                    i = l - 1;
                  }
                }
        
                // Determine whether item is loose or not.
                // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
                // for discount behavior.
                loose = next || /\n\n(?!\s*$)/.test(item);
                if (i !== l - 1) {
                  next = item.charAt(item.length - 1) === '\n';
                  if (!loose) loose = next;
                }
        
                this.tokens.push({
                  type: loose
                    ? 'loose_item_start'
                    : 'list_item_start'
                });
        
                // Recurse.
                this.token(item, false, bq);
        
                this.tokens.push({
                  type: 'list_item_end'
                });
              }
        
              this.tokens.push({
                type: 'list_end'
              });
        
              continue;
            }
        
            // html
            if (cap = this.rules.html.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: this.options.sanitize
                  ? 'paragraph'
                  : 'html',
                pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
                text: cap[0]
              });
              continue;
            }
        
            // def
            if ((!bq && top) && (cap = this.rules.def.exec(src))) {
              src = src.substring(cap[0].length);
              this.tokens.links[cap[1].toLowerCase()] = {
                href: cap[2],
                title: cap[3]
              };
              continue;
            }
        
            // table (gfm)
            if (top && (cap = this.rules.table.exec(src))) {
              src = src.substring(cap[0].length);
        
              item = {
                type: 'table',
                header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
              };
        
              for (i = 0; i < item.align.length; i++) {
                if (/^ *-+: *$/.test(item.align[i])) {
                  item.align[i] = 'right';
                } else if (/^ *:-+: *$/.test(item.align[i])) {
                  item.align[i] = 'center';
                } else if (/^ *:-+ *$/.test(item.align[i])) {
                  item.align[i] = 'left';
                } else {
                  item.align[i] = null;
                }
              }
        
              for (i = 0; i < item.cells.length; i++) {
                item.cells[i] = item.cells[i]
                  .replace(/^ *\| *| *\| *$/g, '')
                  .split(/ *\| */);
              }
        
              this.tokens.push(item);
        
              continue;
            }
        
            // top-level paragraph
            if (top && (cap = this.rules.paragraph.exec(src))) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'paragraph',
                text: cap[1].charAt(cap[1].length - 1) === '\n'
                  ? cap[1].slice(0, -1)
                  : cap[1]
              });
              continue;
            }
        
            // text
            if (cap = this.rules.text.exec(src)) {
              // Top-level should never reach here.
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'text',
                text: cap[0]
              });
              continue;
            }
        
            if (src) {
              throw new
                Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
          }
        
          return this.tokens;
        };
        
        /**
         * Inline-Level Grammar
         */
        
        var inline = {
          escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
          autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
          url: noop,
          tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
          link: /^!?\[(inside)\]\(href\)/,
          reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
          nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
          strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
          em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
          code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
          br: /^ {2,}\n(?!\s*$)/,
          del: noop,
          text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
        };
        
        inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
        inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
        
        inline.link = replace(inline.link)
          ('inside', inline._inside)
          ('href', inline._href)
          ();
        
        inline.reflink = replace(inline.reflink)
          ('inside', inline._inside)
          ();
        
        /**
         * Normal Inline Grammar
         */
        
        inline.normal = merge({}, inline);
        
        /**
         * Pedantic Inline Grammar
         */
        
        inline.pedantic = merge({}, inline.normal, {
          strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
          em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
        });
        
        /**
         * GFM Inline Grammar
         */
        
        inline.gfm = merge({}, inline.normal, {
          escape: replace(inline.escape)('])', '~|])')(),
          url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
          del: /^~~(?=\S)([\s\S]*?\S)~~/,
          text: replace(inline.text)
            (']|', '~]|')
            ('|', '|https?://|')
            ()
        });
        
        /**
         * GFM + Line Breaks Inline Grammar
         */
        
        inline.breaks = merge({}, inline.gfm, {
          br: replace(inline.br)('{2,}', '*')(),
          text: replace(inline.gfm.text)('{2,}', '*')()
        });
        
        /**
         * Inline Lexer & Compiler
         */
        
        function InlineLexer(links, options) {
          this.options = options || marked.defaults;
          this.links = links;
          this.rules = inline.normal;
          this.renderer = this.options.renderer || new Renderer;
          this.renderer.options = this.options;
        
          if (!this.links) {
            throw new
              Error('Tokens array requires a `links` property.');
          }
        
          if (this.options.gfm) {
            if (this.options.breaks) {
              this.rules = inline.breaks;
            } else {
              this.rules = inline.gfm;
            }
          } else if (this.options.pedantic) {
            this.rules = inline.pedantic;
          }
        }
        
        /**
         * Expose Inline Rules
         */
        
        InlineLexer.rules = inline;
        
        /**
         * Static Lexing/Compiling Method
         */
        
        InlineLexer.output = function(src, links, options) {
          var inline = new InlineLexer(links, options);
          return inline.output(src);
        };
        
        /**
         * Lexing/Compiling
         */
        
        InlineLexer.prototype.output = function(src) {
          var out = ''
            , link
            , text
            , href
            , cap;
        
          while (src) {
            // escape
            if (cap = this.rules.escape.exec(src)) {
              src = src.substring(cap[0].length);
              out += cap[1];
              continue;
            }
        
            // autolink
            if (cap = this.rules.autolink.exec(src)) {
              src = src.substring(cap[0].length);
              if (cap[2] === '@') {
                text = cap[1].charAt(6) === ':'
                  ? this.mangle(cap[1].substring(7))
                  : this.mangle(cap[1]);
                href = this.mangle('mailto:') + text;
              } else {
                text = escape(cap[1]);
                href = text;
              }
              out += this.renderer.link(href, null, text);
              continue;
            }
        
            // url (gfm)
            if (!this.inLink && (cap = this.rules.url.exec(src))) {
              src = src.substring(cap[0].length);
              text = escape(cap[1]);
              href = text;
              out += this.renderer.link(href, null, text);
              continue;
            }
        
            // tag
            if (cap = this.rules.tag.exec(src)) {
              if (!this.inLink && /^<a /i.test(cap[0])) {
                this.inLink = true;
              } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
                this.inLink = false;
              }
              src = src.substring(cap[0].length);
              out += this.options.sanitize
                ? escape(cap[0])
                : cap[0];
              continue;
            }
        
            // link
            if (cap = this.rules.link.exec(src)) {
              src = src.substring(cap[0].length);
              this.inLink = true;
              out += this.outputLink(cap, {
                href: cap[2],
                title: cap[3]
              });
              this.inLink = false;
              continue;
            }
        
            // reflink, nolink
            if ((cap = this.rules.reflink.exec(src))
                || (cap = this.rules.nolink.exec(src))) {
              src = src.substring(cap[0].length);
              link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
              link = this.links[link.toLowerCase()];
              if (!link || !link.href) {
                out += cap[0].charAt(0);
                src = cap[0].substring(1) + src;
                continue;
              }
              this.inLink = true;
              out += this.outputLink(cap, link);
              this.inLink = false;
              continue;
            }
        
            // strong
            if (cap = this.rules.strong.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.strong(this.output(cap[2] || cap[1]));
              continue;
            }
        
            // em
            if (cap = this.rules.em.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.em(this.output(cap[2] || cap[1]));
              continue;
            }
        
            // code
            if (cap = this.rules.code.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.codespan(escape(cap[2], true));
              continue;
            }
        
            // br
            if (cap = this.rules.br.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.br();
              continue;
            }
        
            // del (gfm)
            if (cap = this.rules.del.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.del(this.output(cap[1]));
              continue;
            }
        
            // text
            if (cap = this.rules.text.exec(src)) {
              src = src.substring(cap[0].length);
              out += escape(this.smartypants(cap[0]));
              continue;
            }
        
            if (src) {
              throw new
                Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
          }
        
          return out;
        };
        
        /**
         * Compile Link
         */
        
        InlineLexer.prototype.outputLink = function(cap, link) {
          var href = escape(link.href)
            , title = link.title ? escape(link.title) : null;
        
          return cap[0].charAt(0) !== '!'
            ? this.renderer.link(href, title, this.output(cap[1]))
            : this.renderer.image(href, title, escape(cap[1]));
        };
        
        /**
         * Smartypants Transformations
         */
        
        InlineLexer.prototype.smartypants = function(text) {
          if (!this.options.smartypants) return text;
          return text
            // em-dashes
            .replace(/--/g, '\u2014')
            // opening singles
            .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
            // closing singles & apostrophes
            .replace(/'/g, '\u2019')
            // opening doubles
            .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
            // closing doubles
            .replace(/"/g, '\u201d')
            // ellipses
            .replace(/\.{3}/g, '\u2026');
        };
        
        /**
         * Mangle Links
         */
        
        InlineLexer.prototype.mangle = function(text) {
          var out = ''
            , l = text.length
            , i = 0
            , ch;
        
          for (; i < l; i++) {
            ch = text.charCodeAt(i);
            if (Math.random() > 0.5) {
              ch = 'x' + ch.toString(16);
            }
            out += '&#' + ch + ';';
          }
        
          return out;
        };
        
        /**
         * Renderer
         */
        
        function Renderer(options) {
          this.options = options || {};
        }
        
        Renderer.prototype.code = function(code, lang, escaped) {
          if (this.options.highlight) {
            var out = this.options.highlight(code, lang);
            if (out != null && out !== code) {
              escaped = true;
              code = out;
            }
          }
        
          if (!lang) {
            return '<pre><code>'
              + (escaped ? code : escape(code, true))
              + '\n</code></pre>';
          }
        
          return '<pre><code class="'
            + this.options.langPrefix
            + escape(lang, true)
            + '">'
            + (escaped ? code : escape(code, true))
            + '\n</code></pre>\n';
        };
        
        Renderer.prototype.blockquote = function(quote) {
          return '<blockquote>\n' + quote + '</blockquote>\n';
        };
        
        Renderer.prototype.html = function(html) {
          return html;
        };
        
        Renderer.prototype.heading = function(text, level, raw) {
          return '<h'
            + level
            + ' id="'
            + this.options.headerPrefix
            + raw.toLowerCase().replace(/[^\w]+/g, '-')
            + '">'
            + text
            + '</h'
            + level
            + '>\n';
        };
        
        Renderer.prototype.hr = function() {
          return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
        };
        
        Renderer.prototype.list = function(body, ordered) {
          var type = ordered ? 'ol' : 'ul';
          return '<' + type + '>\n' + body + '</' + type + '>\n';
        };
        
        Renderer.prototype.listitem = function(text) {
          return '<li>' + text + '</li>\n';
        };
        
        Renderer.prototype.paragraph = function(text) {
          return '<p>' + text + '</p>\n';
        };
        
        Renderer.prototype.table = function(header, body) {
          return '<table>\n'
            + '<thead>\n'
            + header
            + '</thead>\n'
            + '<tbody>\n'
            + body
            + '</tbody>\n'
            + '</table>\n';
        };
        
        Renderer.prototype.tablerow = function(content) {
          return '<tr>\n' + content + '</tr>\n';
        };
        
        Renderer.prototype.tablecell = function(content, flags) {
          var type = flags.header ? 'th' : 'td';
          var tag = flags.align
            ? '<' + type + ' style="text-align:' + flags.align + '">'
            : '<' + type + '>';
          return tag + content + '</' + type + '>\n';
        };
        
        // span level renderer
        Renderer.prototype.strong = function(text) {
          return '<strong>' + text + '</strong>';
        };
        
        Renderer.prototype.em = function(text) {
          return '<em>' + text + '</em>';
        };
        
        Renderer.prototype.codespan = function(text) {
          return '<code>' + text + '</code>';
        };
        
        Renderer.prototype.br = function() {
          return this.options.xhtml ? '<br/>' : '<br>';
        };
        
        Renderer.prototype.del = function(text) {
          return '<del>' + text + '</del>';
        };
        
        Renderer.prototype.link = function(href, title, text) {
          if (this.options.sanitize) {
            try {
              var prot = decodeURIComponent(unescape(href))
                .replace(/[^\w:]/g, '')
                .toLowerCase();
            } catch (e) {
              return '';
            }
            if (prot.indexOf('javascript:') === 0) {
              return '';
            }
          }
          var out = '<a href="' + href + '"';
          if (title) {
            out += ' title="' + title + '"';
          }
          out += '>' + text + '</a>';
          return out;
        };
        
        Renderer.prototype.image = function(href, title, text) {
          var out = '<img src="' + href + '" alt="' + text + '"';
          if (title) {
            out += ' title="' + title + '"';
          }
          out += this.options.xhtml ? '/>' : '>';
          return out;
        };
        
        /**
         * Parsing & Compiling
         */
        
        function Parser(options) {
          this.tokens = [];
          this.token = null;
          this.options = options || marked.defaults;
          this.options.renderer = this.options.renderer || new Renderer;
          this.renderer = this.options.renderer;
          this.renderer.options = this.options;
        }
        
        /**
         * Static Parse Method
         */
        
        Parser.parse = function(src, options, renderer) {
          var parser = new Parser(options, renderer);
          return parser.parse(src);
        };
        
        /**
         * Parse Loop
         */
        
        Parser.prototype.parse = function(src) {
          this.inline = new InlineLexer(src.links, this.options, this.renderer);
          this.tokens = src.reverse();
        
          var out = '';
          while (this.next()) {
            out += this.tok();
          }
        
          return out;
        };
        
        /**
         * Next Token
         */
        
        Parser.prototype.next = function() {
          return this.token = this.tokens.pop();
        };
        
        /**
         * Preview Next Token
         */
        
        Parser.prototype.peek = function() {
          return this.tokens[this.tokens.length - 1] || 0;
        };
        
        /**
         * Parse Text Tokens
         */
        
        Parser.prototype.parseText = function() {
          var body = this.token.text;
        
          while (this.peek().type === 'text') {
            body += '\n' + this.next().text;
          }
        
          return this.inline.output(body);
        };
        
        /**
         * Parse Current Token
         */
        
        Parser.prototype.tok = function() {
          switch (this.token.type) {
            case 'space': {
              return '';
            }
            case 'hr': {
              return this.renderer.hr();
            }
            case 'heading': {
              return this.renderer.heading(
                this.inline.output(this.token.text),
                this.token.depth,
                this.token.text);
            }
            case 'code': {
              return this.renderer.code(this.token.text,
                this.token.lang,
                this.token.escaped);
            }
            case 'table': {
              var header = ''
                , body = ''
                , i
                , row
                , cell
                , flags
                , j;
        
              // header
              cell = '';
              for (i = 0; i < this.token.header.length; i++) {
                flags = { header: true, align: this.token.align[i] };
                cell += this.renderer.tablecell(
                  this.inline.output(this.token.header[i]),
                  { header: true, align: this.token.align[i] }
                );
              }
              header += this.renderer.tablerow(cell);
        
              for (i = 0; i < this.token.cells.length; i++) {
                row = this.token.cells[i];
        
                cell = '';
                for (j = 0; j < row.length; j++) {
                  cell += this.renderer.tablecell(
                    this.inline.output(row[j]),
                    { header: false, align: this.token.align[j] }
                  );
                }
        
                body += this.renderer.tablerow(cell);
              }
              return this.renderer.table(header, body);
            }
            case 'blockquote_start': {
              var body = '';
        
              while (this.next().type !== 'blockquote_end') {
                body += this.tok();
              }
        
              return this.renderer.blockquote(body);
            }
            case 'list_start': {
              var body = ''
                , ordered = this.token.ordered;
        
              while (this.next().type !== 'list_end') {
                body += this.tok();
              }
        
              return this.renderer.list(body, ordered);
            }
            case 'list_item_start': {
              var body = '';
        
              while (this.next().type !== 'list_item_end') {
                body += this.token.type === 'text'
                  ? this.parseText()
                  : this.tok();
              }
        
              return this.renderer.listitem(body);
            }
            case 'loose_item_start': {
              var body = '';
        
              while (this.next().type !== 'list_item_end') {
                body += this.tok();
              }
        
              return this.renderer.listitem(body);
            }
            case 'html': {
              var html = !this.token.pre && !this.options.pedantic
                ? this.inline.output(this.token.text)
                : this.token.text;
              return this.renderer.html(html);
            }
            case 'paragraph': {
              return this.renderer.paragraph(this.inline.output(this.token.text));
            }
            case 'text': {
              return this.renderer.paragraph(this.parseText());
            }
          }
        };
        
        /**
         * Helpers
         */
        
        function escape(html, encode) {
          return html
            .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
        }
        
        function unescape(html) {
          return html.replace(/&([#\w]+);/g, function(_, n) {
            n = n.toLowerCase();
            if (n === 'colon') return ':';
            if (n.charAt(0) === '#') {
              return n.charAt(1) === 'x'
                ? String.fromCharCode(parseInt(n.substring(2), 16))
                : String.fromCharCode(+n.substring(1));
            }
            return '';
          });
        }
        
        function replace(regex, opt) {
          regex = regex.source;
          opt = opt || '';
          return function self(name, val) {
            if (!name) return new RegExp(regex, opt);
            val = val.source || val;
            val = val.replace(/(^|[^\[])\^/g, '$1');
            regex = regex.replace(name, val);
            return self;
          };
        }
        
        function noop() {}
        noop.exec = noop;
        
        function merge(obj) {
          var i = 1
            , target
            , key;
        
          for (; i < arguments.length; i++) {
            target = arguments[i];
            for (key in target) {
              if (Object.prototype.hasOwnProperty.call(target, key)) {
                obj[key] = target[key];
              }
            }
          }
        
          return obj;
        }
        
        
        /**
         * Marked
         */
        
        function marked(src, opt, callback) {
          if (callback || typeof opt === 'function') {
            if (!callback) {
              callback = opt;
              opt = null;
            }
        
            opt = merge({}, marked.defaults, opt || {});
        
            var highlight = opt.highlight
              , tokens
              , pending
              , i = 0;
        
            try {
              tokens = Lexer.lex(src, opt)
            } catch (e) {
              return callback(e);
            }
        
            pending = tokens.length;
        
            var done = function(err) {
              if (err) {
                opt.highlight = highlight;
                return callback(err);
              }
        
              var out;
        
              try {
                out = Parser.parse(tokens, opt);
              } catch (e) {
                err = e;
              }
        
              opt.highlight = highlight;
        
              return err
                ? callback(err)
                : callback(null, out);
            };
        
            if (!highlight || highlight.length < 3) {
              return done();
            }
        
            delete opt.highlight;
        
            if (!pending) return done();
        
            for (; i < tokens.length; i++) {
              (function(token) {
                if (token.type !== 'code') {
                  return --pending || done();
                }
                return highlight(token.text, token.lang, function(err, code) {
                  if (err) return done(err);
                  if (code == null || code === token.text) {
                    return --pending || done();
                  }
                  token.text = code;
                  token.escaped = true;
                  --pending || done();
                });
              })(tokens[i]);
            }
        
            return;
          }
          try {
            if (opt) opt = merge({}, marked.defaults, opt);
            return Parser.parse(Lexer.lex(src, opt), opt);
          } catch (e) {
            e.message += '\nPlease report this to https://github.com/chjj/marked.';
            if ((opt || marked.defaults).silent) {
              return '<p>An error occured:</p><pre>'
                + escape(e.message + '', true)
                + '</pre>';
            }
            throw e;
          }
        }
        
        /**
         * Options
         */
        
        marked.options =
        marked.setOptions = function(opt) {
          merge(marked.defaults, opt);
          return marked;
        };
        
        marked.defaults = {
          gfm: true,
          tables: true,
          breaks: false,
          pedantic: false,
          sanitize: false,
          smartLists: false,
          silent: false,
          highlight: null,
          langPrefix: 'lang-',
          smartypants: false,
          headerPrefix: '',
          renderer: new Renderer,
          xhtml: false
        };
        
        /**
         * Expose
         */
        
        marked.Parser = Parser;
        marked.parser = Parser.parse;
        
        marked.Renderer = Renderer;
        
        marked.Lexer = Lexer;
        marked.lexer = Lexer.lex;
        
        marked.InlineLexer = InlineLexer;
        marked.inlineLexer = InlineLexer.output;
        
        marked.parse = marked;
        
        if (typeof module !== 'undefined' && typeof exports === 'object') {
          module.exports = marked;
        } else if (typeof define === 'function' && define.amd) {
          define(function() { return marked; });
        } else {
          this.marked = marked;
        }
        
        }).call(function() {
          return this || (typeof window !== 'undefined' ? window : global);
        }());
        
    • typescript
      • core.d.ts.text
        /// <reference no-default-lib="true"/>
        
        /////////////////////////////
        /// ECMAScript APIs
        /////////////////////////////
        
        declare var NaN: number;
        declare var Infinity: number;
        
        /**
          * Evaluates JavaScript code and executes it. 
          * @param x A String value that contains valid JavaScript code.
          */
        declare function eval(x: string): any;
        
        /**
          * Converts A string to an integer.
          * @param s A string to convert into a number.
          * @param radix A value between 2 and 36 that specifies the base of the number in numString. 
          * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
          * All other strings are considered decimal.
          */
        declare function parseInt(s: string, radix?: number): number;
        
        /**
          * Converts a string to a floating-point number. 
          * @param string A string that contains a floating-point number. 
          */
        declare function parseFloat(string: string): number;
        
        /**
          * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number). 
          * @param number A numeric value.
          */
        declare function isNaN(number: number): boolean;
        
        /** 
          * Determines whether a supplied number is finite.
          * @param number Any numeric value.
          */
        declare function isFinite(number: number): boolean;
        
        /**
          * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).
          * @param encodedURI A value representing an encoded URI.
          */
        declare function decodeURI(encodedURI: string): string;
        
        /**
          * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).
          * @param encodedURIComponent A value representing an encoded URI component.
          */
        declare function decodeURIComponent(encodedURIComponent: string): string;
        
        /** 
          * Encodes a text string as a valid Uniform Resource Identifier (URI)
          * @param uri A value representing an encoded URI.
          */
        declare function encodeURI(uri: string): string;
        
        /**
          * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).
          * @param uriComponent A value representing an encoded URI component.
          */
        declare function encodeURIComponent(uriComponent: string): string;
        
        interface PropertyDescriptor {
            configurable?: boolean;
            enumerable?: boolean;
            value?: any;
            writable?: boolean;
            get? (): any;
            set? (v: any): void;
        }
        
        interface PropertyDescriptorMap {
            [s: string]: PropertyDescriptor;
        }
        
        interface Object {
            /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
            constructor: Function;
        
            /** Returns a string representation of an object. */
            toString(): string;
        
            /** Returns a date converted to a string using the current locale. */
            toLocaleString(): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): Object;
        
            /**
              * Determines whether an object has a property with the specified name. 
              * @param v A property name.
              */
            hasOwnProperty(v: string): boolean;
        
            /**
              * Determines whether an object exists in another object's prototype chain. 
              * @param v Another object whose prototype chain is to be checked.
              */
            isPrototypeOf(v: Object): boolean;
        
            /** 
              * Determines whether a specified property is enumerable.
              * @param v A property name.
              */
            propertyIsEnumerable(v: string): boolean;
        }
        
        interface ObjectConstructor {
            new (value?: any): Object;
            (): any;
            (value: any): any;
        
            /** A reference to the prototype for a class of objects. */
            prototype: Object;
        
            /** 
              * Returns the prototype of an object. 
              * @param o The object that references the prototype.
              */
            getPrototypeOf(o: any): any;
        
            /**
              * Gets the own property descriptor of the specified object. 
              * An own property descriptor is one that is defined directly on the object and is not inherited from the object's prototype. 
              * @param o Object that contains the property.
              * @param p Name of the property.
            */
            getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;
        
            /** 
              * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly 
              * on that object, and are not inherited from the object's prototype. The properties of an object include both fields (objects) and functions.
              * @param o Object that contains the own properties.
              */
            getOwnPropertyNames(o: any): string[];
        
            /** 
              * Creates an object that has the specified prototype, and that optionally contains specified properties.
              * @param o Object to use as a prototype. May be null
              * @param properties JavaScript object that contains one or more property descriptors. 
              */
            create(o: any, properties?: PropertyDescriptorMap): any;
        
            /**
              * Adds a property to an object, or modifies attributes of an existing property. 
              * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.
              * @param p The property name.
              * @param attributes Descriptor for the property. It can be for a data property or an accessor property.
              */
            defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
        
            /**
              * Adds one or more properties to an object, and/or modifies attributes of existing properties. 
              * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
              * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
              */
            defineProperties(o: any, properties: PropertyDescriptorMap): any;
        
            /**
              * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
              * @param o Object on which to lock the attributes. 
              */
            seal<T>(o: T): T;
        
            /**
              * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.
              * @param o Object on which to lock the attributes.
              */
            freeze<T>(o: T): T;
        
            /**
              * Prevents the addition of new properties to an object.
              * @param o Object to make non-extensible. 
              */
            preventExtensions<T>(o: T): T;
        
            /**
              * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.
              * @param o Object to test. 
              */
            isSealed(o: any): boolean;
        
            /**
              * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.
              * @param o Object to test.  
              */
            isFrozen(o: any): boolean;
        
            /**
              * Returns a value that indicates whether new properties can be added to an object.
              * @param o Object to test. 
              */
            isExtensible(o: any): boolean;
        
            /**
              * Returns the names of the enumerable properties and methods of an object.
              * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
              */
            keys(o: any): string[];
        }
        
        /**
          * Provides functionality common to all JavaScript objects.
          */
        declare var Object: ObjectConstructor;
        
        /**
          * Creates a new function.
          */
        interface Function {
            /**
              * Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.
              * @param thisArg The object to be used as the this object.
              * @param argArray A set of arguments to be passed to the function.
              */
            apply(thisArg: any, argArray?: any): any;
        
            /**
              * Calls a method of an object, substituting another object for the current object.
              * @param thisArg The object to be used as the current object.
              * @param argArray A list of arguments to be passed to the method.
              */
            call(thisArg: any, ...argArray: any[]): any;
        
            /**
              * For a given function, creates a bound function that has the same body as the original function. 
              * The this object of the bound function is associated with the specified object, and has the specified initial parameters.
              * @param thisArg An object to which the this keyword can refer inside the new function.
              * @param argArray A list of arguments to be passed to the new function.
              */
            bind(thisArg: any, ...argArray: any[]): any;
        
            prototype: any;
            length: number;
        
            // Non-standard extensions
            arguments: any;
            caller: Function;
        }
        
        interface FunctionConstructor {
            /**
              * Creates a new function.
              * @param args A list of arguments the function accepts.
              */
            new (...args: string[]): Function;
            (...args: string[]): Function;
            prototype: Function;
        }
        
        declare var Function: FunctionConstructor;
        
        interface IArguments {
            [index: number]: any;
            length: number;
            callee: Function;
        }
        
        interface String {
            /** Returns a string representation of a string. */
            toString(): string;
        
            /**
              * Returns the character at the specified index.
              * @param pos The zero-based index of the desired character.
              */
            charAt(pos: number): string;
        
            /** 
              * Returns the Unicode value of the character at the specified location.
              * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
              */
            charCodeAt(index: number): number;
        
            /**
              * Returns a string that contains the concatenation of two or more strings.
              * @param strings The strings to append to the end of the string.  
              */
            concat(...strings: string[]): string;
        
            /**
              * Returns the position of the first occurrence of a substring. 
              * @param searchString The substring to search for in the string
              * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.
              */
            indexOf(searchString: string, position?: number): number;
        
            /**
              * Returns the last occurrence of a substring in the string.
              * @param searchString The substring to search for.
              * @param position The index at which to begin searching. If omitted, the search begins at the end of the string.
              */
            lastIndexOf(searchString: string, position?: number): number;
        
            /**
              * Determines whether two strings are equivalent in the current locale.
              * @param that String to compare to target string
              */
            localeCompare(that: string): number;
        
            /** 
              * Matches a string with a regular expression, and returns an array containing the results of that search.
              * @param regexp A variable name or string literal containing the regular expression pattern and flags.
              */
            match(regexp: string): RegExpMatchArray;
        
            /** 
              * Matches a string with a regular expression, and returns an array containing the results of that search.
              * @param regexp A regular expression object that contains the regular expression pattern and applicable flags. 
              */
            match(regexp: RegExp): RegExpMatchArray;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A String object or string literal that represents the regular expression
              * @param replaceValue A String object or string literal containing the text to replace for every successful match of rgExp in stringObj.
              */
            replace(searchValue: string, replaceValue: string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A String object or string literal that represents the regular expression
              * @param replaceValue A function that returns the replacement text.
              */
            replace(searchValue: string, replaceValue: (substring: string, ...args: any[]) => string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
              * @param replaceValue A String object or string literal containing the text to replace for every successful match of rgExp in stringObj.
              */
            replace(searchValue: RegExp, replaceValue: string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
              * @param replaceValue A function that returns the replacement text.
              */
            replace(searchValue: RegExp, replaceValue: (substring: string, ...args: any[]) => string): string;
        
            /**
              * Finds the first substring match in a regular expression search.
              * @param regexp The regular expression pattern and applicable flags. 
              */
            search(regexp: string): number;
        
            /**
              * Finds the first substring match in a regular expression search.
              * @param regexp The regular expression pattern and applicable flags. 
              */
            search(regexp: RegExp): number;
        
            /**
              * Returns a section of a string.
              * @param start The index to the beginning of the specified portion of stringObj. 
              * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. 
              * If this value is not specified, the substring continues to the end of stringObj.
              */
            slice(start?: number, end?: number): string;
        
            /**
              * Split a string into substrings using the specified separator and return them as an array.
              * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. 
              * @param limit A value used to limit the number of elements returned in the array.
              */
            split(separator: string, limit?: number): string[];
        
            /**
              * Split a string into substrings using the specified separator and return them as an array.
              * @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. 
              * @param limit A value used to limit the number of elements returned in the array.
              */
            split(separator: RegExp, limit?: number): string[];
        
            /**
              * Returns the substring at the specified location within a String object. 
              * @param start The zero-based index number indicating the beginning of the substring.
              * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
              * If end is omitted, the characters from start through the end of the original string are returned.
              */
            substring(start: number, end?: number): string;
        
            /** Converts all the alphabetic characters in a string to lowercase. */
            toLowerCase(): string;
        
            /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */
            toLocaleLowerCase(): string;
        
            /** Converts all the alphabetic characters in a string to uppercase. */
            toUpperCase(): string;
        
            /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */
            toLocaleUpperCase(): string;
        
            /** Removes the leading and trailing white space and line terminator characters from a string. */
            trim(): string;
        
            /** Returns the length of a String object. */
            length: number;
        
            // IE extensions
            /**
              * Gets a substring beginning at the specified location and having the specified length.
              * @param from The starting position of the desired substring. The index of the first character in the string is zero.
              * @param length The number of characters to include in the returned substring.
              */
            substr(from: number, length?: number): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): string;
        
            [index: number]: string;
        }
        
        interface StringConstructor {
            new (value?: any): String;
            (value?: any): string;
            prototype: String;
            fromCharCode(...codes: number[]): string;
        }
        
        /** 
          * Allows manipulation and formatting of text strings and determination and location of substrings within strings. 
          */
        declare var String: StringConstructor;
        
        interface Boolean {
            /** Returns the primitive value of the specified object. */
            valueOf(): boolean;
        }
        
        interface BooleanConstructor {
            new (value?: any): Boolean;
            (value?: any): boolean;
            prototype: Boolean;
        }
        
        declare var Boolean: BooleanConstructor;
        
        interface Number {
            /**
              * Returns a string representation of an object.
              * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
              */
            toString(radix?: number): string;
        
            /** 
              * Returns a string representing a number in fixed-point notation.
              * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
              */
            toFixed(fractionDigits?: number): string;
        
            /**
              * Returns a string containing a number represented in exponential notation.
              * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
              */
            toExponential(fractionDigits?: number): string;
        
            /**
              * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.
              * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
              */
            toPrecision(precision?: number): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): number;
        }
        
        interface NumberConstructor {
            new (value?: any): Number;
            (value?: any): number;
            prototype: Number;
        
            /** The largest number that can be represented in JavaScript. Equal to approximately 1.79E+308. */
            MAX_VALUE: number;
        
            /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */
            MIN_VALUE: number;
        
            /** 
              * A value that is not a number.
              * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function.
              */
            NaN: number;
        
            /** 
              * A value that is less than the largest negative number that can be represented in JavaScript.
              * JavaScript displays NEGATIVE_INFINITY values as -infinity. 
              */
            NEGATIVE_INFINITY: number;
        
            /**
              * A value greater than the largest number that can be represented in JavaScript. 
              * JavaScript displays POSITIVE_INFINITY values as infinity. 
              */
            POSITIVE_INFINITY: number;
        }
        
        /** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */
        declare var Number: NumberConstructor;
        
        interface TemplateStringsArray extends Array<string> {
            raw: string[];
        }
        
        interface Math {
            /** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
            E: number;
            /** The natural logarithm of 10. */
            LN10: number;
            /** The natural logarithm of 2. */
            LN2: number;
            /** The base-2 logarithm of e. */
            LOG2E: number;
            /** The base-10 logarithm of e. */
            LOG10E: number;
            /** Pi. This is the ratio of the circumference of a circle to its diameter. */
            PI: number;
            /** The square root of 0.5, or, equivalently, one divided by the square root of 2. */
            SQRT1_2: number;
            /** The square root of 2. */
            SQRT2: number;
            /**
              * Returns the absolute value of a number (the value without regard to whether it is positive or negative). 
              * For example, the absolute value of -5 is the same as the absolute value of 5.
              * @param x A numeric expression for which the absolute value is needed.
              */
            abs(x: number): number;
            /**
              * Returns the arc cosine (or inverse cosine) of a number. 
              * @param x A numeric expression.
              */
            acos(x: number): number;
            /** 
              * Returns the arcsine of a number. 
              * @param x A numeric expression.
              */
            asin(x: number): number;
            /**
              * Returns the arctangent of a number. 
              * @param x A numeric expression for which the arctangent is needed.
              */
            atan(x: number): number;
            /**
              * Returns the angle (in radians) from the X axis to a point (y,x).
              * @param y A numeric expression representing the cartesian y-coordinate.
              * @param x A numeric expression representing the cartesian x-coordinate.
              */
            atan2(y: number, x: number): number;
            /**
              * Returns the smallest number greater than or equal to its numeric argument. 
              * @param x A numeric expression.
              */
            ceil(x: number): number;
            /**
              * Returns the cosine of a number. 
              * @param x A numeric expression that contains an angle measured in radians.
              */
            cos(x: number): number;
            /**
              * Returns e (the base of natural logarithms) raised to a power. 
              * @param x A numeric expression representing the power of e.
              */
            exp(x: number): number;
            /**
              * Returns the greatest number less than or equal to its numeric argument. 
              * @param x A numeric expression.
              */
            floor(x: number): number;
            /**
              * Returns the natural logarithm (base e) of a number. 
              * @param x A numeric expression.
              */
            log(x: number): number;
            /**
              * Returns the larger of a set of supplied numeric expressions. 
              * @param values Numeric expressions to be evaluated.
              */
            max(...values: number[]): number;
            /**
              * Returns the smaller of a set of supplied numeric expressions. 
              * @param values Numeric expressions to be evaluated.
              */
            min(...values: number[]): number;
            /**
              * Returns the value of a base expression taken to a specified power. 
              * @param x The base value of the expression.
              * @param y The exponent value of the expression.
              */
            pow(x: number, y: number): number;
            /** Returns a pseudorandom number between 0 and 1. */
            random(): number;
            /** 
              * Returns a supplied numeric expression rounded to the nearest number.
              * @param x The value to be rounded to the nearest number.
              */
            round(x: number): number;
            /**
              * Returns the sine of a number.
              * @param x A numeric expression that contains an angle measured in radians.
              */
            sin(x: number): number;
            /**
              * Returns the square root of a number.
              * @param x A numeric expression.
              */
            sqrt(x: number): number;
            /**
              * Returns the tangent of a number.
              * @param x A numeric expression that contains an angle measured in radians.
              */
            tan(x: number): number;
        }
        /** An intrinsic object that provides basic mathematics functionality and constants. */
        declare var Math: Math;
        
        /** Enables basic storage and retrieval of dates and times. */
        interface Date {
            /** Returns a string representation of a date. The format of the string depends on the locale. */
            toString(): string;
            /** Returns a date as a string value. */
            toDateString(): string;
            /** Returns a time as a string value. */
            toTimeString(): string;
            /** Returns a value as a string value appropriate to the host environment's current locale. */
            toLocaleString(): string;
            /** Returns a date as a string value appropriate to the host environment's current locale. */
            toLocaleDateString(): string;
            /** Returns a time as a string value appropriate to the host environment's current locale. */
            toLocaleTimeString(): string;
            /** Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC. */
            valueOf(): number;
            /** Gets the time value in milliseconds. */
            getTime(): number;
            /** Gets the year, using local time. */
            getFullYear(): number;
            /** Gets the year using Universal Coordinated Time (UTC). */
            getUTCFullYear(): number;
            /** Gets the month, using local time. */
            getMonth(): number;
            /** Gets the month of a Date object using Universal Coordinated Time (UTC). */
            getUTCMonth(): number;
            /** Gets the day-of-the-month, using local time. */
            getDate(): number;
            /** Gets the day-of-the-month, using Universal Coordinated Time (UTC). */
            getUTCDate(): number;
            /** Gets the day of the week, using local time. */
            getDay(): number;
            /** Gets the day of the week using Universal Coordinated Time (UTC). */
            getUTCDay(): number;
            /** Gets the hours in a date, using local time. */
            getHours(): number;
            /** Gets the hours value in a Date object using Universal Coordinated Time (UTC). */
            getUTCHours(): number;
            /** Gets the minutes of a Date object, using local time. */
            getMinutes(): number;
            /** Gets the minutes of a Date object using Universal Coordinated Time (UTC). */
            getUTCMinutes(): number;
            /** Gets the seconds of a Date object, using local time. */
            getSeconds(): number;
            /** Gets the seconds of a Date object using Universal Coordinated Time (UTC). */
            getUTCSeconds(): number;
            /** Gets the milliseconds of a Date, using local time. */
            getMilliseconds(): number;
            /** Gets the milliseconds of a Date object using Universal Coordinated Time (UTC). */
            getUTCMilliseconds(): number;
            /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */
            getTimezoneOffset(): number;
            /** 
              * Sets the date and time value in the Date object.
              * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT. 
              */
            setTime(time: number): number;
            /**
              * Sets the milliseconds value in the Date object using local time. 
              * @param ms A numeric value equal to the millisecond value.
              */
            setMilliseconds(ms: number): number;
            /** 
              * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC).
              * @param ms A numeric value equal to the millisecond value. 
              */
            setUTCMilliseconds(ms: number): number;
        
            /**
              * Sets the seconds value in the Date object using local time. 
              * @param sec A numeric value equal to the seconds value.
              * @param ms A numeric value equal to the milliseconds value.
              */
            setSeconds(sec: number, ms?: number): number;
            /**
              * Sets the seconds value in the Date object using Universal Coordinated Time (UTC).
              * @param sec A numeric value equal to the seconds value.
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCSeconds(sec: number, ms?: number): number;
            /**
              * Sets the minutes value in the Date object using local time. 
              * @param min A numeric value equal to the minutes value. 
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setMinutes(min: number, sec?: number, ms?: number): number;
            /**
              * Sets the minutes value in the Date object using Universal Coordinated Time (UTC).
              * @param min A numeric value equal to the minutes value. 
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCMinutes(min: number, sec?: number, ms?: number): number;
            /**
              * Sets the hour value in the Date object using local time.
              * @param hours A numeric value equal to the hours value.
              * @param min A numeric value equal to the minutes value.
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setHours(hours: number, min?: number, sec?: number, ms?: number): number;
            /**
              * Sets the hours value in the Date object using Universal Coordinated Time (UTC).
              * @param hours A numeric value equal to the hours value.
              * @param min A numeric value equal to the minutes value.
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;
            /**
              * Sets the numeric day-of-the-month value of the Date object using local time. 
              * @param date A numeric value equal to the day of the month.
              */
            setDate(date: number): number;
            /** 
              * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC).
              * @param date A numeric value equal to the day of the month. 
              */
            setUTCDate(date: number): number;
            /** 
              * Sets the month value in the Date object using local time. 
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. 
              * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used.
              */
            setMonth(month: number, date?: number): number;
            /**
              * Sets the month value in the Date object using Universal Coordinated Time (UTC).
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.
              * @param date A numeric value representing the day of the month. If it is not supplied, the value from a call to the getUTCDate method is used.
              */
            setUTCMonth(month: number, date?: number): number;
            /**
              * Sets the year of the Date object using local time.
              * @param year A numeric value for the year.
              * @param month A zero-based numeric value for the month (0 for January, 11 for December). Must be specified if numDate is specified.
              * @param date A numeric value equal for the day of the month.
              */
            setFullYear(year: number, month?: number, date?: number): number;
            /**
              * Sets the year value in the Date object using Universal Coordinated Time (UTC).
              * @param year A numeric value equal to the year.
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. Must be supplied if numDate is supplied.
              * @param date A numeric value equal to the day of the month.
              */
            setUTCFullYear(year: number, month?: number, date?: number): number;
            /** Returns a date converted to a string using Universal Coordinated Time (UTC). */
            toUTCString(): string;
            /** Returns a date as a string value in ISO format. */
            toISOString(): string;
            /** Used by the JSON.stringify method to enable the transformation of an object's data for JavaScript Object Notation (JSON) serialization. */
            toJSON(key?: any): string;
        }
        
        interface DateConstructor {
            new (): Date;
            new (value: number): Date;
            new (value: string): Date;
            new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
            (): string;
            prototype: Date;
            /**
              * Parses a string containing a date, and returns the number of milliseconds between that date and midnight, January 1, 1970.
              * @param s A date string
              */
            parse(s: string): number;
            /**
              * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date. 
              * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.
              * @param month The month as an number between 0 and 11 (January to December).
              * @param date The date as an number between 1 and 31.
              * @param hours Must be supplied if minutes is supplied. An number from 0 to 23 (midnight to 11pm) that specifies the hour.
              * @param minutes Must be supplied if seconds is supplied. An number from 0 to 59 that specifies the minutes.
              * @param seconds Must be supplied if milliseconds is supplied. An number from 0 to 59 that specifies the seconds.
              * @param ms An number from 0 to 999 that specifies the milliseconds.
              */
            UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
            now(): number;
        }
        
        declare var Date: DateConstructor;
        
        interface RegExpMatchArray extends Array<string> {
            index?: number;
            input?: string;
        }
        
        interface RegExpExecArray extends Array<string> {
            index: number;
            input: string;
        }
        
        interface RegExp {
            /** 
              * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.
              * @param string The String object or string literal on which to perform the search.
              */
            exec(string: string): RegExpExecArray;
        
            /** 
              * Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
              * @param string String on which to perform the search.
              */
            test(string: string): boolean;
        
            /** Returns a copy of the text of the regular expression pattern. Read-only. The rgExp argument is a Regular expression object. It can be a variable name or a literal. */
            source: string;
        
            /** Returns a Boolean value indicating the state of the global flag (g) used with a regular expression. Default is false. Read-only. */
            global: boolean;
        
            /** Returns a Boolean value indicating the state of the ignoreCase flag (i) used with a regular expression. Default is false. Read-only. */
            ignoreCase: boolean;
        
            /** Returns a Boolean value indicating the state of the multiline flag (m) used with a regular expression. Default is false. Read-only. */
            multiline: boolean;
        
            lastIndex: number;
        
            // Non-standard extensions
            compile(): RegExp;
        }
        
        interface RegExpConstructor {
            new (pattern: string, flags?: string): RegExp;
            (pattern: string, flags?: string): RegExp;
            prototype: RegExp;
        
            // Non-standard extensions
            $1: string;
            $2: string;
            $3: string;
            $4: string;
            $5: string;
            $6: string;
            $7: string;
            $8: string;
            $9: string;
            lastMatch: string;
        }
        
        declare var RegExp: RegExpConstructor;
        
        interface Error {
            name: string;
            message: string;
        }
        
        interface ErrorConstructor {
            new (message?: string): Error;
            (message?: string): Error;
            prototype: Error;
        }
        
        declare var Error: ErrorConstructor;
        
        interface EvalError extends Error {
        }
        
        interface EvalErrorConstructor {
            new (message?: string): EvalError;
            (message?: string): EvalError;
            prototype: EvalError;
        }
        
        declare var EvalError: EvalErrorConstructor;
        
        interface RangeError extends Error {
        }
        
        interface RangeErrorConstructor {
            new (message?: string): RangeError;
            (message?: string): RangeError;
            prototype: RangeError;
        }
        
        declare var RangeError: RangeErrorConstructor;
        
        interface ReferenceError extends Error {
        }
        
        interface ReferenceErrorConstructor {
            new (message?: string): ReferenceError;
            (message?: string): ReferenceError;
            prototype: ReferenceError;
        }
        
        declare var ReferenceError: ReferenceErrorConstructor;
        
        interface SyntaxError extends Error {
        }
        
        interface SyntaxErrorConstructor {
            new (message?: string): SyntaxError;
            (message?: string): SyntaxError;
            prototype: SyntaxError;
        }
        
        declare var SyntaxError: SyntaxErrorConstructor;
        
        interface TypeError extends Error {
        }
        
        interface TypeErrorConstructor {
            new (message?: string): TypeError;
            (message?: string): TypeError;
            prototype: TypeError;
        }
        
        declare var TypeError: TypeErrorConstructor;
        
        interface URIError extends Error {
        }
        
        interface URIErrorConstructor {
            new (message?: string): URIError;
            (message?: string): URIError;
            prototype: URIError;
        }
        
        declare var URIError: URIErrorConstructor;
        
        interface JSON {
            /**
              * Converts a JavaScript Object Notation (JSON) string into an object.
              * @param text A valid JSON string.
              * @param reviver A function that transforms the results. This function is called for each member of the object. 
              * If a member contains nested objects, the nested objects are transformed before the parent object is. 
              */
            parse(text: string, reviver?: (key: any, value: any) => any): any;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              */
            stringify(value: any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer A function that transforms the results.
              */
            stringify(value: any, replacer: (key: string, value: any) => any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer Array that transforms the results.
              */
            stringify(value: any, replacer: any[]): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer A function that transforms the results.
              * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
              */
            stringify(value: any, replacer: (key: string, value: any) => any, space: any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer Array that transforms the results.
              * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
              */
            stringify(value: any, replacer: any[], space: any): string;
        }
        /**
          * An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
          */
        declare var JSON: JSON;
        
        
        /////////////////////////////
        /// ECMAScript Array API (specially handled by compiler)
        /////////////////////////////
        
        interface Array<T> {
            /**
              * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
              */
            length: number;
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
            toLocaleString(): string;
            /**
              * Appends new elements to an array, and returns the new length of the array.
              * @param items New elements of the Array.
              */
            push(...items: T[]): number;
            /**
              * Removes the last element from an array and returns it.
              */
            pop(): T;
            /**
              * Combines two or more arrays.
              * @param items Additional items to add to the end of array1.
              */
            concat<U extends T[]>(...items: U[]): T[];
            /**
              * Combines two or more arrays.
              * @param items Additional items to add to the end of array1.
              */
            concat(...items: T[]): T[];
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): T[];
            /**
              * Removes the first element from an array and returns it.
              */
            shift(): T;
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): T[];
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: T, b: T) => number): T[];
        
            /**
              * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
              * @param start The zero-based location in the array from which to start removing elements.
              */
            splice(start: number): T[];
        
            /**
              * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
              * @param start The zero-based location in the array from which to start removing elements.
              * @param deleteCount The number of elements to remove.
              * @param items Elements to insert into the array in place of the deleted elements.
              */
            splice(start: number, deleteCount: number, ...items: T[]): T[];
        
            /**
              * Inserts new elements at the start of an array.
              * @param items  Elements to insert at the start of the Array.
              */
            unshift(...items: T[]): number;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
              */
            indexOf(searchElement: T, fromIndex?: number): number;
        
            /**
              * Returns the index of the last occurrence of a specified value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
              */
            lastIndexOf(searchElement: T, fromIndex?: number): number;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[];
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
            /**
              * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
        
            [n: number]: T;
        }
        
        interface ArrayConstructor {
            new (arrayLength?: number): any[];
            new <T>(arrayLength: number): T[];
            new <T>(...items: T[]): T[];
            (arrayLength?: number): any[];
            <T>(arrayLength: number): T[];
            <T>(...items: T[]): T[];
            isArray(arg: any): boolean;
            prototype: Array<any>;
        }
        
        declare var Array: ArrayConstructor;
        
      • dom.generated.d.ts.text
        /////////////////////////////
        /// IE DOM APIs
        /////////////////////////////
        
        
        interface PositionOptions {
            enableHighAccuracy?: boolean;
            timeout?: number;
            maximumAge?: number;
        }
        
        interface ObjectURLOptions {
            oneTimeOnly?: boolean;
        }
        
        interface StoreExceptionsInformation extends ExceptionInformation {
            siteName?: string;
            explanationString?: string;
            detailURI?: string;
        }
        
        interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {
            arrayOfDomainStrings?: string[];
        }
        
        interface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation {
            arrayOfDomainStrings?: string[];
        }
        
        interface AlgorithmParameters {
        }
        
        interface MutationObserverInit {
            childList?: boolean;
            attributes?: boolean;
            characterData?: boolean;
            subtree?: boolean;
            attributeOldValue?: boolean;
            characterDataOldValue?: boolean;
            attributeFilter?: string[];
        }
        
        interface PointerEventInit extends MouseEventInit {
            pointerId?: number;
            width?: number;
            height?: number;
            pressure?: number;
            tiltX?: number;
            tiltY?: number;
            pointerType?: string;
            isPrimary?: boolean;
        }
        
        interface ExceptionInformation {
            domain?: string;
        }
        
        interface DeviceAccelerationDict {
            x?: number;
            y?: number;
            z?: number;
        }
        
        interface MsZoomToOptions {
            contentX?: number;
            contentY?: number;
            viewportX?: string;
            viewportY?: string;
            scaleFactor?: number;
            animate?: string;
        }
        
        interface DeviceRotationRateDict {
            alpha?: number;
            beta?: number;
            gamma?: number;
        }
        
        interface Algorithm {
            name?: string;
            params?: AlgorithmParameters;
        }
        
        interface MouseEventInit {
            bubbles?: boolean;
            cancelable?: boolean;
            view?: Window;
            detail?: number;
            screenX?: number;
            screenY?: number;
            clientX?: number;
            clientY?: number;
            ctrlKey?: boolean;
            shiftKey?: boolean;
            altKey?: boolean;
            metaKey?: boolean;
            button?: number;
            buttons?: number;
            relatedTarget?: EventTarget;
        }
        
        interface WebGLContextAttributes {
            alpha?: boolean;
            depth?: boolean;
            stencil?: boolean;
            antialias?: boolean;
            premultipliedAlpha?: boolean;
            preserveDrawingBuffer?: boolean;
        }
        
        interface NodeListOf<TNode extends Node> extends NodeList {
            length: number;
            item(index: number): TNode;
            [index: number]: TNode;
        }
        
        interface HTMLElement extends Element, ElementCSSInlineStyle, MSEventAttachmentTarget, MSNodeExtensions {
            hidden: any;
            readyState: any;
            onmouseleave: (ev: MouseEvent) => any;
            onbeforecut: (ev: DragEvent) => any;
            onkeydown: (ev: KeyboardEvent) => any;
            onmove: (ev: MSEventObj) => any;
            onkeyup: (ev: KeyboardEvent) => any;
            onreset: (ev: Event) => any;
            onhelp: (ev: Event) => any;
            ondragleave: (ev: DragEvent) => any;
            className: string;
            onfocusin: (ev: FocusEvent) => any;
            onseeked: (ev: Event) => any;
            recordNumber: any;
            title: string;
            parentTextEdit: Element;
            outerHTML: string;
            ondurationchange: (ev: Event) => any;
            offsetHeight: number;
            all: HTMLCollection;
            onblur: (ev: FocusEvent) => any;
            dir: string;
            onemptied: (ev: Event) => any;
            onseeking: (ev: Event) => any;
            oncanplay: (ev: Event) => any;
            ondeactivate: (ev: UIEvent) => any;
            ondatasetchanged: (ev: MSEventObj) => any;
            onrowsdelete: (ev: MSEventObj) => any;
            sourceIndex: number;
            onloadstart: (ev: Event) => any;
            onlosecapture: (ev: MSEventObj) => any;
            ondragenter: (ev: DragEvent) => any;
            oncontrolselect: (ev: MSEventObj) => any;
            onsubmit: (ev: Event) => any;
            behaviorUrns: MSBehaviorUrnsCollection;
            scopeName: string;
            onchange: (ev: Event) => any;
            id: string;
            onlayoutcomplete: (ev: MSEventObj) => any;
            uniqueID: string;
            onbeforeactivate: (ev: UIEvent) => any;
            oncanplaythrough: (ev: Event) => any;
            onbeforeupdate: (ev: MSEventObj) => any;
            onfilterchange: (ev: MSEventObj) => any;
            offsetParent: Element;
            ondatasetcomplete: (ev: MSEventObj) => any;
            onsuspend: (ev: Event) => any;
            onmouseenter: (ev: MouseEvent) => any;
            innerText: string;
            onerrorupdate: (ev: MSEventObj) => any;
            onmouseout: (ev: MouseEvent) => any;
            parentElement: HTMLElement;
            onmousewheel: (ev: MouseWheelEvent) => any;
            onvolumechange: (ev: Event) => any;
            oncellchange: (ev: MSEventObj) => any;
            onrowexit: (ev: MSEventObj) => any;
            onrowsinserted: (ev: MSEventObj) => any;
            onpropertychange: (ev: MSEventObj) => any;
            filters: any;
            children: HTMLCollection;
            ondragend: (ev: DragEvent) => any;
            onbeforepaste: (ev: DragEvent) => any;
            ondragover: (ev: DragEvent) => any;
            offsetTop: number;
            onmouseup: (ev: MouseEvent) => any;
            ondragstart: (ev: DragEvent) => any;
            onbeforecopy: (ev: DragEvent) => any;
            ondrag: (ev: DragEvent) => any;
            innerHTML: string;
            onmouseover: (ev: MouseEvent) => any;
            lang: string;
            uniqueNumber: number;
            onpause: (ev: Event) => any;
            tagUrn: string;
            onmousedown: (ev: MouseEvent) => any;
            onclick: (ev: MouseEvent) => any;
            onwaiting: (ev: Event) => any;
            onresizestart: (ev: MSEventObj) => any;
            offsetLeft: number;
            isTextEdit: boolean;
            isDisabled: boolean;
            onpaste: (ev: DragEvent) => any;
            canHaveHTML: boolean;
            onmoveend: (ev: MSEventObj) => any;
            language: string;
            onstalled: (ev: Event) => any;
            onmousemove: (ev: MouseEvent) => any;
            style: MSStyleCSSProperties;
            isContentEditable: boolean;
            onbeforeeditfocus: (ev: MSEventObj) => any;
            onratechange: (ev: Event) => any;
            contentEditable: string;
            tabIndex: number;
            document: Document;
            onprogress: (ev: ProgressEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            oncontextmenu: (ev: MouseEvent) => any;
            onloadedmetadata: (ev: Event) => any;
            onafterupdate: (ev: MSEventObj) => any;
            onerror: (ev: ErrorEvent) => any;
            onplay: (ev: Event) => any;
            onresizeend: (ev: MSEventObj) => any;
            onplaying: (ev: Event) => any;
            isMultiLine: boolean;
            onfocusout: (ev: FocusEvent) => any;
            onabort: (ev: UIEvent) => any;
            ondataavailable: (ev: MSEventObj) => any;
            hideFocus: boolean;
            onreadystatechange: (ev: Event) => any;
            onkeypress: (ev: KeyboardEvent) => any;
            onloadeddata: (ev: Event) => any;
            onbeforedeactivate: (ev: UIEvent) => any;
            outerText: string;
            disabled: boolean;
            onactivate: (ev: UIEvent) => any;
            accessKey: string;
            onmovestart: (ev: MSEventObj) => any;
            onselectstart: (ev: Event) => any;
            onfocus: (ev: FocusEvent) => any;
            ontimeupdate: (ev: Event) => any;
            onresize: (ev: UIEvent) => any;
            oncut: (ev: DragEvent) => any;
            onselect: (ev: UIEvent) => any;
            ondrop: (ev: DragEvent) => any;
            offsetWidth: number;
            oncopy: (ev: DragEvent) => any;
            onended: (ev: Event) => any;
            onscroll: (ev: UIEvent) => any;
            onrowenter: (ev: MSEventObj) => any;
            onload: (ev: Event) => any;
            canHaveChildren: boolean;
            oninput: (ev: Event) => any;
            onmscontentzoom: (ev: MSEventObj) => any;
            oncuechange: (ev: Event) => any;
            spellcheck: boolean;
            classList: DOMTokenList;
            onmsmanipulationstatechanged: (ev: any) => any;
            draggable: boolean;
            dataset: DOMStringMap;
            dragDrop(): boolean;
            scrollIntoView(top?: boolean): void;
            addFilter(filter: any): void;
            setCapture(containerCapture?: boolean): void;
            focus(): void;
            getAdjacentText(where: string): string;
            insertAdjacentText(where: string, text: string): void;
            getElementsByClassName(classNames: string): NodeList;
            setActive(): void;
            removeFilter(filter: any): void;
            blur(): void;
            clearAttributes(): void;
            releaseCapture(): void;
            createControlRange(): ControlRangeCollection;
            removeBehavior(cookie: number): boolean;
            contains(child: HTMLElement): boolean;
            click(): void;
            insertAdjacentElement(position: string, insertedElement: Element): Element;
            mergeAttributes(source: HTMLElement, preserveIdentity?: boolean): void;
            replaceAdjacentText(where: string, newText: string): string;
            applyElement(apply: Element, where?: string): Element;
            addBehavior(bstrUrl: string, factory?: any): number;
            insertAdjacentHTML(where: string, html: string): void;
            msGetInputContext(): MSInputMethodContext;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLElement: {
            prototype: HTMLElement;
            new(): HTMLElement;
        }
        
        interface Document extends Node, NodeSelector, MSEventAttachmentTarget, DocumentEvent, MSResourceMetadata, MSNodeExtensions, MSDocumentExtensions, GlobalEventHandlers {
            /**
              * Gets a reference to the root node of the document. 
              */
            documentElement: HTMLElement;
            /**
              * Retrieves the collection of user agents and versions declared in the X-UA-Compatible
              */
            compatible: MSCompatibleInfoCollection;
            /**
              * Fires when the user presses a key.
              * @param ev The keyboard event
              */
            onkeydown: (ev: KeyboardEvent) => any;
            /**
              * Fires when the user releases a key.
              * @param ev The keyboard event
              */
            onkeyup: (ev: KeyboardEvent) => any;
            /**
              * Gets the implementation object of the current document. 
              */
            implementation: DOMImplementation;
            /**
              * Fires when the user resets a form. 
              * @param ev The event.
              */
            onreset: (ev: Event) => any;
            /**
              * Retrieves a collection of all script objects in the document.
              */
            scripts: HTMLCollection;
            /**
              * Fires when the user presses the F1 key while the browser is the active window. 
              * @param ev The event.
              */
            onhelp: (ev: Event) => any;
            /** 
              * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation.
              * @param ev The drag event.
              */
            ondragleave: (ev: DragEvent) => any;
            /**
              * Gets or sets the character set used to encode the object.
              */
            charset: string;
            /**
              * Fires for an element just prior to setting focus on that element.
              * @param ev The focus event
              */
            onfocusin: (ev: FocusEvent) => any;
            /** 
              * Sets or gets the color of the links that the user has visited.
              */
            vlinkColor: string;
            /**
              * Occurs when the seek operation ends. 
              * @param ev The event.
              */
            onseeked: (ev: Event) => any;
            security: string;
            /**
              * Contains the title of the document.
              */
            title: string;
            /**
              * Retrieves a collection of namespace objects.
              */
            namespaces: MSNamespaceInfoCollection;
            /**
              * Gets the default character set from the current regional language settings.
              */
            defaultCharset: string;
            /**
              * Retrieves a collection of all embed objects in the document.
              */
            embeds: HTMLCollection;
            /**
              * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document.
              */
            styleSheets: StyleSheetList;
            /**
              * Retrieves a collection of all window objects defined by the given document or defined by the document associated with the given window.
              */
            frames: Window;
            /**
              * Occurs when the duration attribute is updated. 
              * @param ev The event.
              */
            ondurationchange: (ev: Event) => any;
            /**
              * Returns a reference to the collection of elements contained by the object.
              */
            all: HTMLCollection;
            /**
              * Retrieves a collection, in source order, of all form objects in the document.
              */
            forms: HTMLCollection;
            /** 
              * Fires when the object loses the input focus. 
              * @param ev The focus event.
              */
            onblur: (ev: FocusEvent) => any;
            /**
              * Sets or retrieves a value that indicates the reading order of the object. 
              */
            dir: string;
            /**
              * Occurs when the media element is reset to its initial state. 
              * @param ev The event.
              */
            onemptied: (ev: Event) => any;
            /**
              * Sets or gets a value that indicates whether the document can be edited.
              */
            designMode: string;
            /**
              * Occurs when the current playback position is moved. 
              * @param ev The event.
              */
            onseeking: (ev: Event) => any;
            /**
              * Fires when the activeElement is changed from the current object to another object in the parent document.
              * @param ev The UI Event
              */
            ondeactivate: (ev: UIEvent) => any;
            /**
              * Occurs when playback is possible, but would require further buffering. 
              * @param ev The event.
              */
            oncanplay: (ev: Event) => any;
            /**
              * Fires when the data set exposed by a data source object changes. 
              * @param ev The event.
              */
            ondatasetchanged: (ev: MSEventObj) => any;
            /**
              * Fires when rows are about to be deleted from the recordset.
              * @param ev The event 
              */
            onrowsdelete: (ev: MSEventObj) => any;
            Script: MSScriptHost;
            /**
              * Occurs when Internet Explorer begins looking for media data. 
              * @param ev The event.
              */
            onloadstart: (ev: Event) => any;
            /**
              * Gets the URL for the document, stripped of any character encoding.
              */
            URLUnencoded: string;
            defaultView: Window;
            /**
              * Fires when the user is about to make a control selection of the object.
              * @param ev The event.
              */
            oncontrolselect: (ev: MSEventObj) => any;
            /** 
              * Fires on the target element when the user drags the object to a valid drop target.
              * @param ev The drag event.
              */
            ondragenter: (ev: DragEvent) => any;
            onsubmit: (ev: Event) => any;
            /**
              * Returns the character encoding used to create the webpage that is loaded into the document object.
              */
            inputEncoding: string;
            /**
              * Gets the object that has the focus when the parent document has focus.
              */
            activeElement: Element;
            /**
              * Fires when the contents of the object or selection have changed. 
              * @param ev The event.
              */
            onchange: (ev: Event) => any;
            /**
              * Retrieves a collection of all a objects that specify the href property and all area objects in the document.
              */
            links: HTMLCollection;
            /**
              * Retrieves an autogenerated, unique identifier for the object. 
              */
            uniqueID: string;
            /**
              * Sets or gets the URL for the current document. 
              */
            URL: string;
            /**
              * Fires immediately before the object is set as the active element.
              * @param ev The event.
              */
            onbeforeactivate: (ev: UIEvent) => any;
            head: HTMLHeadElement;
            cookie: string;
            xmlEncoding: string;
            oncanplaythrough: (ev: Event) => any;
            /** 
              * Retrieves the document compatibility mode of the document.
              */
            documentMode: number;
            characterSet: string;
            /**
              * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order.
              */
            anchors: HTMLCollection;
            onbeforeupdate: (ev: MSEventObj) => any;
            /** 
              * Fires to indicate that all data is available from the data source object. 
              * @param ev The event.
              */
            ondatasetcomplete: (ev: MSEventObj) => any;
            plugins: HTMLCollection;
            /**
              * Occurs if the load operation has been intentionally halted. 
              * @param ev The event.
              */
            onsuspend: (ev: Event) => any;
            /**
              * Gets the root svg element in the document hierarchy.
              */
            rootElement: SVGSVGElement;
            /**
              * Retrieves a value that indicates the current state of the object.
              */
            readyState: string;
            /**
              * Gets the URL of the location that referred the user to the current page.
              */
            referrer: string;
            /**
              * Sets or gets the color of all active links in the document.
              */
            alinkColor: string;
            /**
              * Fires on a databound object when an error occurs while updating the associated data in the data source object. 
              * @param ev The event.
              */
            onerrorupdate: (ev: MSEventObj) => any;
            /**
              * Gets a reference to the container object of the window.
              */
            parentWindow: Window;
            /**
              * Fires when the user moves the mouse pointer outside the boundaries of the object. 
              * @param ev The mouse event.
              */
            onmouseout: (ev: MouseEvent) => any;
            /**
              * Occurs when a user clicks a button in a Thumbnail Toolbar of a webpage running in Site Mode.
              * @param ev The event.
              */
            onmsthumbnailclick: (ev: MSSiteModeEvent) => any;
            /**
              * Fires when the wheel button is rotated. 
              * @param ev The mouse event
              */
            onmousewheel: (ev: MouseWheelEvent) => any;
            /**
              * Occurs when the volume is changed, or playback is muted or unmuted.
              * @param ev The event.
              */
            onvolumechange: (ev: Event) => any;
            /** 
              * Fires when data changes in the data provider.
              * @param ev The event.
              */
            oncellchange: (ev: MSEventObj) => any;
            /**
              * Fires just before the data source control changes the current row in the object. 
              * @param ev The event.
              */
            onrowexit: (ev: MSEventObj) => any;
            /**
              * Fires just after new rows are inserted in the current recordset.
              * @param ev The event.
              */
            onrowsinserted: (ev: MSEventObj) => any;
            /**
              * Gets or sets the version attribute specified in the declaration of an XML document.
              */
            xmlVersion: string;
            msCapsLockWarningOff: boolean;
            /**
              * Fires when a property changes on the object.
              * @param ev The event.
              */
            onpropertychange: (ev: MSEventObj) => any;
            /**
              * Fires on the source object when the user releases the mouse at the close of a drag operation.
              * @param ev The event.
              */
            ondragend: (ev: DragEvent) => any;
            /**
              * Gets an object representing the document type declaration associated with the current document. 
              */
            doctype: DocumentType;
            /**
              * Fires on the target element continuously while the user drags the object over a valid drop target.
              * @param ev The event.
              */
            ondragover: (ev: DragEvent) => any;
            /**
              * Deprecated. Sets or retrieves a value that indicates the background color behind the object. 
              */
            bgColor: string;
            /**
              * Fires on the source object when the user starts to drag a text selection or selected object. 
              * @param ev The event.
              */
            ondragstart: (ev: DragEvent) => any;
            /**
              * Fires when the user releases a mouse button while the mouse is over the object. 
              * @param ev The mouse event.
              */
            onmouseup: (ev: MouseEvent) => any;
            /**
              * Fires on the source object continuously during a drag operation.
              * @param ev The event.
              */
            ondrag: (ev: DragEvent) => any;
            /**
              * Fires when the user moves the mouse pointer into the object.
              * @param ev The mouse event.
              */
            onmouseover: (ev: MouseEvent) => any;
            /**
              * Sets or gets the color of the document links. 
              */
            linkColor: string;
            /**
              * Occurs when playback is paused.
              * @param ev The event.
              */
            onpause: (ev: Event) => any;
            /**
              * Fires when the user clicks the object with either mouse button. 
              * @param ev The mouse event.
              */
            onmousedown: (ev: MouseEvent) => any;
            /**
              * Fires when the user clicks the left mouse button on the object
              * @param ev The mouse event.
              */
            onclick: (ev: MouseEvent) => any;
            /**
              * Occurs when playback stops because the next frame of a video resource is not available. 
              * @param ev The event.
              */
            onwaiting: (ev: Event) => any;
            /**
              * Fires when the user clicks the Stop button or leaves the Web page.
              * @param ev The event.
              */
            onstop: (ev: Event) => any;
            /**
              * Occurs when an item is removed from a Jump List of a webpage running in Site Mode. 
              * @param ev The event.
              */
            onmssitemodejumplistitemremoved: (ev: MSSiteModeEvent) => any;
            /**
              * Retrieves a collection of all applet objects in the document.
              */
            applets: HTMLCollection;
            /**
              * Specifies the beginning and end of the document body.
              */
            body: HTMLElement;
            /**
              * Sets or gets the security domain of the document. 
              */
            domain: string;
            xmlStandalone: boolean;
            /**
              * Represents the active selection, which is a highlighted block of text or other elements in the document that a user or a script can carry out some action on.
              */
            selection: MSSelection;
            /**
              * Occurs when the download has stopped. 
              * @param ev The event.
              */
            onstalled: (ev: Event) => any;
            /**
              * Fires when the user moves the mouse over the object. 
              * @param ev The mouse event.
              */
            onmousemove: (ev: MouseEvent) => any;
            /**
              * Fires before an object contained in an editable element enters a UI-activated state or when an editable container object is control selected.
              * @param ev The event.
              */
            onbeforeeditfocus: (ev: MSEventObj) => any;
            /**
              * Occurs when the playback rate is increased or decreased. 
              * @param ev The event.
              */
            onratechange: (ev: Event) => any;
            /**
              * Occurs to indicate progress while downloading media data. 
              * @param ev The event.
              */
            onprogress: (ev: ProgressEvent) => any;
            /**
              * Fires when the user double-clicks the object.
              * @param ev The mouse event.
              */
            ondblclick: (ev: MouseEvent) => any;
            /**
              * Fires when the user clicks the right mouse button in the client area, opening the context menu. 
              * @param ev The mouse event.
              */
            oncontextmenu: (ev: MouseEvent) => any;
            /**
              * Occurs when the duration and dimensions of the media have been determined.
              * @param ev The event.
              */
            onloadedmetadata: (ev: Event) => any;
            media: string;
            /**
              * Fires when an error occurs during object loading.
              * @param ev The event.
              */
            onerror: (ev: ErrorEvent) => any;
            /**
              * Occurs when the play method is requested. 
              * @param ev The event.
              */
            onplay: (ev: Event) => any;
            onafterupdate: (ev: MSEventObj) => any;
            /**
              * Occurs when the audio or video has started playing. 
              * @param ev The event.
              */
            onplaying: (ev: Event) => any;
            /**
              * Retrieves a collection, in source order, of img objects in the document.
              */
            images: HTMLCollection;
            /**
              * Contains information about the current URL. 
              */
            location: Location;
            /**
              * Fires when the user aborts the download.
              * @param ev The event.
              */
            onabort: (ev: UIEvent) => any;
            /**
              * Fires for the current element with focus immediately after moving focus to another element. 
              * @param ev The event.
              */
            onfocusout: (ev: FocusEvent) => any;
            /**
              * Fires when the selection state of a document changes.
              * @param ev The event.
              */
            onselectionchange: (ev: Event) => any;
            /**
              * Fires when a local DOM Storage area is written to disk.
              * @param ev The event.
              */
            onstoragecommit: (ev: StorageEvent) => any;
            /**
              * Fires periodically as data arrives from data source objects that asynchronously transmit their data. 
              * @param ev The event.
              */
            ondataavailable: (ev: MSEventObj) => any;
            /**
              * Fires when the state of the object has changed.
              * @param ev The event
              */
            onreadystatechange: (ev: Event) => any;
            /**
              * Gets the date that the page was last modified, if the page supplies one. 
              */
            lastModified: string;
            /**
              * Fires when the user presses an alphanumeric key.
              * @param ev The event.
              */
            onkeypress: (ev: KeyboardEvent) => any;
            /**
              * Occurs when media data is loaded at the current playback position. 
              * @param ev The event.
              */
            onloadeddata: (ev: Event) => any;
            /**
              * Fires immediately before the activeElement is changed from the current object to another object in the parent document.
              * @param ev The event.
              */
            onbeforedeactivate: (ev: UIEvent) => any;
            /**
              * Fires when the object is set as the active element.
              * @param ev The event.
              */
            onactivate: (ev: UIEvent) => any;
            onselectstart: (ev: Event) => any;
            /**
              * Fires when the object receives focus. 
              * @param ev The event.
              */
            onfocus: (ev: FocusEvent) => any;
            /**
              * Sets or gets the foreground (text) color of the document.
              */
            fgColor: string;
            /**
              * Occurs to indicate the current playback position.
              * @param ev The event.
              */
            ontimeupdate: (ev: Event) => any;
            /**
              * Fires when the current selection changes.
              * @param ev The event.
              */
            onselect: (ev: UIEvent) => any;
            ondrop: (ev: DragEvent) => any;
            /**
              * Occurs when the end of playback is reached. 
              * @param ev The event
              */
            onended: (ev: Event) => any;
            /**
              * Gets a value that indicates whether standards-compliant mode is switched on for the object.
              */
            compatMode: string;
            /**
              * Fires when the user repositions the scroll box in the scroll bar on the object. 
              * @param ev The event.
              */
            onscroll: (ev: UIEvent) => any;
            /**
              * Fires to indicate that the current row has changed in the data source and new data values are available on the object. 
              * @param ev The event.
              */
            onrowenter: (ev: MSEventObj) => any;
            /**
              * Fires immediately after the browser loads the object. 
              * @param ev The event.
              */
            onload: (ev: Event) => any;
            oninput: (ev: Event) => any;
            onmspointerdown: (ev: any) => any;
            msHidden: boolean;
            msVisibilityState: string;
            onmsgesturedoubletap: (ev: any) => any;
            visibilityState: string;
            onmsmanipulationstatechanged: (ev: any) => any;
            onmspointerhover: (ev: any) => any;
            onmscontentzoom: (ev: MSEventObj) => any;
            onmspointermove: (ev: any) => any;
            onmsgesturehold: (ev: any) => any;
            onmsgesturechange: (ev: any) => any;
            onmsgesturestart: (ev: any) => any;
            onmspointercancel: (ev: any) => any;
            onmsgestureend: (ev: any) => any;
            onmsgesturetap: (ev: any) => any;
            onmspointerout: (ev: any) => any;
            onmsinertiastart: (ev: any) => any;
            msCSSOMElementFloatMetrics: boolean;
            onmspointerover: (ev: any) => any;
            hidden: boolean;
            onmspointerup: (ev: any) => any;
            msFullscreenEnabled: boolean;
            onmsfullscreenerror: (ev: any) => any;
            onmspointerenter: (ev: any) => any;
            msFullscreenElement: Element;
            onmsfullscreenchange: (ev: any) => any;
            onmspointerleave: (ev: any) => any;
            /**
              * Returns a reference to the first object with the specified value of the ID or NAME attribute.
              * @param elementId String that specifies the ID value. Case-insensitive.
              */
            getElementById(elementId: string): HTMLElement;
            /**
              * Returns the current value of the document, range, or current selection for the given command.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandValue(commandId: string): string;
            adoptNode(source: Node): Node;
            /**
              * Returns a Boolean value that indicates whether the specified command is in the indeterminate state.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandIndeterm(commandId: string): boolean;
            getElementsByTagNameNS(namespaceURI: string, localName: string): NodeList;
            createProcessingInstruction(target: string, data: string): ProcessingInstruction;
            /**
              * Executes a command on the current document, current selection, or the given range.
              * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script.
              * @param showUI Display the user interface, defaults to false.
              * @param value Value to assign.
              */
            execCommand(commandId: string, showUI?: boolean, value?: any): boolean;
            /**
              * Returns the element for the specified x coordinate and the specified y coordinate. 
              * @param x The x-offset
              * @param y The y-offset
              */
            elementFromPoint(x: number, y: number): Element;
            createCDATASection(data: string): CDATASection;
            /**
              * Retrieves the string associated with a command.
              * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers. 
              */
            queryCommandText(commandId: string): string;
            /**
              * Writes one or more HTML expressions to a document in the specified window. 
              * @param content Specifies the text and HTML tags to write.
              */
            write(...content: string[]): void;
            /**
              * Allows updating the print settings for the page.
              */
            updateSettings(): void;
            /**
              * Creates an instance of the element for the specified tag.
              * @param tagName The name of an element.
              */
            createElement(tagName: "a"): HTMLAnchorElement;
            createElement(tagName: "abbr"): HTMLPhraseElement;
            createElement(tagName: "acronym"): HTMLPhraseElement;
            createElement(tagName: "address"): HTMLBlockElement;
            createElement(tagName: "applet"): HTMLAppletElement;
            createElement(tagName: "area"): HTMLAreaElement;
            createElement(tagName: "article"): HTMLElement;
            createElement(tagName: "aside"): HTMLElement;
            createElement(tagName: "audio"): HTMLAudioElement;
            createElement(tagName: "b"): HTMLPhraseElement;
            createElement(tagName: "base"): HTMLBaseElement;
            createElement(tagName: "basefont"): HTMLBaseFontElement;
            createElement(tagName: "bdo"): HTMLPhraseElement;
            createElement(tagName: "bgsound"): HTMLBGSoundElement;
            createElement(tagName: "big"): HTMLPhraseElement;
            createElement(tagName: "blockquote"): HTMLBlockElement;
            createElement(tagName: "body"): HTMLBodyElement;
            createElement(tagName: "br"): HTMLBRElement;
            createElement(tagName: "button"): HTMLButtonElement;
            createElement(tagName: "canvas"): HTMLCanvasElement;
            createElement(tagName: "caption"): HTMLTableCaptionElement;
            createElement(tagName: "center"): HTMLBlockElement;
            createElement(tagName: "cite"): HTMLPhraseElement;
            createElement(tagName: "code"): HTMLPhraseElement;
            createElement(tagName: "col"): HTMLTableColElement;
            createElement(tagName: "colgroup"): HTMLTableColElement;
            createElement(tagName: "datalist"): HTMLDataListElement;
            createElement(tagName: "dd"): HTMLDDElement;
            createElement(tagName: "del"): HTMLModElement;
            createElement(tagName: "dfn"): HTMLPhraseElement;
            createElement(tagName: "dir"): HTMLDirectoryElement;
            createElement(tagName: "div"): HTMLDivElement;
            createElement(tagName: "dl"): HTMLDListElement;
            createElement(tagName: "dt"): HTMLDTElement;
            createElement(tagName: "em"): HTMLPhraseElement;
            createElement(tagName: "embed"): HTMLEmbedElement;
            createElement(tagName: "fieldset"): HTMLFieldSetElement;
            createElement(tagName: "figcaption"): HTMLElement;
            createElement(tagName: "figure"): HTMLElement;
            createElement(tagName: "font"): HTMLFontElement;
            createElement(tagName: "footer"): HTMLElement;
            createElement(tagName: "form"): HTMLFormElement;
            createElement(tagName: "frame"): HTMLFrameElement;
            createElement(tagName: "frameset"): HTMLFrameSetElement;
            createElement(tagName: "h1"): HTMLHeadingElement;
            createElement(tagName: "h2"): HTMLHeadingElement;
            createElement(tagName: "h3"): HTMLHeadingElement;
            createElement(tagName: "h4"): HTMLHeadingElement;
            createElement(tagName: "h5"): HTMLHeadingElement;
            createElement(tagName: "h6"): HTMLHeadingElement;
            createElement(tagName: "head"): HTMLHeadElement;
            createElement(tagName: "header"): HTMLElement;
            createElement(tagName: "hgroup"): HTMLElement;
            createElement(tagName: "hr"): HTMLHRElement;
            createElement(tagName: "html"): HTMLHtmlElement;
            createElement(tagName: "i"): HTMLPhraseElement;
            createElement(tagName: "iframe"): HTMLIFrameElement;
            createElement(tagName: "img"): HTMLImageElement;
            createElement(tagName: "input"): HTMLInputElement;
            createElement(tagName: "ins"): HTMLModElement;
            createElement(tagName: "isindex"): HTMLIsIndexElement;
            createElement(tagName: "kbd"): HTMLPhraseElement;
            createElement(tagName: "keygen"): HTMLBlockElement;
            createElement(tagName: "label"): HTMLLabelElement;
            createElement(tagName: "legend"): HTMLLegendElement;
            createElement(tagName: "li"): HTMLLIElement;
            createElement(tagName: "link"): HTMLLinkElement;
            createElement(tagName: "listing"): HTMLBlockElement;
            createElement(tagName: "map"): HTMLMapElement;
            createElement(tagName: "mark"): HTMLElement;
            createElement(tagName: "marquee"): HTMLMarqueeElement;
            createElement(tagName: "menu"): HTMLMenuElement;
            createElement(tagName: "meta"): HTMLMetaElement;
            createElement(tagName: "nav"): HTMLElement;
            createElement(tagName: "nextid"): HTMLNextIdElement;
            createElement(tagName: "nobr"): HTMLPhraseElement;
            createElement(tagName: "noframes"): HTMLElement;
            createElement(tagName: "noscript"): HTMLElement;
            createElement(tagName: "object"): HTMLObjectElement;
            createElement(tagName: "ol"): HTMLOListElement;
            createElement(tagName: "optgroup"): HTMLOptGroupElement;
            createElement(tagName: "option"): HTMLOptionElement;
            createElement(tagName: "p"): HTMLParagraphElement;
            createElement(tagName: "param"): HTMLParamElement;
            createElement(tagName: "plaintext"): HTMLBlockElement;
            createElement(tagName: "pre"): HTMLPreElement;
            createElement(tagName: "progress"): HTMLProgressElement;
            createElement(tagName: "q"): HTMLQuoteElement;
            createElement(tagName: "rt"): HTMLPhraseElement;
            createElement(tagName: "ruby"): HTMLPhraseElement;
            createElement(tagName: "s"): HTMLPhraseElement;
            createElement(tagName: "samp"): HTMLPhraseElement;
            createElement(tagName: "script"): HTMLScriptElement;
            createElement(tagName: "section"): HTMLElement;
            createElement(tagName: "select"): HTMLSelectElement;
            createElement(tagName: "small"): HTMLPhraseElement;
            createElement(tagName: "SOURCE"): HTMLSourceElement;
            createElement(tagName: "span"): HTMLSpanElement;
            createElement(tagName: "strike"): HTMLPhraseElement;
            createElement(tagName: "strong"): HTMLPhraseElement;
            createElement(tagName: "style"): HTMLStyleElement;
            createElement(tagName: "sub"): HTMLPhraseElement;
            createElement(tagName: "sup"): HTMLPhraseElement;
            createElement(tagName: "table"): HTMLTableElement;
            createElement(tagName: "tbody"): HTMLTableSectionElement;
            createElement(tagName: "td"): HTMLTableDataCellElement;
            createElement(tagName: "textarea"): HTMLTextAreaElement;
            createElement(tagName: "tfoot"): HTMLTableSectionElement;
            createElement(tagName: "th"): HTMLTableHeaderCellElement;
            createElement(tagName: "thead"): HTMLTableSectionElement;
            createElement(tagName: "title"): HTMLTitleElement;
            createElement(tagName: "tr"): HTMLTableRowElement;
            createElement(tagName: "track"): HTMLTrackElement;
            createElement(tagName: "tt"): HTMLPhraseElement;
            createElement(tagName: "u"): HTMLPhraseElement;
            createElement(tagName: "ul"): HTMLUListElement;
            createElement(tagName: "var"): HTMLPhraseElement;
            createElement(tagName: "video"): HTMLVideoElement;
            createElement(tagName: "wbr"): HTMLElement;
            createElement(tagName: "x-ms-webview"): MSHTMLWebViewElement;
            createElement(tagName: "xmp"): HTMLBlockElement;
            createElement(tagName: string): HTMLElement;
            /**
              * Removes mouse capture from the object in the current document.
              */
            releaseCapture(): void;
            /**
              * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. 
              * @param content The text and HTML tags to write.
              */
            writeln(...content: string[]): void;
            createElementNS(namespaceURI: string, qualifiedName: string): Element;
            /**
              * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method.
              * @param url Specifies a MIME type for the document.
              * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element.
              * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, "fullscreen=yes, toolbar=yes"). The following values are supported.
              * @param replace Specifies whether the existing entry for the document is replaced in the history list.
              */
            open(url?: string, name?: string, features?: string, replace?: boolean): any;
            /**
              * Returns a Boolean value that indicates whether the current command is supported on the current range.
              * @param commandId Specifies a command identifier.
              */
            queryCommandSupported(commandId: string): boolean;
            /**
              * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document.
              * @param root The root element or node to start traversing on.
              * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow.
              * @param filter A custom NodeFilter function to use.
              * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.
              */
            createTreeWalker(root: Node, whatToShow: number, filter: NodeFilter, entityReferenceExpansion: boolean): TreeWalker;
            createAttributeNS(namespaceURI: string, qualifiedName: string): Attr;
            /** 
              * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document.
              * @param commandId Specifies a command identifier.
              */
            queryCommandEnabled(commandId: string): boolean;
            /**
              * Causes the element to receive the focus and executes the code specified by the onfocus event.
              */
            focus(): void;
            /**
              * Closes an output stream and forces the sent data to display.
              */
            close(): void;
            getElementsByClassName(classNames: string): NodeList;
            importNode(importedNode: Node, deep: boolean): Node;
            /**
              *  Returns an empty range object that has both of its boundary points positioned at the beginning of the document. 
              */
            createRange(): Range;
            /**
              * Fires a specified event on the object.
              * @param eventName Specifies the name of the event to fire.
              * @param eventObj Object that specifies the event object from which to obtain event object properties.
              */
            fireEvent(eventName: string, eventObj?: any): boolean;
            /**
              * Creates a comment object with the specified data.
              * @param data Sets the comment object's data.
              */
            createComment(data: string): Comment;
            /**
              * Retrieves a collection of objects based on the specified element name.
              * @param name Specifies the name of an element.
              */
            getElementsByTagName(name: "a"): NodeListOf<HTMLAnchorElement>;
            getElementsByTagName(name: "abbr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "acronym"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "address"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "applet"): NodeListOf<HTMLAppletElement>;
            getElementsByTagName(name: "area"): NodeListOf<HTMLAreaElement>;
            getElementsByTagName(name: "article"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "aside"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "audio"): NodeListOf<HTMLAudioElement>;
            getElementsByTagName(name: "b"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "base"): NodeListOf<HTMLBaseElement>;
            getElementsByTagName(name: "basefont"): NodeListOf<HTMLBaseFontElement>;
            getElementsByTagName(name: "bdo"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "bgsound"): NodeListOf<HTMLBGSoundElement>;
            getElementsByTagName(name: "big"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "blockquote"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "body"): NodeListOf<HTMLBodyElement>;
            getElementsByTagName(name: "br"): NodeListOf<HTMLBRElement>;
            getElementsByTagName(name: "button"): NodeListOf<HTMLButtonElement>;
            getElementsByTagName(name: "canvas"): NodeListOf<HTMLCanvasElement>;
            getElementsByTagName(name: "caption"): NodeListOf<HTMLTableCaptionElement>;
            getElementsByTagName(name: "center"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "cite"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "code"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "col"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "colgroup"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "datalist"): NodeListOf<HTMLDataListElement>;
            getElementsByTagName(name: "dd"): NodeListOf<HTMLDDElement>;
            getElementsByTagName(name: "del"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "dfn"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "dir"): NodeListOf<HTMLDirectoryElement>;
            getElementsByTagName(name: "div"): NodeListOf<HTMLDivElement>;
            getElementsByTagName(name: "dl"): NodeListOf<HTMLDListElement>;
            getElementsByTagName(name: "dt"): NodeListOf<HTMLDTElement>;
            getElementsByTagName(name: "em"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "embed"): NodeListOf<HTMLEmbedElement>;
            getElementsByTagName(name: "fieldset"): NodeListOf<HTMLFieldSetElement>;
            getElementsByTagName(name: "figcaption"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "figure"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "font"): NodeListOf<HTMLFontElement>;
            getElementsByTagName(name: "footer"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "form"): NodeListOf<HTMLFormElement>;
            getElementsByTagName(name: "frame"): NodeListOf<HTMLFrameElement>;
            getElementsByTagName(name: "frameset"): NodeListOf<HTMLFrameSetElement>;
            getElementsByTagName(name: "h1"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h2"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h3"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h4"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h5"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h6"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "head"): NodeListOf<HTMLHeadElement>;
            getElementsByTagName(name: "header"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hgroup"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hr"): NodeListOf<HTMLHRElement>;
            getElementsByTagName(name: "html"): NodeListOf<HTMLHtmlElement>;
            getElementsByTagName(name: "i"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "iframe"): NodeListOf<HTMLIFrameElement>;
            getElementsByTagName(name: "img"): NodeListOf<HTMLImageElement>;
            getElementsByTagName(name: "input"): NodeListOf<HTMLInputElement>;
            getElementsByTagName(name: "ins"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "isindex"): NodeListOf<HTMLIsIndexElement>;
            getElementsByTagName(name: "kbd"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "keygen"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "label"): NodeListOf<HTMLLabelElement>;
            getElementsByTagName(name: "legend"): NodeListOf<HTMLLegendElement>;
            getElementsByTagName(name: "li"): NodeListOf<HTMLLIElement>;
            getElementsByTagName(name: "link"): NodeListOf<HTMLLinkElement>;
            getElementsByTagName(name: "listing"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "map"): NodeListOf<HTMLMapElement>;
            getElementsByTagName(name: "mark"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "marquee"): NodeListOf<HTMLMarqueeElement>;
            getElementsByTagName(name: "menu"): NodeListOf<HTMLMenuElement>;
            getElementsByTagName(name: "meta"): NodeListOf<HTMLMetaElement>;
            getElementsByTagName(name: "nav"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "nextid"): NodeListOf<HTMLNextIdElement>;
            getElementsByTagName(name: "nobr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "noframes"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "noscript"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "object"): NodeListOf<HTMLObjectElement>;
            getElementsByTagName(name: "ol"): NodeListOf<HTMLOListElement>;
            getElementsByTagName(name: "optgroup"): NodeListOf<HTMLOptGroupElement>;
            getElementsByTagName(name: "option"): NodeListOf<HTMLOptionElement>;
            getElementsByTagName(name: "p"): NodeListOf<HTMLParagraphElement>;
            getElementsByTagName(name: "param"): NodeListOf<HTMLParamElement>;
            getElementsByTagName(name: "plaintext"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "pre"): NodeListOf<HTMLPreElement>;
            getElementsByTagName(name: "progress"): NodeListOf<HTMLProgressElement>;
            getElementsByTagName(name: "q"): NodeListOf<HTMLQuoteElement>;
            getElementsByTagName(name: "rt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ruby"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "s"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "samp"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "script"): NodeListOf<HTMLScriptElement>;
            getElementsByTagName(name: "section"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "select"): NodeListOf<HTMLSelectElement>;
            getElementsByTagName(name: "small"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "SOURCE"): NodeListOf<HTMLSourceElement>;
            getElementsByTagName(name: "span"): NodeListOf<HTMLSpanElement>;
            getElementsByTagName(name: "strike"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "strong"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "style"): NodeListOf<HTMLStyleElement>;
            getElementsByTagName(name: "sub"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "sup"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "table"): NodeListOf<HTMLTableElement>;
            getElementsByTagName(name: "tbody"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "td"): NodeListOf<HTMLTableDataCellElement>;
            getElementsByTagName(name: "textarea"): NodeListOf<HTMLTextAreaElement>;
            getElementsByTagName(name: "tfoot"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "th"): NodeListOf<HTMLTableHeaderCellElement>;
            getElementsByTagName(name: "thead"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "title"): NodeListOf<HTMLTitleElement>;
            getElementsByTagName(name: "tr"): NodeListOf<HTMLTableRowElement>;
            getElementsByTagName(name: "track"): NodeListOf<HTMLTrackElement>;
            getElementsByTagName(name: "tt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "u"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ul"): NodeListOf<HTMLUListElement>;
            getElementsByTagName(name: "var"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "video"): NodeListOf<HTMLVideoElement>;
            getElementsByTagName(name: "wbr"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "x-ms-webview"): NodeListOf<MSHTMLWebViewElement>;
            getElementsByTagName(name: "xmp"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: string): NodeList;
            /**
              * Creates a new document.
              */
            createDocumentFragment(): DocumentFragment;
            /**
              * Creates a style sheet for the document. 
              * @param href Specifies how to add the style sheet to the document. If a file name is specified for the URL, the style information is added as a link object. If the URL contains style information, it is added to the style object.
              * @param index Specifies the index that indicates where the new style sheet is inserted in the styleSheets collection. The default is to insert the new style sheet at the end of the collection.
              */
            createStyleSheet(href?: string, index?: number): CSSStyleSheet;
            /**
              * Gets a collection of objects based on the value of the NAME or ID attribute.
              * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute.
              */
            getElementsByName(elementName: string): NodeList;
            /**
              * Returns a Boolean value that indicates the current state of the command.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandState(commandId: string): boolean;
            /**
              * Gets a value indicating whether the object currently has focus.
              */
            hasFocus(): boolean;
            /**
              * Displays help information for the given command identifier.
              * @param commandId Displays help information for the given command identifier.
              */
            execCommandShowHelp(commandId: string): boolean;
            /**
              * Creates an attribute object with a specified name.
              * @param name String that sets the attribute object's name.
              */
            createAttribute(name: string): Attr;
            /**
              * Creates a text string from the specified value. 
              * @param data String that specifies the nodeValue property of the text node.
              */
            createTextNode(data: string): Text;
            /**
              * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. 
              * @param root The root element or node to start traversing on.
              * @param whatToShow The type of nodes or elements to appear in the node list
              * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter.
              * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.
              */
            createNodeIterator(root: Node, whatToShow: number, filter: NodeFilter, entityReferenceExpansion: boolean): NodeIterator;
            /**
              * Generates an event object to pass event context information when you use the fireEvent method.
              * @param eventObj An object that specifies an existing event object on which to base the new object.
              */
            createEventObject(eventObj?: any): MSEventObj;
            /**
              * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage.
              */
            getSelection(): Selection;
            msElementsFromPoint(x: number, y: number): NodeList;
            msElementsFromRect(left: number, top: number, width: number, height: number): NodeList;
            clear(): void;
            msExitFullscreen(): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "msthumbnailclick", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stop", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mssitemodejumplistitemremoved", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectionchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "storagecommit", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msfullscreenerror", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msfullscreenchange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var Document: {
            prototype: Document;
            new(): Document;
        }
        
        interface Console {
            info(message?: any, ...optionalParams: any[]): void;
            warn(message?: any, ...optionalParams: any[]): void;
            error(message?: any, ...optionalParams: any[]): void;
            log(message?: any, ...optionalParams: any[]): void;
            profile(reportName?: string): void;
            assert(test?: boolean, message?: string, ...optionalParams: any[]): void;
            msIsIndependentlyComposed(element: Element): boolean;
            clear(): void;
            dir(value?: any, ...optionalParams: any[]): void;
            profileEnd(): void;
            count(countTitle?: string): void;
            groupEnd(): void;
            time(timerName?: string): void;
            timeEnd(timerName?: string): void;
            trace(): void;
            group(groupTitle?: string): void;
            dirxml(value: any): void;
            debug(message?: string, ...optionalParams: any[]): void;
            groupCollapsed(groupTitle?: string): void;
            select(element: Element): void;
        }
        declare var Console: {
            prototype: Console;
            new(): Console;
        }
        
        interface MSEventObj extends Event {
            nextPage: string;
            keyCode: number;
            toElement: Element;
            returnValue: any;
            dataFld: string;
            y: number;
            dataTransfer: DataTransfer;
            propertyName: string;
            url: string;
            offsetX: number;
            recordset: any;
            screenX: number;
            buttonID: number;
            wheelDelta: number;
            reason: number;
            origin: string;
            data: string;
            srcFilter: any;
            boundElements: HTMLCollection;
            cancelBubble: boolean;
            altLeft: boolean;
            behaviorCookie: number;
            bookmarks: BookmarkCollection;
            type: string;
            repeat: boolean;
            srcElement: Element;
            source: Window;
            fromElement: Element;
            offsetY: number;
            x: number;
            behaviorPart: number;
            qualifier: string;
            altKey: boolean;
            ctrlKey: boolean;
            clientY: number;
            shiftKey: boolean;
            shiftLeft: boolean;
            contentOverflow: boolean;
            screenY: number;
            ctrlLeft: boolean;
            button: number;
            srcUrn: string;
            clientX: number;
            actionURL: string;
            getAttribute(strAttributeName: string, lFlags?: number): any;
            setAttribute(strAttributeName: string, AttributeValue: any, lFlags?: number): void;
            removeAttribute(strAttributeName: string, lFlags?: number): boolean;
        }
        declare var MSEventObj: {
            prototype: MSEventObj;
            new(): MSEventObj;
        }
        
        interface HTMLCanvasElement extends HTMLElement {
            /**
              * Gets or sets the width of a canvas element on a document.
              */
            width: number;
            /**
              * Gets or sets the height of a canvas element on a document.
              */
            height: number;
            /**
              * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.
              * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl");
              */
            getContext(contextId: "2d"): CanvasRenderingContext2D;
            /**
              * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.
              * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl");
              */
            getContext(contextId: "experimental-webgl"): WebGLRenderingContext;
            /**
              * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.
              * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl");
              */
            getContext(contextId: string, ...args: any[]): any;
            /**
              * Returns the content of the current canvas as an image that you can use as a source for another canvas or an HTML element.
              * @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.
              */
            toDataURL(type?: string, ...args: any[]): string;
            /**
              * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing.
              */
            msToBlob(): Blob;
        }
        declare var HTMLCanvasElement: {
            prototype: HTMLCanvasElement;
            new(): HTMLCanvasElement;
        }
        
        interface Window extends EventTarget, MSEventAttachmentTarget, WindowLocalStorage, MSWindowExtensions, WindowSessionStorage, WindowTimers, WindowBase64, IDBEnvironment, WindowConsole, GlobalEventHandlers {
            ondragend: (ev: DragEvent) => any;
            onkeydown: (ev: KeyboardEvent) => any;
            ondragover: (ev: DragEvent) => any;
            onkeyup: (ev: KeyboardEvent) => any;
            onreset: (ev: Event) => any;
            onmouseup: (ev: MouseEvent) => any;
            ondragstart: (ev: DragEvent) => any;
            ondrag: (ev: DragEvent) => any;
            screenX: number;
            onmouseover: (ev: MouseEvent) => any;
            ondragleave: (ev: DragEvent) => any;
            history: History;
            pageXOffset: number;
            name: string;
            onafterprint: (ev: Event) => any;
            onpause: (ev: Event) => any;
            onbeforeprint: (ev: Event) => any;
            top: Window;
            onmousedown: (ev: MouseEvent) => any;
            onseeked: (ev: Event) => any;
            opener: Window;
            onclick: (ev: MouseEvent) => any;
            innerHeight: number;
            onwaiting: (ev: Event) => any;
            ononline: (ev: Event) => any;
            ondurationchange: (ev: Event) => any;
            frames: Window;
            onblur: (ev: FocusEvent) => any;
            onemptied: (ev: Event) => any;
            onseeking: (ev: Event) => any;
            oncanplay: (ev: Event) => any;
            outerWidth: number;
            onstalled: (ev: Event) => any;
            onmousemove: (ev: MouseEvent) => any;
            innerWidth: number;
            onoffline: (ev: Event) => any;
            length: number;
            screen: Screen;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            onratechange: (ev: Event) => any;
            onstorage: (ev: StorageEvent) => any;
            onloadstart: (ev: Event) => any;
            ondragenter: (ev: DragEvent) => any;
            onsubmit: (ev: Event) => any;
            self: Window;
            document: Document;
            onprogress: (ev: ProgressEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            pageYOffset: number;
            oncontextmenu: (ev: MouseEvent) => any;
            onchange: (ev: Event) => any;
            onloadedmetadata: (ev: Event) => any;
            onplay: (ev: Event) => any;
            onerror: ErrorEventHandler;
            onplaying: (ev: Event) => any;
            parent: Window;
            location: Location;
            oncanplaythrough: (ev: Event) => any;
            onabort: (ev: UIEvent) => any;
            onreadystatechange: (ev: Event) => any;
            outerHeight: number;
            onkeypress: (ev: KeyboardEvent) => any;
            frameElement: Element;
            onloadeddata: (ev: Event) => any;
            onsuspend: (ev: Event) => any;
            window: Window;
            onfocus: (ev: FocusEvent) => any;
            onmessage: (ev: MessageEvent) => any;
            ontimeupdate: (ev: Event) => any;
            onresize: (ev: UIEvent) => any;
            onselect: (ev: UIEvent) => any;
            navigator: Navigator;
            styleMedia: StyleMedia;
            ondrop: (ev: DragEvent) => any;
            onmouseout: (ev: MouseEvent) => any;
            onended: (ev: Event) => any;
            onhashchange: (ev: Event) => any;
            onunload: (ev: Event) => any;
            onscroll: (ev: UIEvent) => any;
            screenY: number;
            onmousewheel: (ev: MouseWheelEvent) => any;
            onload: (ev: Event) => any;
            onvolumechange: (ev: Event) => any;
            oninput: (ev: Event) => any;
            performance: Performance;
            onmspointerdown: (ev: any) => any;
            animationStartTime: number;
            onmsgesturedoubletap: (ev: any) => any;
            onmspointerhover: (ev: any) => any;
            onmsgesturehold: (ev: any) => any;
            onmspointermove: (ev: any) => any;
            onmsgesturechange: (ev: any) => any;
            onmsgesturestart: (ev: any) => any;
            onmspointercancel: (ev: any) => any;
            onmsgestureend: (ev: any) => any;
            onmsgesturetap: (ev: any) => any;
            onmspointerout: (ev: any) => any;
            msAnimationStartTime: number;
            applicationCache: ApplicationCache;
            onmsinertiastart: (ev: any) => any;
            onmspointerover: (ev: any) => any;
            onpopstate: (ev: PopStateEvent) => any;
            onmspointerup: (ev: any) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            ondevicemotion: (ev: DeviceMotionEvent) => any;
            devicePixelRatio: number;
            msCrypto: Crypto;
            ondeviceorientation: (ev: DeviceOrientationEvent) => any;
            doNotTrack: string;
            onmspointerenter: (ev: any) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            onmspointerleave: (ev: any) => any;
            alert(message?: any): void;
            scroll(x?: number, y?: number): void;
            focus(): void;
            scrollTo(x?: number, y?: number): void;
            print(): void;
            prompt(message?: string, _default?: string): string;
            toString(): string;
            open(url?: string, target?: string, features?: string, replace?: boolean): Window;
            scrollBy(x?: number, y?: number): void;
            confirm(message?: string): boolean;
            close(): void;
            postMessage(message: any, targetOrigin: string, ports?: any): void;
            showModalDialog(url?: string, argument?: any, options?: any): any;
            blur(): void;
            getSelection(): Selection;
            getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
            msCancelRequestAnimationFrame(handle: number): void;
            matchMedia(mediaQuery: string): MediaQueryList;
            cancelAnimationFrame(handle: number): void;
            msIsStaticHTML(html: string): boolean;
            msMatchMedia(mediaQuery: string): MediaQueryList;
            requestAnimationFrame(callback: FrameRequestCallback): number;
            msRequestAnimationFrame(callback: FrameRequestCallback): number;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var Window: {
            prototype: Window;
            new(): Window;
        }
        
        interface HTMLCollection extends MSHTMLCollectionExtensions {
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Retrieves an object from various collections.
              */
            item(nameOrIndex?: any, optionalIndex?: any): Element;
            /**
              * Retrieves a select object or an object from an options collection.
              */
            namedItem(name: string): Element;
            // [name: string]: Element;
            [index: number]: Element;
        }
        declare var HTMLCollection: {
            prototype: HTMLCollection;
            new(): HTMLCollection;
        }
        
        interface BlobPropertyBag {
            type?: string;
            endings?: string;
        }
        
        interface Blob {
            type: string;
            size: number;
            msDetachStream(): any;
            slice(start?: number, end?: number, contentType?: string): Blob;
            msClose(): void;
        }
        declare var Blob: {
            prototype: Blob;
            new (blobParts?: any[], options?: BlobPropertyBag): Blob;
        }
        
        interface NavigatorID {
            appVersion: string;
            appName: string;
            userAgent: string;
            platform: string;
            product: string;
            vendor: string;
        }
        
        interface HTMLTableElement extends HTMLElement, MSDataBindingTableExtensions, MSDataBindingExtensions, DOML2DeprecatedBackgroundStyle, DOML2DeprecatedBackgroundColorStyle {
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorLight: any;
            /**
              * Sets or retrieves the amount of space between cells in a table.
              */
            cellSpacing: string;
            /**
              * Retrieves the tFoot object of the table.
              */
            tFoot: HTMLTableSectionElement;
            /**
              * Sets or retrieves the way the border frame around the table is displayed.
              */
            frame: string;
            /**
              * Sets or retrieves the border color of the object. 
              */
            borderColor: any;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: HTMLCollection;
            /**
              * Sets or retrieves which dividing lines (inner borders) are displayed.
              */
            rules: string;
            /**
              * Sets or retrieves the number of columns in the table.
              */
            cols: number;
            /**
              * Sets or retrieves a description and/or structure of the object.
              */
            summary: string;
            /**
              * Retrieves the caption object of a table.
              */
            caption: HTMLTableCaptionElement;
            /**
              * Retrieves a collection of all tBody objects in the table. Objects in this collection are in source order.
              */
            tBodies: HTMLCollection;
            /**
              * Retrieves the tHead object of the table.
              */
            tHead: HTMLTableSectionElement;
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
            /**
              * Retrieves a collection of all cells in the table row or in the entire table.
              */
            cells: HTMLCollection;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Sets or retrieves the amount of space between the border of the cell and the content of the cell.
              */
            cellPadding: string;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            border: string;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorDark: any;
            /**
              * Removes the specified row (tr) from the element and from the rows collection.
              * @param index Number that specifies the zero-based position in the rows collection of the row to remove.
              */
            deleteRow(index?: number): void;
            /**
              * Creates an empty tBody element in the table.
              */
            createTBody(): HTMLElement;
            /**
              * Deletes the caption element and its contents from the table.
              */
            deleteCaption(): void;
            /**
              * Creates a new row (tr) in the table, and adds the row to the rows collection.
              * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
              */
            insertRow(index?: number): HTMLElement;
            /**
              * Deletes the tFoot element and its contents from the table.
              */
            deleteTFoot(): void;
            /**
              * Returns the tHead element object if successful, or null otherwise.
              */
            createTHead(): HTMLElement;
            /**
              * Deletes the tHead element and its contents from the table.
              */
            deleteTHead(): void;
            /**
              * Creates an empty caption element in the table.
              */
            createCaption(): HTMLElement;
            /**
              * Moves a table row to a new position.
              * @param indexFrom Number that specifies the index in the rows collection of the table row that is moved.
              * @param indexTo Number that specifies where the row is moved within the rows collection.
              */
            moveRow(indexFrom?: number, indexTo?: number): any;
            /**
              * Creates an empty tFoot element in the table.
              */
            createTFoot(): HTMLElement;
        }
        declare var HTMLTableElement: {
            prototype: HTMLTableElement;
            new(): HTMLTableElement;
        }
        
        interface TreeWalker {
            whatToShow: number;
            filter: NodeFilter;
            root: Node;
            currentNode: Node;
            expandEntityReferences: boolean;
            previousSibling(): Node;
            lastChild(): Node;
            nextSibling(): Node;
            nextNode(): Node;
            parentNode(): Node;
            firstChild(): Node;
            previousNode(): Node;
        }
        declare var TreeWalker: {
            prototype: TreeWalker;
            new(): TreeWalker;
        }
        
        interface GetSVGDocument {
            getSVGDocument(): Document;
        }
        
        interface SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {
            y: number;
            y1: number;
            x: number;
            x1: number;
        }
        declare var SVGPathSegCurvetoQuadraticRel: {
            prototype: SVGPathSegCurvetoQuadraticRel;
            new(): SVGPathSegCurvetoQuadraticRel;
        }
        
        interface Performance {
            navigation: PerformanceNavigation;
            timing: PerformanceTiming;
            getEntriesByType(entryType: string): any;
            toJSON(): any;
            getMeasures(measureName?: string): any;
            clearMarks(markName?: string): void;
            getMarks(markName?: string): any;
            clearResourceTimings(): void;
            mark(markName: string): void;
            measure(measureName: string, startMarkName?: string, endMarkName?: string): void;
            getEntriesByName(name: string, entryType?: string): any;
            getEntries(): any;
            clearMeasures(measureName?: string): void;
            setResourceTimingBufferSize(maxSize: number): void;
            now(): number;
        }
        declare var Performance: {
            prototype: Performance;
            new(): Performance;
        }
        
        interface MSDataBindingTableExtensions {
            dataPageSize: number;
            nextPage(): void;
            firstPage(): void;
            refresh(): void;
            previousPage(): void;
            lastPage(): void;
        }
        
        interface CompositionEvent extends UIEvent {
            data: string;
            locale: string;
            initCompositionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, locale: string): void;
        }
        declare var CompositionEvent: {
            prototype: CompositionEvent;
            new(): CompositionEvent;
        }
        
        interface WindowTimers extends WindowTimersExtension {
            clearTimeout(handle: number): void;
            setTimeout(handler: any, timeout?: any, ...args: any[]): number;
            clearInterval(handle: number): void;
            setInterval(handler: any, timeout?: any, ...args: any[]): number;
        }
        
        interface SVGMarkerElement extends SVGElement, SVGStylable, SVGLangSpace, SVGFitToViewBox, SVGExternalResourcesRequired {
            orientType: SVGAnimatedEnumeration;
            markerUnits: SVGAnimatedEnumeration;
            markerWidth: SVGAnimatedLength;
            markerHeight: SVGAnimatedLength;
            orientAngle: SVGAnimatedAngle;
            refY: SVGAnimatedLength;
            refX: SVGAnimatedLength;
            setOrientToAngle(angle: SVGAngle): void;
            setOrientToAuto(): void;
            SVG_MARKER_ORIENT_UNKNOWN: number;
            SVG_MARKER_ORIENT_ANGLE: number;
            SVG_MARKERUNITS_UNKNOWN: number;
            SVG_MARKERUNITS_STROKEWIDTH: number;
            SVG_MARKER_ORIENT_AUTO: number;
            SVG_MARKERUNITS_USERSPACEONUSE: number;
        }
        declare var SVGMarkerElement: {
            prototype: SVGMarkerElement;
            new(): SVGMarkerElement;
            SVG_MARKER_ORIENT_UNKNOWN: number;
            SVG_MARKER_ORIENT_ANGLE: number;
            SVG_MARKERUNITS_UNKNOWN: number;
            SVG_MARKERUNITS_STROKEWIDTH: number;
            SVG_MARKER_ORIENT_AUTO: number;
            SVG_MARKERUNITS_USERSPACEONUSE: number;
        }
        
        interface CSSStyleDeclaration {
            backgroundAttachment: string;
            visibility: string;
            textAlignLast: string;
            borderRightStyle: string;
            counterIncrement: string;
            orphans: string;
            cssText: string;
            borderStyle: string;
            pointerEvents: string;
            borderTopColor: string;
            markerEnd: string;
            textIndent: string;
            listStyleImage: string;
            cursor: string;
            listStylePosition: string;
            wordWrap: string;
            borderTopStyle: string;
            alignmentBaseline: string;
            opacity: string;
            direction: string;
            strokeMiterlimit: string;
            maxWidth: string;
            color: string;
            clip: string;
            borderRightWidth: string;
            verticalAlign: string;
            overflow: string;
            mask: string;
            borderLeftStyle: string;
            emptyCells: string;
            stopOpacity: string;
            paddingRight: string;
            parentRule: CSSRule;
            background: string;
            boxSizing: string;
            textJustify: string;
            height: string;
            paddingTop: string;
            length: number;
            right: string;
            baselineShift: string;
            borderLeft: string;
            widows: string;
            lineHeight: string;
            left: string;
            textUnderlinePosition: string;
            glyphOrientationHorizontal: string;
            display: string;
            textAnchor: string;
            cssFloat: string;
            strokeDasharray: string;
            rubyAlign: string;
            fontSizeAdjust: string;
            borderLeftColor: string;
            backgroundImage: string;
            listStyleType: string;
            strokeWidth: string;
            textOverflow: string;
            fillRule: string;
            borderBottomColor: string;
            zIndex: string;
            position: string;
            listStyle: string;
            msTransformOrigin: string;
            dominantBaseline: string;
            overflowY: string;
            fill: string;
            captionSide: string;
            borderCollapse: string;
            boxShadow: string;
            quotes: string;
            tableLayout: string;
            unicodeBidi: string;
            borderBottomWidth: string;
            backgroundSize: string;
            textDecoration: string;
            strokeDashoffset: string;
            fontSize: string;
            border: string;
            pageBreakBefore: string;
            borderTopRightRadius: string;
            msTransform: string;
            borderBottomLeftRadius: string;
            textTransform: string;
            rubyPosition: string;
            strokeLinejoin: string;
            clipPath: string;
            borderRightColor: string;
            fontFamily: string;
            clear: string;
            content: string;
            backgroundClip: string;
            marginBottom: string;
            counterReset: string;
            outlineWidth: string;
            marginRight: string;
            paddingLeft: string;
            borderBottom: string;
            wordBreak: string;
            marginTop: string;
            top: string;
            fontWeight: string;
            borderRight: string;
            width: string;
            kerning: string;
            pageBreakAfter: string;
            borderBottomStyle: string;
            fontStretch: string;
            padding: string;
            strokeOpacity: string;
            markerStart: string;
            bottom: string;
            borderLeftWidth: string;
            clipRule: string;
            backgroundPosition: string;
            backgroundColor: string;
            pageBreakInside: string;
            backgroundOrigin: string;
            strokeLinecap: string;
            borderTopWidth: string;
            outlineStyle: string;
            borderTop: string;
            outlineColor: string;
            paddingBottom: string;
            marginLeft: string;
            font: string;
            outline: string;
            wordSpacing: string;
            maxHeight: string;
            fillOpacity: string;
            letterSpacing: string;
            borderSpacing: string;
            backgroundRepeat: string;
            borderRadius: string;
            borderWidth: string;
            borderBottomRightRadius: string;
            whiteSpace: string;
            fontStyle: string;
            minWidth: string;
            stopColor: string;
            borderTopLeftRadius: string;
            borderColor: string;
            marker: string;
            glyphOrientationVertical: string;
            markerMid: string;
            fontVariant: string;
            minHeight: string;
            stroke: string;
            rubyOverhang: string;
            overflowX: string;
            textAlign: string;
            margin: string;
            animationFillMode: string;
            floodColor: string;
            animationIterationCount: string;
            textShadow: string;
            backfaceVisibility: string;
            msAnimationIterationCount: string;
            animationDelay: string;
            animationTimingFunction: string;
            columnWidth: any;
            msScrollSnapX: string;
            columnRuleColor: any;
            columnRuleWidth: any;
            transitionDelay: string;
            transition: string;
            msFlowFrom: string;
            msScrollSnapType: string;
            msContentZoomSnapType: string;
            msGridColumns: string;
            msAnimationName: string;
            msGridRowAlign: string;
            msContentZoomChaining: string;
            msGridColumn: any;
            msHyphenateLimitZone: any;
            msScrollRails: string;
            msAnimationDelay: string;
            enableBackground: string;
            msWrapThrough: string;
            columnRuleStyle: string;
            msAnimation: string;
            msFlexFlow: string;
            msScrollSnapY: string;
            msHyphenateLimitLines: any;
            msTouchAction: string;
            msScrollLimit: string;
            animation: string;
            transform: string;
            filter: string;
            colorInterpolationFilters: string;
            transitionTimingFunction: string;
            msBackfaceVisibility: string;
            animationPlayState: string;
            transformOrigin: string;
            msScrollLimitYMin: any;
            msFontFeatureSettings: string;
            msContentZoomLimitMin: any;
            columnGap: any;
            transitionProperty: string;
            msAnimationDuration: string;
            msAnimationFillMode: string;
            msFlexDirection: string;
            msTransitionDuration: string;
            fontFeatureSettings: string;
            breakBefore: string;
            msFlexWrap: string;
            perspective: string;
            msFlowInto: string;
            msTransformStyle: string;
            msScrollTranslation: string;
            msTransitionProperty: string;
            msUserSelect: string;
            msOverflowStyle: string;
            msScrollSnapPointsY: string;
            animationDirection: string;
            animationDuration: string;
            msFlex: string;
            msTransitionTimingFunction: string;
            animationName: string;
            columnRule: string;
            msGridColumnSpan: any;
            msFlexNegative: string;
            columnFill: string;
            msGridRow: any;
            msFlexOrder: string;
            msFlexItemAlign: string;
            msFlexPositive: string;
            msContentZoomLimitMax: any;
            msScrollLimitYMax: any;
            msGridColumnAlign: string;
            perspectiveOrigin: string;
            lightingColor: string;
            columns: string;
            msScrollChaining: string;
            msHyphenateLimitChars: string;
            msTouchSelect: string;
            floodOpacity: string;
            msAnimationDirection: string;
            msAnimationPlayState: string;
            columnSpan: string;
            msContentZooming: string;
            msPerspective: string;
            msFlexPack: string;
            msScrollSnapPointsX: string;
            msContentZoomSnapPoints: string;
            msGridRowSpan: any;
            msContentZoomSnap: string;
            msScrollLimitXMin: any;
            breakInside: string;
            msHighContrastAdjust: string;
            msFlexLinePack: string;
            msGridRows: string;
            transitionDuration: string;
            msHyphens: string;
            breakAfter: string;
            msTransition: string;
            msPerspectiveOrigin: string;
            msContentZoomLimit: string;
            msScrollLimitXMax: any;
            msFlexAlign: string;
            msWrapMargin: any;
            columnCount: any;
            msAnimationTimingFunction: string;
            msTransitionDelay: string;
            transformStyle: string;
            msWrapFlow: string;
            msFlexPreferredSize: string;
            alignItems: string;
            borderImageSource: string;
            flexBasis: string;
            borderImageWidth: string;
            borderImageRepeat: string;
            order: string;
            flex: string;
            alignContent: string;
            msImeAlign: string;
            flexShrink: string;
            flexGrow: string;
            borderImageSlice: string;
            flexWrap: string;
            borderImageOutset: string;
            flexDirection: string;
            touchAction: string;
            flexFlow: string;
            borderImage: string;
            justifyContent: string;
            alignSelf: string;
            msTextCombineHorizontal: string;
            getPropertyPriority(propertyName: string): string;
            getPropertyValue(propertyName: string): string;
            removeProperty(propertyName: string): string;
            item(index: number): string;
            [index: number]: string;
            setProperty(propertyName: string, value: string, priority?: string): void;
        }
        declare var CSSStyleDeclaration: {
            prototype: CSSStyleDeclaration;
            new(): CSSStyleDeclaration;
        }
        
        interface SVGGElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
        }
        declare var SVGGElement: {
            prototype: SVGGElement;
            new(): SVGGElement;
        }
        
        interface MSStyleCSSProperties extends MSCSSProperties {
            pixelWidth: number;
            posHeight: number;
            posLeft: number;
            pixelTop: number;
            pixelBottom: number;
            textDecorationNone: boolean;
            pixelLeft: number;
            posTop: number;
            posBottom: number;
            textDecorationOverline: boolean;
            posWidth: number;
            textDecorationLineThrough: boolean;
            pixelHeight: number;
            textDecorationBlink: boolean;
            posRight: number;
            pixelRight: number;
            textDecorationUnderline: boolean;
        }
        declare var MSStyleCSSProperties: {
            prototype: MSStyleCSSProperties;
            new(): MSStyleCSSProperties;
        }
        
        interface Navigator extends NavigatorID, NavigatorOnLine, NavigatorContentUtils, MSNavigatorExtensions, NavigatorGeolocation, MSNavigatorDoNotTrack, NavigatorStorageUtils, MSFileSaver {
            msMaxTouchPoints: number;
            msPointerEnabled: boolean;
            msManipulationViewsEnabled: boolean;
            pointerEnabled: boolean;
            maxTouchPoints: number;
            msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
        }
        declare var Navigator: {
            prototype: Navigator;
            new(): Navigator;
        }
        
        interface SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {
            y: number;
            x2: number;
            x: number;
            y2: number;
        }
        declare var SVGPathSegCurvetoCubicSmoothAbs: {
            prototype: SVGPathSegCurvetoCubicSmoothAbs;
            new(): SVGPathSegCurvetoCubicSmoothAbs;
        }
        
        interface SVGZoomEvent extends UIEvent {
            zoomRectScreen: SVGRect;
            previousScale: number;
            newScale: number;
            previousTranslate: SVGPoint;
            newTranslate: SVGPoint;
        }
        declare var SVGZoomEvent: {
            prototype: SVGZoomEvent;
            new(): SVGZoomEvent;
        }
        
        interface NodeSelector {
            querySelectorAll(selectors: string): NodeList;
            querySelector(selectors: string): Element;
        }
        
        interface HTMLTableDataCellElement extends HTMLTableCellElement {
        }
        declare var HTMLTableDataCellElement: {
            prototype: HTMLTableDataCellElement;
            new(): HTMLTableDataCellElement;
        }
        
        interface HTMLBaseElement extends HTMLElement {
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Gets or sets the baseline URL on which relative links are based.
              */
            href: string;
        }
        declare var HTMLBaseElement: {
            prototype: HTMLBaseElement;
            new(): HTMLBaseElement;
        }
        
        interface ClientRect {
            left: number;
            width: number;
            right: number;
            top: number;
            bottom: number;
            height: number;
        }
        declare var ClientRect: {
            prototype: ClientRect;
            new(): ClientRect;
        }
        
        interface PositionErrorCallback {
            (error: PositionError): void;
        }
        
        interface DOMImplementation {
            createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType;
            createDocument(namespaceURI: string, qualifiedName: string, doctype: DocumentType): Document;
            hasFeature(feature: string, version?: string): boolean;
            createHTMLDocument(title: string): Document;
        }
        declare var DOMImplementation: {
            prototype: DOMImplementation;
            new(): DOMImplementation;
        }
        
        interface SVGUnitTypes {
            SVG_UNIT_TYPE_UNKNOWN: number;
            SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: number;
            SVG_UNIT_TYPE_USERSPACEONUSE: number;
        }
        declare var SVGUnitTypes: SVGUnitTypes;
        
        interface Element extends Node, NodeSelector, ElementTraversal, GlobalEventHandlers {
            scrollTop: number;
            clientLeft: number;
            scrollLeft: number;
            tagName: string;
            clientWidth: number;
            scrollWidth: number;
            clientHeight: number;
            clientTop: number;
            scrollHeight: number;
            msRegionOverflow: string;
            onmspointerdown: (ev: any) => any;
            onmsgotpointercapture: (ev: any) => any;
            onmsgesturedoubletap: (ev: any) => any;
            onmspointerhover: (ev: any) => any;
            onmsgesturehold: (ev: any) => any;
            onmspointermove: (ev: any) => any;
            onmsgesturechange: (ev: any) => any;
            onmsgesturestart: (ev: any) => any;
            onmspointercancel: (ev: any) => any;
            onmsgestureend: (ev: any) => any;
            onmsgesturetap: (ev: any) => any;
            onmspointerout: (ev: any) => any;
            onmsinertiastart: (ev: any) => any;
            onmslostpointercapture: (ev: any) => any;
            onmspointerover: (ev: any) => any;
            msContentZoomFactor: number;
            onmspointerup: (ev: any) => any;
            onlostpointercapture: (ev: PointerEvent) => any;
            onmspointerenter: (ev: any) => any;
            ongotpointercapture: (ev: PointerEvent) => any;
            onmspointerleave: (ev: any) => any;
            getAttribute(name?: string): string;
            getElementsByTagNameNS(namespaceURI: string, localName: string): NodeList;
            hasAttributeNS(namespaceURI: string, localName: string): boolean;
            getBoundingClientRect(): ClientRect;
            getAttributeNS(namespaceURI: string, localName: string): string;
            getAttributeNodeNS(namespaceURI: string, localName: string): Attr;
            setAttributeNodeNS(newAttr: Attr): Attr;
            msMatchesSelector(selectors: string): boolean;
            hasAttribute(name: string): boolean;
            removeAttribute(name?: string): void;
            setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;
            getAttributeNode(name: string): Attr;
            fireEvent(eventName: string, eventObj?: any): boolean;
            getElementsByTagName(name: "a"): NodeListOf<HTMLAnchorElement>;
            getElementsByTagName(name: "abbr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "acronym"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "address"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "applet"): NodeListOf<HTMLAppletElement>;
            getElementsByTagName(name: "area"): NodeListOf<HTMLAreaElement>;
            getElementsByTagName(name: "article"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "aside"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "audio"): NodeListOf<HTMLAudioElement>;
            getElementsByTagName(name: "b"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "base"): NodeListOf<HTMLBaseElement>;
            getElementsByTagName(name: "basefont"): NodeListOf<HTMLBaseFontElement>;
            getElementsByTagName(name: "bdo"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "bgsound"): NodeListOf<HTMLBGSoundElement>;
            getElementsByTagName(name: "big"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "blockquote"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "body"): NodeListOf<HTMLBodyElement>;
            getElementsByTagName(name: "br"): NodeListOf<HTMLBRElement>;
            getElementsByTagName(name: "button"): NodeListOf<HTMLButtonElement>;
            getElementsByTagName(name: "canvas"): NodeListOf<HTMLCanvasElement>;
            getElementsByTagName(name: "caption"): NodeListOf<HTMLTableCaptionElement>;
            getElementsByTagName(name: "center"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "cite"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "code"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "col"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "colgroup"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "datalist"): NodeListOf<HTMLDataListElement>;
            getElementsByTagName(name: "dd"): NodeListOf<HTMLDDElement>;
            getElementsByTagName(name: "del"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "dfn"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "dir"): NodeListOf<HTMLDirectoryElement>;
            getElementsByTagName(name: "div"): NodeListOf<HTMLDivElement>;
            getElementsByTagName(name: "dl"): NodeListOf<HTMLDListElement>;
            getElementsByTagName(name: "dt"): NodeListOf<HTMLDTElement>;
            getElementsByTagName(name: "em"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "embed"): NodeListOf<HTMLEmbedElement>;
            getElementsByTagName(name: "fieldset"): NodeListOf<HTMLFieldSetElement>;
            getElementsByTagName(name: "figcaption"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "figure"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "font"): NodeListOf<HTMLFontElement>;
            getElementsByTagName(name: "footer"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "form"): NodeListOf<HTMLFormElement>;
            getElementsByTagName(name: "frame"): NodeListOf<HTMLFrameElement>;
            getElementsByTagName(name: "frameset"): NodeListOf<HTMLFrameSetElement>;
            getElementsByTagName(name: "h1"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h2"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h3"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h4"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h5"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h6"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "head"): NodeListOf<HTMLHeadElement>;
            getElementsByTagName(name: "header"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hgroup"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hr"): NodeListOf<HTMLHRElement>;
            getElementsByTagName(name: "html"): NodeListOf<HTMLHtmlElement>;
            getElementsByTagName(name: "i"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "iframe"): NodeListOf<HTMLIFrameElement>;
            getElementsByTagName(name: "img"): NodeListOf<HTMLImageElement>;
            getElementsByTagName(name: "input"): NodeListOf<HTMLInputElement>;
            getElementsByTagName(name: "ins"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "isindex"): NodeListOf<HTMLIsIndexElement>;
            getElementsByTagName(name: "kbd"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "keygen"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "label"): NodeListOf<HTMLLabelElement>;
            getElementsByTagName(name: "legend"): NodeListOf<HTMLLegendElement>;
            getElementsByTagName(name: "li"): NodeListOf<HTMLLIElement>;
            getElementsByTagName(name: "link"): NodeListOf<HTMLLinkElement>;
            getElementsByTagName(name: "listing"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "map"): NodeListOf<HTMLMapElement>;
            getElementsByTagName(name: "mark"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "marquee"): NodeListOf<HTMLMarqueeElement>;
            getElementsByTagName(name: "menu"): NodeListOf<HTMLMenuElement>;
            getElementsByTagName(name: "meta"): NodeListOf<HTMLMetaElement>;
            getElementsByTagName(name: "nav"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "nextid"): NodeListOf<HTMLNextIdElement>;
            getElementsByTagName(name: "nobr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "noframes"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "noscript"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "object"): NodeListOf<HTMLObjectElement>;
            getElementsByTagName(name: "ol"): NodeListOf<HTMLOListElement>;
            getElementsByTagName(name: "optgroup"): NodeListOf<HTMLOptGroupElement>;
            getElementsByTagName(name: "option"): NodeListOf<HTMLOptionElement>;
            getElementsByTagName(name: "p"): NodeListOf<HTMLParagraphElement>;
            getElementsByTagName(name: "param"): NodeListOf<HTMLParamElement>;
            getElementsByTagName(name: "plaintext"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "pre"): NodeListOf<HTMLPreElement>;
            getElementsByTagName(name: "progress"): NodeListOf<HTMLProgressElement>;
            getElementsByTagName(name: "q"): NodeListOf<HTMLQuoteElement>;
            getElementsByTagName(name: "rt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ruby"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "s"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "samp"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "script"): NodeListOf<HTMLScriptElement>;
            getElementsByTagName(name: "section"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "select"): NodeListOf<HTMLSelectElement>;
            getElementsByTagName(name: "small"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "SOURCE"): NodeListOf<HTMLSourceElement>;
            getElementsByTagName(name: "span"): NodeListOf<HTMLSpanElement>;
            getElementsByTagName(name: "strike"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "strong"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "style"): NodeListOf<HTMLStyleElement>;
            getElementsByTagName(name: "sub"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "sup"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "table"): NodeListOf<HTMLTableElement>;
            getElementsByTagName(name: "tbody"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "td"): NodeListOf<HTMLTableDataCellElement>;
            getElementsByTagName(name: "textarea"): NodeListOf<HTMLTextAreaElement>;
            getElementsByTagName(name: "tfoot"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "th"): NodeListOf<HTMLTableHeaderCellElement>;
            getElementsByTagName(name: "thead"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "title"): NodeListOf<HTMLTitleElement>;
            getElementsByTagName(name: "tr"): NodeListOf<HTMLTableRowElement>;
            getElementsByTagName(name: "track"): NodeListOf<HTMLTrackElement>;
            getElementsByTagName(name: "tt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "u"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ul"): NodeListOf<HTMLUListElement>;
            getElementsByTagName(name: "var"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "video"): NodeListOf<HTMLVideoElement>;
            getElementsByTagName(name: "wbr"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "x-ms-webview"): NodeListOf<MSHTMLWebViewElement>;
            getElementsByTagName(name: "xmp"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: string): NodeList;
            getClientRects(): ClientRectList;
            setAttributeNode(newAttr: Attr): Attr;
            removeAttributeNode(oldAttr: Attr): Attr;
            setAttribute(name?: string, value?: string): void;
            removeAttributeNS(namespaceURI: string, localName: string): void;
            msGetRegionContent(): MSRangeCollection;
            msReleasePointerCapture(pointerId: number): void;
            msSetPointerCapture(pointerId: number): void;
            msZoomTo(args: MsZoomToOptions): void;
            setPointerCapture(pointerId: number): void;
            msGetUntransformedBounds(): ClientRect;
            releasePointerCapture(pointerId: number): void;
            msRequestFullscreen(): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var Element: {
            prototype: Element;
            new(): Element;
        }
        
        interface HTMLNextIdElement extends HTMLElement {
            n: string;
        }
        declare var HTMLNextIdElement: {
            prototype: HTMLNextIdElement;
            new(): HTMLNextIdElement;
        }
        
        interface SVGPathSegMovetoRel extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegMovetoRel: {
            prototype: SVGPathSegMovetoRel;
            new(): SVGPathSegMovetoRel;
        }
        
        interface SVGLineElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            y1: SVGAnimatedLength;
            x2: SVGAnimatedLength;
            x1: SVGAnimatedLength;
            y2: SVGAnimatedLength;
        }
        declare var SVGLineElement: {
            prototype: SVGLineElement;
            new(): SVGLineElement;
        }
        
        interface HTMLParagraphElement extends HTMLElement, DOML2DeprecatedTextFlowControl {
            /**
              * Sets or retrieves how the object is aligned with adjacent text. 
              */
            align: string;
        }
        declare var HTMLParagraphElement: {
            prototype: HTMLParagraphElement;
            new(): HTMLParagraphElement;
        }
        
        interface HTMLAreasCollection extends HTMLCollection {
            /**
              * Removes an element from the collection.
              */
            remove(index?: number): void;
            /**
              * Adds an element to the areas, controlRange, or options collection.
              */
            add(element: HTMLElement, before?: any): void;
        }
        declare var HTMLAreasCollection: {
            prototype: HTMLAreasCollection;
            new(): HTMLAreasCollection;
        }
        
        interface SVGDescElement extends SVGElement, SVGStylable, SVGLangSpace {
        }
        declare var SVGDescElement: {
            prototype: SVGDescElement;
            new(): SVGDescElement;
        }
        
        interface Node extends EventTarget {
            nodeType: number;
            previousSibling: Node;
            localName: string;
            namespaceURI: string;
            textContent: string;
            parentNode: Node;
            nextSibling: Node;
            nodeValue: string;
            lastChild: Node;
            childNodes: NodeList;
            nodeName: string;
            ownerDocument: Document;
            attributes: NamedNodeMap;
            firstChild: Node;
            prefix: string;
            removeChild(oldChild: Node): Node;
            appendChild(newChild: Node): Node;
            isSupported(feature: string, version: string): boolean;
            isEqualNode(arg: Node): boolean;
            lookupPrefix(namespaceURI: string): string;
            isDefaultNamespace(namespaceURI: string): boolean;
            compareDocumentPosition(other: Node): number;
            normalize(): void;
            isSameNode(other: Node): boolean;
            hasAttributes(): boolean;
            lookupNamespaceURI(prefix: string): string;
            cloneNode(deep?: boolean): Node;
            hasChildNodes(): boolean;
            replaceChild(newChild: Node, oldChild: Node): Node;
            insertBefore(newChild: Node, refChild?: Node): Node;
            ENTITY_REFERENCE_NODE: number;
            ATTRIBUTE_NODE: number;
            DOCUMENT_FRAGMENT_NODE: number;
            TEXT_NODE: number;
            ELEMENT_NODE: number;
            COMMENT_NODE: number;
            DOCUMENT_POSITION_DISCONNECTED: number;
            DOCUMENT_POSITION_CONTAINED_BY: number;
            DOCUMENT_POSITION_CONTAINS: number;
            DOCUMENT_TYPE_NODE: number;
            DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
            DOCUMENT_NODE: number;
            ENTITY_NODE: number;
            PROCESSING_INSTRUCTION_NODE: number;
            CDATA_SECTION_NODE: number;
            NOTATION_NODE: number;
            DOCUMENT_POSITION_FOLLOWING: number;
            DOCUMENT_POSITION_PRECEDING: number;
        }
        declare var Node: {
            prototype: Node;
            new(): Node;
            ENTITY_REFERENCE_NODE: number;
            ATTRIBUTE_NODE: number;
            DOCUMENT_FRAGMENT_NODE: number;
            TEXT_NODE: number;
            ELEMENT_NODE: number;
            COMMENT_NODE: number;
            DOCUMENT_POSITION_DISCONNECTED: number;
            DOCUMENT_POSITION_CONTAINED_BY: number;
            DOCUMENT_POSITION_CONTAINS: number;
            DOCUMENT_TYPE_NODE: number;
            DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
            DOCUMENT_NODE: number;
            ENTITY_NODE: number;
            PROCESSING_INSTRUCTION_NODE: number;
            CDATA_SECTION_NODE: number;
            NOTATION_NODE: number;
            DOCUMENT_POSITION_FOLLOWING: number;
            DOCUMENT_POSITION_PRECEDING: number;
        }
        
        interface SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegCurvetoQuadraticSmoothRel: {
            prototype: SVGPathSegCurvetoQuadraticSmoothRel;
            new(): SVGPathSegCurvetoQuadraticSmoothRel;
        }
        
        interface DOML2DeprecatedListSpaceReduction {
            compact: boolean;
        }
        
        interface MSScriptHost {
        }
        declare var MSScriptHost: {
            prototype: MSScriptHost;
            new(): MSScriptHost;
        }
        
        interface SVGClipPathElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            clipPathUnits: SVGAnimatedEnumeration;
        }
        declare var SVGClipPathElement: {
            prototype: SVGClipPathElement;
            new(): SVGClipPathElement;
        }
        
        interface MouseEvent extends UIEvent {
            toElement: Element;
            layerY: number;
            fromElement: Element;
            which: number;
            pageX: number;
            offsetY: number;
            x: number;
            y: number;
            metaKey: boolean;
            altKey: boolean;
            ctrlKey: boolean;
            offsetX: number;
            screenX: number;
            clientY: number;
            shiftKey: boolean;
            layerX: number;
            screenY: number;
            relatedTarget: EventTarget;
            button: number;
            pageY: number;
            buttons: number;
            clientX: number;
            initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget): void;
            getModifierState(keyArg: string): boolean;
        }
        declare var MouseEvent: {
            prototype: MouseEvent;
            new(): MouseEvent;
        }
        
        interface RangeException {
            code: number;
            message: string;
            name: string;
            toString(): string;
            INVALID_NODE_TYPE_ERR: number;
            BAD_BOUNDARYPOINTS_ERR: number;
        }
        declare var RangeException: {
            prototype: RangeException;
            new(): RangeException;
            INVALID_NODE_TYPE_ERR: number;
            BAD_BOUNDARYPOINTS_ERR: number;
        }
        
        interface SVGTextPositioningElement extends SVGTextContentElement {
            y: SVGAnimatedLengthList;
            rotate: SVGAnimatedNumberList;
            dy: SVGAnimatedLengthList;
            x: SVGAnimatedLengthList;
            dx: SVGAnimatedLengthList;
        }
        declare var SVGTextPositioningElement: {
            prototype: SVGTextPositioningElement;
            new(): SVGTextPositioningElement;
        }
        
        interface HTMLAppletElement extends HTMLElement, DOML2DeprecatedMarginStyle, DOML2DeprecatedBorderStyle, DOML2DeprecatedAlignmentStyle, MSDataBindingExtensions, MSDataBindingRecordSetExtensions {
            width: number;
            /**
              * Sets or retrieves the Internet media type for the code associated with the object.
              */
            codeType: string;
            object: string;
            form: HTMLFormElement;
            code: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.
              */
            archive: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves a message to be displayed while an object is loading.
              */
            standby: string;
            /**
              * Sets or retrieves the class identifier for the object.
              */
            classid: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            name: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Sets or retrieves the URL that references the data of the object.
              */
            data: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Gets or sets the optional alternative HTML script to execute if the object fails to load.
              */
            altHtml: string;
            /**
              * Address of a pointer to the document this page or frame contains. If there is no document, then null will be returned.
              */
            contentDocument: Document;
            /**
              * Sets or retrieves the URL of the component.
              */
            codeBase: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own declare functionality for the object.
              */
            declare: boolean;
            /**
              * Returns the content type of the object.
              */
            type: string;
            /**
              * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.
              */
            BaseHref: string;
        }
        declare var HTMLAppletElement: {
            prototype: HTMLAppletElement;
            new(): HTMLAppletElement;
        }
        
        interface TextMetrics {
            width: number;
        }
        declare var TextMetrics: {
            prototype: TextMetrics;
            new(): TextMetrics;
        }
        
        interface DocumentEvent {
            createEvent(eventInterface: "AnimationEvent"): AnimationEvent;
            createEvent(eventInterface: "CloseEvent"): CloseEvent;
            createEvent(eventInterface: "CompositionEvent"): CompositionEvent;
            createEvent(eventInterface: "CustomEvent"): CustomEvent;
            createEvent(eventInterface: "DeviceMotionEvent"): DeviceMotionEvent;
            createEvent(eventInterface: "DeviceOrientationEvent"): DeviceOrientationEvent;
            createEvent(eventInterface: "DragEvent"): DragEvent;
            createEvent(eventInterface: "ErrorEvent"): ErrorEvent;
            createEvent(eventInterface: "Event"): Event;
            createEvent(eventInterface: "Events"): Event;
            createEvent(eventInterface: "FocusEvent"): FocusEvent;
            createEvent(eventInterface: "HTMLEvents"): Event;
            createEvent(eventInterface: "IDBVersionChangeEvent"): IDBVersionChangeEvent;
            createEvent(eventInterface: "KeyboardEvent"): KeyboardEvent;
            createEvent(eventInterface: "LongRunningScriptDetectedEvent"): LongRunningScriptDetectedEvent;
            createEvent(eventInterface: "MessageEvent"): MessageEvent;
            createEvent(eventInterface: "MouseEvent"): MouseEvent;
            createEvent(eventInterface: "MouseEvents"): MouseEvent;
            createEvent(eventInterface: "MouseWheelEvent"): MouseWheelEvent;
            createEvent(eventInterface: "MSGestureEvent"): MSGestureEvent;
            createEvent(eventInterface: "MSPointerEvent"): MSPointerEvent;
            createEvent(eventInterface: "MutationEvent"): MutationEvent;
            createEvent(eventInterface: "MutationEvents"): MutationEvent;
            createEvent(eventInterface: "NavigationCompletedEvent"): NavigationCompletedEvent;
            createEvent(eventInterface: "NavigationEvent"): NavigationEvent;
            createEvent(eventInterface: "PageTransitionEvent"): PageTransitionEvent;
            createEvent(eventInterface: "PointerEvent"): MSPointerEvent;
            createEvent(eventInterface: "PopStateEvent"): PopStateEvent;
            createEvent(eventInterface: "ProgressEvent"): ProgressEvent;
            createEvent(eventInterface: "StorageEvent"): StorageEvent;
            createEvent(eventInterface: "SVGZoomEvents"): SVGZoomEvent;
            createEvent(eventInterface: "TextEvent"): TextEvent;
            createEvent(eventInterface: "TrackEvent"): TrackEvent;
            createEvent(eventInterface: "TransitionEvent"): TransitionEvent;
            createEvent(eventInterface: "UIEvent"): UIEvent;
            createEvent(eventInterface: "UIEvents"): UIEvent;
            createEvent(eventInterface: "UnviewableContentIdentifiedEvent"): UnviewableContentIdentifiedEvent;
            createEvent(eventInterface: "WebGLContextEvent"): WebGLContextEvent;
            createEvent(eventInterface: "WheelEvent"): WheelEvent;
            createEvent(eventInterface: string): Event;
        }
        
        interface HTMLOListElement extends HTMLElement, DOML2DeprecatedListSpaceReduction, DOML2DeprecatedListNumberingAndBulletStyle {
            /**
              * The starting number.
              */
            start: number;
        }
        declare var HTMLOListElement: {
            prototype: HTMLOListElement;
            new(): HTMLOListElement;
        }
        
        interface SVGPathSegLinetoVerticalRel extends SVGPathSeg {
            y: number;
        }
        declare var SVGPathSegLinetoVerticalRel: {
            prototype: SVGPathSegLinetoVerticalRel;
            new(): SVGPathSegLinetoVerticalRel;
        }
        
        interface SVGAnimatedString {
            animVal: string;
            baseVal: string;
        }
        declare var SVGAnimatedString: {
            prototype: SVGAnimatedString;
            new(): SVGAnimatedString;
        }
        
        interface CDATASection extends Text {
        }
        declare var CDATASection: {
            prototype: CDATASection;
            new(): CDATASection;
        }
        
        interface StyleMedia {
            type: string;
            matchMedium(mediaquery: string): boolean;
        }
        declare var StyleMedia: {
            prototype: StyleMedia;
            new(): StyleMedia;
        }
        
        interface HTMLSelectElement extends HTMLElement, MSHTMLCollectionExtensions, MSDataBindingExtensions {
            options: HTMLSelectElement;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Sets or retrieves the number of rows in the list box. 
              */
            size: number;
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Sets or retrieves the index of the selected option in a select object.
              */
            selectedIndex: number;
            /**
              * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.
              */
            multiple: boolean;
            /**
              * Retrieves the type of select control based on the value of the MULTIPLE attribute.
              */
            type: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Removes an element from the collection.
              * @param index Number that specifies the zero-based index of the element to remove from the collection.
              */
            remove(index?: number): void;
            /**
              * Adds an element to the areas, controlRange, or options collection.
              * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection.
              * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection. 
              */
            add(element: HTMLElement, before?: any): void;
            /**
              * Retrieves a select object or an object from an options collection.
              * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is an integer, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.
              * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.
              */
            item(name?: any, index?: any): any;
            /**
              * Retrieves a select object or an object from an options collection.
              * @param namedItem A String that specifies the name or id property of the object to retrieve. A collection is returned if more than one match is made.
              */
            namedItem(name: string): any;
            [name: string]: any;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLSelectElement: {
            prototype: HTMLSelectElement;
            new(): HTMLSelectElement;
        }
        
        interface TextRange {
            boundingLeft: number;
            htmlText: string;
            offsetLeft: number;
            boundingWidth: number;
            boundingHeight: number;
            boundingTop: number;
            text: string;
            offsetTop: number;
            moveToPoint(x: number, y: number): void;
            queryCommandValue(cmdID: string): any;
            getBookmark(): string;
            move(unit: string, count?: number): number;
            queryCommandIndeterm(cmdID: string): boolean;
            scrollIntoView(fStart?: boolean): void;
            findText(string: string, count?: number, flags?: number): boolean;
            execCommand(cmdID: string, showUI?: boolean, value?: any): boolean;
            getBoundingClientRect(): ClientRect;
            moveToBookmark(bookmark: string): boolean;
            isEqual(range: TextRange): boolean;
            duplicate(): TextRange;
            collapse(start?: boolean): void;
            queryCommandText(cmdID: string): string;
            select(): void;
            pasteHTML(html: string): void;
            inRange(range: TextRange): boolean;
            moveEnd(unit: string, count?: number): number;
            getClientRects(): ClientRectList;
            moveStart(unit: string, count?: number): number;
            parentElement(): Element;
            queryCommandState(cmdID: string): boolean;
            compareEndPoints(how: string, sourceRange: TextRange): number;
            execCommandShowHelp(cmdID: string): boolean;
            moveToElementText(element: Element): void;
            expand(Unit: string): boolean;
            queryCommandSupported(cmdID: string): boolean;
            setEndPoint(how: string, SourceRange: TextRange): void;
            queryCommandEnabled(cmdID: string): boolean;
        }
        declare var TextRange: {
            prototype: TextRange;
            new(): TextRange;
        }
        
        interface SVGTests {
            requiredFeatures: SVGStringList;
            requiredExtensions: SVGStringList;
            systemLanguage: SVGStringList;
            hasExtension(extension: string): boolean;
        }
        
        interface HTMLBlockElement extends HTMLElement, DOML2DeprecatedTextFlowControl {
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
        }
        declare var HTMLBlockElement: {
            prototype: HTMLBlockElement;
            new(): HTMLBlockElement;
        }
        
        interface CSSStyleSheet extends StyleSheet {
            owningElement: Element;
            imports: StyleSheetList;
            isAlternate: boolean;
            rules: MSCSSRuleList;
            isPrefAlternate: boolean;
            readOnly: boolean;
            cssText: string;
            ownerRule: CSSRule;
            href: string;
            cssRules: CSSRuleList;
            id: string;
            pages: StyleSheetPageList;
            addImport(bstrURL: string, lIndex?: number): number;
            addPageRule(bstrSelector: string, bstrStyle: string, lIndex?: number): number;
            insertRule(rule: string, index?: number): number;
            removeRule(lIndex: number): void;
            deleteRule(index?: number): void;
            addRule(bstrSelector: string, bstrStyle?: string, lIndex?: number): number;
            removeImport(lIndex: number): void;
        }
        declare var CSSStyleSheet: {
            prototype: CSSStyleSheet;
            new(): CSSStyleSheet;
        }
        
        interface MSSelection {
            type: string;
            typeDetail: string;
            createRange(): TextRange;
            clear(): void;
            createRangeCollection(): TextRangeCollection;
            empty(): void;
        }
        declare var MSSelection: {
            prototype: MSSelection;
            new(): MSSelection;
        }
        
        interface HTMLMetaElement extends HTMLElement {
            /**
              * Gets or sets information used to bind the value of a content attribute of a meta element to an HTTP response header.
              */
            httpEquiv: string;
            /**
              * Sets or retrieves the value specified in the content attribute of the meta object.
              */
            name: string;
            /**
              * Gets or sets meta-information to associate with httpEquiv or name.
              */
            content: string;
            /**
              * Sets or retrieves the URL property that will be loaded after the specified time has elapsed. 
              */
            url: string;
            /**
              * Sets or retrieves a scheme to be used in interpreting the value of a property specified for the object.
              */
            scheme: string;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
        }
        declare var HTMLMetaElement: {
            prototype: HTMLMetaElement;
            new(): HTMLMetaElement;
        }
        
        interface SVGPatternElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLangSpace, SVGTests, SVGFitToViewBox, SVGExternalResourcesRequired, SVGURIReference {
            patternUnits: SVGAnimatedEnumeration;
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            patternContentUnits: SVGAnimatedEnumeration;
            patternTransform: SVGAnimatedTransformList;
            height: SVGAnimatedLength;
        }
        declare var SVGPatternElement: {
            prototype: SVGPatternElement;
            new(): SVGPatternElement;
        }
        
        interface SVGAnimatedAngle {
            animVal: SVGAngle;
            baseVal: SVGAngle;
        }
        declare var SVGAnimatedAngle: {
            prototype: SVGAnimatedAngle;
            new(): SVGAnimatedAngle;
        }
        
        interface Selection {
            isCollapsed: boolean;
            anchorNode: Node;
            focusNode: Node;
            anchorOffset: number;
            focusOffset: number;
            rangeCount: number;
            addRange(range: Range): void;
            collapseToEnd(): void;
            toString(): string;
            selectAllChildren(parentNode: Node): void;
            getRangeAt(index: number): Range;
            collapse(parentNode: Node, offset: number): void;
            removeAllRanges(): void;
            collapseToStart(): void;
            deleteFromDocument(): void;
            removeRange(range: Range): void;
        }
        declare var Selection: {
            prototype: Selection;
            new(): Selection;
        }
        
        interface SVGScriptElement extends SVGElement, SVGExternalResourcesRequired, SVGURIReference {
            type: string;
        }
        declare var SVGScriptElement: {
            prototype: SVGScriptElement;
            new(): SVGScriptElement;
        }
        
        interface HTMLDDElement extends HTMLElement {
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        declare var HTMLDDElement: {
            prototype: HTMLDDElement;
            new(): HTMLDDElement;
        }
        
        interface MSDataBindingRecordSetReadonlyExtensions {
            recordset: any;
            namedRecordset(dataMember: string, hierarchy?: any): any;
        }
        
        interface CSSStyleRule extends CSSRule {
            selectorText: string;
            style: MSStyleCSSProperties;
            readOnly: boolean;
        }
        declare var CSSStyleRule: {
            prototype: CSSStyleRule;
            new(): CSSStyleRule;
        }
        
        interface NodeIterator {
            whatToShow: number;
            filter: NodeFilter;
            root: Node;
            expandEntityReferences: boolean;
            nextNode(): Node;
            detach(): void;
            previousNode(): Node;
        }
        declare var NodeIterator: {
            prototype: NodeIterator;
            new(): NodeIterator;
        }
        
        interface SVGViewElement extends SVGElement, SVGZoomAndPan, SVGFitToViewBox, SVGExternalResourcesRequired {
            viewTarget: SVGStringList;
        }
        declare var SVGViewElement: {
            prototype: SVGViewElement;
            new(): SVGViewElement;
        }
        
        interface HTMLLinkElement extends HTMLElement, LinkStyle {
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rel: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or retrieves the media type.
              */
            media: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rev: string;
            /**
              * Sets or retrieves the MIME type of the object.
              */
            type: string;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Sets or retrieves the language code of the object.
              */
            hreflang: string;
        }
        declare var HTMLLinkElement: {
            prototype: HTMLLinkElement;
            new(): HTMLLinkElement;
        }
        
        interface SVGLocatable {
            farthestViewportElement: SVGElement;
            nearestViewportElement: SVGElement;
            getBBox(): SVGRect;
            getTransformToElement(element: SVGElement): SVGMatrix;
            getCTM(): SVGMatrix;
            getScreenCTM(): SVGMatrix;
        }
        
        interface HTMLFontElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {
            /**
              * Sets or retrieves the current typeface family.
              */
            face: string;
        }
        declare var HTMLFontElement: {
            prototype: HTMLFontElement;
            new(): HTMLFontElement;
        }
        
        interface SVGTitleElement extends SVGElement, SVGStylable, SVGLangSpace {
        }
        declare var SVGTitleElement: {
            prototype: SVGTitleElement;
            new(): SVGTitleElement;
        }
        
        interface ControlRangeCollection {
            length: number;
            queryCommandValue(cmdID: string): any;
            remove(index: number): void;
            add(item: Element): void;
            queryCommandIndeterm(cmdID: string): boolean;
            scrollIntoView(varargStart?: any): void;
            item(index: number): Element;
            [index: number]: Element;
            execCommand(cmdID: string, showUI?: boolean, value?: any): boolean;
            addElement(item: Element): void;
            queryCommandState(cmdID: string): boolean;
            queryCommandSupported(cmdID: string): boolean;
            queryCommandEnabled(cmdID: string): boolean;
            queryCommandText(cmdID: string): string;
            select(): void;
        }
        declare var ControlRangeCollection: {
            prototype: ControlRangeCollection;
            new(): ControlRangeCollection;
        }
        
        interface MSNamespaceInfo extends MSEventAttachmentTarget {
            urn: string;
            onreadystatechange: (ev: Event) => any;
            name: string;
            readyState: string;
            doImport(implementationUrl: string): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var MSNamespaceInfo: {
            prototype: MSNamespaceInfo;
            new(): MSNamespaceInfo;
        }
        
        interface WindowSessionStorage {
            sessionStorage: Storage;
        }
        
        interface SVGAnimatedTransformList {
            animVal: SVGTransformList;
            baseVal: SVGTransformList;
        }
        declare var SVGAnimatedTransformList: {
            prototype: SVGAnimatedTransformList;
            new(): SVGAnimatedTransformList;
        }
        
        interface HTMLTableCaptionElement extends HTMLElement {
            /**
              * Sets or retrieves the alignment of the caption or legend.
              */
            align: string;
            /**
              * Sets or retrieves whether the caption appears at the top or bottom of the table.
              */
            vAlign: string;
        }
        declare var HTMLTableCaptionElement: {
            prototype: HTMLTableCaptionElement;
            new(): HTMLTableCaptionElement;
        }
        
        interface HTMLOptionElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves the ordinal position of an option in a list box.
              */
            index: number;
            /**
              * Sets or retrieves the status of an option.
              */
            defaultSelected: boolean;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
            /**
              * Sets or retrieves the text string specified by the option tag.
              */
            text: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves a value that you can use to implement your own label functionality for the object.
              */
            label: string;
            /**
              * Sets or retrieves whether the option in the list box is the default item.
              */
            selected: boolean;
        }
        declare var HTMLOptionElement: {
            prototype: HTMLOptionElement;
            new(): HTMLOptionElement;
            create(): HTMLOptionElement;
        }
        
        interface HTMLMapElement extends HTMLElement {
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Retrieves a collection of the area objects defined for the given map object.
              */
            areas: HTMLAreasCollection;
        }
        declare var HTMLMapElement: {
            prototype: HTMLMapElement;
            new(): HTMLMapElement;
        }
        
        interface HTMLMenuElement extends HTMLElement, DOML2DeprecatedListSpaceReduction {
            type: string;
        }
        declare var HTMLMenuElement: {
            prototype: HTMLMenuElement;
            new(): HTMLMenuElement;
        }
        
        interface MouseWheelEvent extends MouseEvent {
            wheelDelta: number;
            initMouseWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, wheelDeltaArg: number): void;
        }
        declare var MouseWheelEvent: {
            prototype: MouseWheelEvent;
            new(): MouseWheelEvent;
        }
        
        interface SVGFitToViewBox {
            viewBox: SVGAnimatedRect;
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
        }
        
        interface SVGPointList {
            numberOfItems: number;
            replaceItem(newItem: SVGPoint, index: number): SVGPoint;
            getItem(index: number): SVGPoint;
            clear(): void;
            appendItem(newItem: SVGPoint): SVGPoint;
            initialize(newItem: SVGPoint): SVGPoint;
            removeItem(index: number): SVGPoint;
            insertItemBefore(newItem: SVGPoint, index: number): SVGPoint;
        }
        declare var SVGPointList: {
            prototype: SVGPointList;
            new(): SVGPointList;
        }
        
        interface SVGAnimatedLengthList {
            animVal: SVGLengthList;
            baseVal: SVGLengthList;
        }
        declare var SVGAnimatedLengthList: {
            prototype: SVGAnimatedLengthList;
            new(): SVGAnimatedLengthList;
        }
        
        interface SVGAnimatedPreserveAspectRatio {
            animVal: SVGPreserveAspectRatio;
            baseVal: SVGPreserveAspectRatio;
        }
        declare var SVGAnimatedPreserveAspectRatio: {
            prototype: SVGAnimatedPreserveAspectRatio;
            new(): SVGAnimatedPreserveAspectRatio;
        }
        
        interface MSSiteModeEvent extends Event {
            buttonID: number;
            actionURL: string;
        }
        declare var MSSiteModeEvent: {
            prototype: MSSiteModeEvent;
            new(): MSSiteModeEvent;
        }
        
        interface DOML2DeprecatedTextFlowControl {
            clear: string;
        }
        
        interface StyleSheetPageList {
            length: number;
            item(index: number): CSSPageRule;
            [index: number]: CSSPageRule;
        }
        declare var StyleSheetPageList: {
            prototype: StyleSheetPageList;
            new(): StyleSheetPageList;
        }
        
        interface MSCSSProperties extends CSSStyleDeclaration {
            scrollbarShadowColor: string;
            scrollbarHighlightColor: string;
            layoutGridChar: string;
            layoutGridType: string;
            textAutospace: string;
            textKashidaSpace: string;
            writingMode: string;
            scrollbarFaceColor: string;
            backgroundPositionY: string;
            lineBreak: string;
            imeMode: string;
            msBlockProgression: string;
            layoutGridLine: string;
            scrollbarBaseColor: string;
            layoutGrid: string;
            layoutFlow: string;
            textKashida: string;
            filter: string;
            zoom: string;
            scrollbarArrowColor: string;
            behavior: string;
            backgroundPositionX: string;
            accelerator: string;
            layoutGridMode: string;
            textJustifyTrim: string;
            scrollbar3dLightColor: string;
            msInterpolationMode: string;
            scrollbarTrackColor: string;
            scrollbarDarkShadowColor: string;
            styleFloat: string;
            getAttribute(attributeName: string, flags?: number): any;
            setAttribute(attributeName: string, AttributeValue: any, flags?: number): void;
            removeAttribute(attributeName: string, flags?: number): boolean;
        }
        declare var MSCSSProperties: {
            prototype: MSCSSProperties;
            new(): MSCSSProperties;
        }
        
        interface SVGExternalResourcesRequired {
            externalResourcesRequired: SVGAnimatedBoolean;
        }
        
        interface HTMLImageElement extends HTMLElement, MSImageResourceExtensions, MSDataBindingExtensions, MSResourceMetadata {
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * The original height of the image resource before sizing.
              */
            naturalHeight: number;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * The original width of the image resource before sizing.
              */
            naturalWidth: number;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: number;
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            hspace: number;
            /**
              * Sets or retrieves a Uniform Resource Identifier (URI) to a long description of the object.
              */
            longDesc: string;
            /**
              * Contains the hypertext reference (HREF) of the URL.
              */
            href: string;
            /**
              * Sets or retrieves whether the image is a server-side image map.
              */
            isMap: boolean;
            /**
              * Retrieves whether the object is fully loaded.
              */
            complete: boolean;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            crossOrigin: string;
            msPlayToPreferredSourceUri: string;
        }
        declare var HTMLImageElement: {
            prototype: HTMLImageElement;
            new(): HTMLImageElement;
            create(): HTMLImageElement;
        }
        
        interface HTMLAreaElement extends HTMLElement {
            /**
              * Sets or retrieves the protocol portion of a URL.
              */
            protocol: string;
            /**
              * Sets or retrieves the substring of the href property that follows the question mark.
              */
            search: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves the coordinates of the object.
              */
            coords: string;
            /**
              * Sets or retrieves the host name part of the location or URL. 
              */
            hostname: string;
            /**
              * Sets or retrieves the port number associated with a URL.
              */
            port: string;
            /**
              * Sets or retrieves the file name or path specified by the object.
              */
            pathname: string;
            /**
              * Sets or retrieves the hostname and port number of the location or URL.
              */
            host: string;
            /**
              * Sets or retrieves the subsection of the href property that follows the number sign (#).
              */
            hash: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or gets whether clicks in this region cause action.
              */
            noHref: boolean;
            /**
              * Sets or retrieves the shape of the object.
              */
            shape: string;
            /** 
              * Returns a string representation of an object.
              */
            toString(): string;
        }
        declare var HTMLAreaElement: {
            prototype: HTMLAreaElement;
            new(): HTMLAreaElement;
        }
        
        interface EventTarget {
            removeEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
            dispatchEvent(evt: Event): boolean;
        }
        
        interface SVGAngle {
            valueAsString: string;
            valueInSpecifiedUnits: number;
            value: number;
            unitType: number;
            newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;
            convertToSpecifiedUnits(unitType: number): void;
            SVG_ANGLETYPE_RAD: number;
            SVG_ANGLETYPE_UNKNOWN: number;
            SVG_ANGLETYPE_UNSPECIFIED: number;
            SVG_ANGLETYPE_DEG: number;
            SVG_ANGLETYPE_GRAD: number;
        }
        declare var SVGAngle: {
            prototype: SVGAngle;
            new(): SVGAngle;
            SVG_ANGLETYPE_RAD: number;
            SVG_ANGLETYPE_UNKNOWN: number;
            SVG_ANGLETYPE_UNSPECIFIED: number;
            SVG_ANGLETYPE_DEG: number;
            SVG_ANGLETYPE_GRAD: number;
        }
        
        interface HTMLButtonElement extends HTMLElement, MSDataBindingExtensions {
            /** 
              * Sets or retrieves the default or selected value of the control.
              */
            value: string;
            status: any;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /** 
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Gets the classification and default behavior of the button.
              */
            type: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Overrides the target attribute on a form element.
              */
            formTarget: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Overrides the action attribute (where the data on a form is sent) on the parent form element.
              */
            formAction: string;
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option.
              */
            formNoValidate: string;
            /**
              * Used to override the encoding (formEnctype attribute) specified on the form element.
              */
            formEnctype: string;
            /**
              * Overrides the submit method attribute previously specified on a form element.
              */
            formMethod: string;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLButtonElement: {
            prototype: HTMLButtonElement;
            new(): HTMLButtonElement;
        }
        
        interface HTMLSourceElement extends HTMLElement {
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            /**
              * Gets or sets the intended media type of the media source.
             */
            media: string;
            /**
             * Gets or sets the MIME type of a media resource.
             */
            type: string;
            msKeySystem: string;
        }
        declare var HTMLSourceElement: {
            prototype: HTMLSourceElement;
            new(): HTMLSourceElement;
        }
        
        interface CanvasGradient {
            addColorStop(offset: number, color: string): void;
        }
        declare var CanvasGradient: {
            prototype: CanvasGradient;
            new(): CanvasGradient;
        }
        
        interface KeyboardEvent extends UIEvent {
            location: number;
            keyCode: number;
            shiftKey: boolean;
            which: number;
            locale: string;
            key: string;
            altKey: boolean;
            metaKey: boolean;
            char: string;
            ctrlKey: boolean;
            repeat: boolean;
            charCode: number;
            getModifierState(keyArg: string): boolean;
            initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;
            DOM_KEY_LOCATION_RIGHT: number;
            DOM_KEY_LOCATION_STANDARD: number;
            DOM_KEY_LOCATION_LEFT: number;
            DOM_KEY_LOCATION_NUMPAD: number;
            DOM_KEY_LOCATION_JOYSTICK: number;
            DOM_KEY_LOCATION_MOBILE: number;
        }
        declare var KeyboardEvent: {
            prototype: KeyboardEvent;
            new(): KeyboardEvent;
            DOM_KEY_LOCATION_RIGHT: number;
            DOM_KEY_LOCATION_STANDARD: number;
            DOM_KEY_LOCATION_LEFT: number;
            DOM_KEY_LOCATION_NUMPAD: number;
            DOM_KEY_LOCATION_JOYSTICK: number;
            DOM_KEY_LOCATION_MOBILE: number;
        }
        
        interface MessageEvent extends Event {
            source: Window;
            origin: string;
            data: any;
            ports: any;
            initMessageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, dataArg: any, originArg: string, lastEventIdArg: string, sourceArg: Window): void;
        }
        declare var MessageEvent: {
            prototype: MessageEvent;
            new(): MessageEvent;
        }
        
        interface SVGElement extends Element {
            onmouseover: (ev: MouseEvent) => any;
            viewportElement: SVGElement;
            onmousemove: (ev: MouseEvent) => any;
            onmouseout: (ev: MouseEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            onfocusout: (ev: FocusEvent) => any;
            onfocusin: (ev: FocusEvent) => any;
            xmlbase: string;
            onmousedown: (ev: MouseEvent) => any;
            onload: (ev: Event) => any;
            onmouseup: (ev: MouseEvent) => any;
            onclick: (ev: MouseEvent) => any;
            ownerSVGElement: SVGSVGElement;
            id: string;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var SVGElement: {
            prototype: SVGElement;
            new(): SVGElement;
        }
        
        interface HTMLScriptElement extends HTMLElement {
            /**
              * Sets or retrieves the status of the script.
              */
            defer: boolean;
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
            /**
              * Retrieves the URL to an external file that contains the source code or data.
              */
            src: string;
            /** 
              * Sets or retrieves the object that is bound to the event script.
              */
            htmlFor: string;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Sets or retrieves the MIME type for the associated scripting engine.
              */
            type: string;
            /**
              * Sets or retrieves the event for which the script is written. 
              */
            event: string;
            async: boolean;
        }
        declare var HTMLScriptElement: {
            prototype: HTMLScriptElement;
            new(): HTMLScriptElement;
        }
        
        interface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment, DOML2DeprecatedBackgroundColorStyle {
            /**
              * Retrieves the position of the object in the rows collection for the table.
              */
            rowIndex: number;
            /**
              * Retrieves a collection of all cells in the table row.
              */
            cells: HTMLCollection;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorLight: any;
            /**
              * Retrieves the position of the object in the collection.
              */
            sectionRowIndex: number;
            /**
              * Sets or retrieves the border color of the object.
              */
            borderColor: any;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorDark: any;
            /**
              * Removes the specified cell from the table row, as well as from the cells collection.
              * @param index Number that specifies the zero-based position of the cell to remove from the table row. If no value is provided, the last cell in the cells collection is deleted.
              */
            deleteCell(index?: number): void;
            /**
              * Creates a new cell in the table row, and adds the cell to the cells collection.
              * @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.
              */
            insertCell(index?: number): HTMLElement;
        }
        declare var HTMLTableRowElement: {
            prototype: HTMLTableRowElement;
            new(): HTMLTableRowElement;
        }
        
        interface CanvasRenderingContext2D {
            miterLimit: number;
            font: string;
            globalCompositeOperation: string;
            msFillRule: string;
            lineCap: string;
            msImageSmoothingEnabled: boolean;
            lineDashOffset: number;
            shadowColor: string;
            lineJoin: string;
            shadowOffsetX: number;
            lineWidth: number;
            canvas: HTMLCanvasElement;
            strokeStyle: any;
            globalAlpha: number;
            shadowOffsetY: number;
            fillStyle: any;
            shadowBlur: number;
            textAlign: string;
            textBaseline: string;
            restore(): void;
            setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;
            save(): void;
            arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
            measureText(text: string): TextMetrics;
            isPointInPath(x: number, y: number, fillRule?: string): boolean;
            quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
            putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;
            rotate(angle: number): void;
            fillText(text: string, x: number, y: number, maxWidth?: number): void;
            translate(x: number, y: number): void;
            scale(x: number, y: number): void;
            createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
            lineTo(x: number, y: number): void;
            getLineDash(): number[];
            fill(fillRule?: string): void;
            createImageData(imageDataOrSw: any, sh?: number): ImageData;
            createPattern(image: HTMLElement, repetition: string): CanvasPattern;
            closePath(): void;
            rect(x: number, y: number, w: number, h: number): void;
            clip(fillRule?: string): void;
            clearRect(x: number, y: number, w: number, h: number): void;
            moveTo(x: number, y: number): void;
            getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
            fillRect(x: number, y: number, w: number, h: number): void;
            bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
            drawImage(image: HTMLElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void;
            transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;
            stroke(): void;
            strokeRect(x: number, y: number, w: number, h: number): void;
            setLineDash(segments: number[]): void;
            strokeText(text: string, x: number, y: number, maxWidth?: number): void;
            beginPath(): void;
            arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
            createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
        }
        declare var CanvasRenderingContext2D: {
            prototype: CanvasRenderingContext2D;
            new(): CanvasRenderingContext2D;
        }
        
        interface MSCSSRuleList {
            length: number;
            item(index?: number): CSSStyleRule;
            [index: number]: CSSStyleRule;
        }
        declare var MSCSSRuleList: {
            prototype: MSCSSRuleList;
            new(): MSCSSRuleList;
        }
        
        interface SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {
            x: number;
        }
        declare var SVGPathSegLinetoHorizontalAbs: {
            prototype: SVGPathSegLinetoHorizontalAbs;
            new(): SVGPathSegLinetoHorizontalAbs;
        }
        
        interface SVGPathSegArcAbs extends SVGPathSeg {
            y: number;
            sweepFlag: boolean;
            r2: number;
            x: number;
            angle: number;
            r1: number;
            largeArcFlag: boolean;
        }
        declare var SVGPathSegArcAbs: {
            prototype: SVGPathSegArcAbs;
            new(): SVGPathSegArcAbs;
        }
        
        interface SVGTransformList {
            numberOfItems: number;
            getItem(index: number): SVGTransform;
            consolidate(): SVGTransform;
            clear(): void;
            appendItem(newItem: SVGTransform): SVGTransform;
            initialize(newItem: SVGTransform): SVGTransform;
            removeItem(index: number): SVGTransform;
            insertItemBefore(newItem: SVGTransform, index: number): SVGTransform;
            replaceItem(newItem: SVGTransform, index: number): SVGTransform;
            createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;
        }
        declare var SVGTransformList: {
            prototype: SVGTransformList;
            new(): SVGTransformList;
        }
        
        interface HTMLHtmlElement extends HTMLElement {
            /**
              * Sets or retrieves the DTD version that governs the current document.
              */
            version: string;
        }
        declare var HTMLHtmlElement: {
            prototype: HTMLHtmlElement;
            new(): HTMLHtmlElement;
        }
        
        interface SVGPathSegClosePath extends SVGPathSeg {
        }
        declare var SVGPathSegClosePath: {
            prototype: SVGPathSegClosePath;
            new(): SVGPathSegClosePath;
        }
        
        interface HTMLFrameElement extends HTMLElement, GetSVGDocument, MSDataBindingExtensions {
            /**
              * Sets or retrieves the width of the object.
              */
            width: any;
            /**
              * Sets or retrieves whether the frame can be scrolled.
              */
            scrolling: string;
            /**
              * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.
              */
            marginHeight: string;
            /**
              * Sets or retrieves the left and right margin widths before displaying the text in a frame.
              */
            marginWidth: string;
            /**
              * Sets or retrieves the border color of the object.
              */
            borderColor: any;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            /**
              * Sets or retrieves whether the user can resize the frame.
              */
            noResize: boolean;
            /**
              * Retrieves the object of the specified.
              */
            contentWindow: Window;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the frame name.
              */
            name: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Sets or retrieves a URI to a long description of the object.
              */
            longDesc: string;
            /**
              * Raised when the object has been completely received from the server.
              */
            onload: (ev: Event) => any;
            /**
              * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied.
              */
            security: any;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLFrameElement: {
            prototype: HTMLFrameElement;
            new(): HTMLFrameElement;
        }
        
        interface SVGAnimatedLength {
            animVal: SVGLength;
            baseVal: SVGLength;
        }
        declare var SVGAnimatedLength: {
            prototype: SVGAnimatedLength;
            new(): SVGAnimatedLength;
        }
        
        interface SVGAnimatedPoints {
            points: SVGPointList;
            animatedPoints: SVGPointList;
        }
        
        interface SVGDefsElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
        }
        declare var SVGDefsElement: {
            prototype: SVGDefsElement;
            new(): SVGDefsElement;
        }
        
        interface HTMLQuoteElement extends HTMLElement {
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
        }
        declare var HTMLQuoteElement: {
            prototype: HTMLQuoteElement;
            new(): HTMLQuoteElement;
        }
        
        interface CSSMediaRule extends CSSRule {
            media: MediaList;
            cssRules: CSSRuleList;
            insertRule(rule: string, index?: number): number;
            deleteRule(index?: number): void;
        }
        declare var CSSMediaRule: {
            prototype: CSSMediaRule;
            new(): CSSMediaRule;
        }
        
        interface WindowModal {
            dialogArguments: any;
            returnValue: any;
        }
        
        interface XMLHttpRequest extends EventTarget {
            responseBody: any;
            status: number;
            readyState: number;
            responseText: string;
            responseXML: any;
            ontimeout: (ev: Event) => any;
            statusText: string;
            onreadystatechange: (ev: Event) => any;
            timeout: number;
            onload: (ev: Event) => any;
            response: any;
            withCredentials: boolean;
            onprogress: (ev: ProgressEvent) => any;
            onabort: (ev: UIEvent) => any;
            responseType: string;
            onloadend: (ev: ProgressEvent) => any;
            upload: XMLHttpRequestEventTarget;
            onerror: (ev: ErrorEvent) => any;
            onloadstart: (ev: Event) => any;
            msCaching: string;
            open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
            send(data?: any): void;
            abort(): void;
            getAllResponseHeaders(): string;
            setRequestHeader(header: string, value: string): void;
            getResponseHeader(header: string): string;
            msCachingEnabled(): boolean;
            overrideMimeType(mime: string): void;
            LOADING: number;
            DONE: number;
            UNSENT: number;
            OPENED: number;
            HEADERS_RECEIVED: number;
            addEventListener(type: "timeout", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var XMLHttpRequest: {
            prototype: XMLHttpRequest;
            new(): XMLHttpRequest;
            LOADING: number;
            DONE: number;
            UNSENT: number;
            OPENED: number;
            HEADERS_RECEIVED: number;
            create(): XMLHttpRequest;
        }
        
        interface HTMLTableHeaderCellElement extends HTMLTableCellElement {
            /**
              * Sets or retrieves the group of cells in a table to which the object's information applies.
              */
            scope: string;
        }
        declare var HTMLTableHeaderCellElement: {
            prototype: HTMLTableHeaderCellElement;
            new(): HTMLTableHeaderCellElement;
        }
        
        interface HTMLDListElement extends HTMLElement, DOML2DeprecatedListSpaceReduction {
        }
        declare var HTMLDListElement: {
            prototype: HTMLDListElement;
            new(): HTMLDListElement;
        }
        
        interface MSDataBindingExtensions {
            dataSrc: string;
            dataFormatAs: string;
            dataFld: string;
        }
        
        interface SVGPathSegLinetoHorizontalRel extends SVGPathSeg {
            x: number;
        }
        declare var SVGPathSegLinetoHorizontalRel: {
            prototype: SVGPathSegLinetoHorizontalRel;
            new(): SVGPathSegLinetoHorizontalRel;
        }
        
        interface SVGEllipseElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            ry: SVGAnimatedLength;
            cx: SVGAnimatedLength;
            rx: SVGAnimatedLength;
            cy: SVGAnimatedLength;
        }
        declare var SVGEllipseElement: {
            prototype: SVGEllipseElement;
            new(): SVGEllipseElement;
        }
        
        interface SVGAElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired, SVGURIReference {
            target: SVGAnimatedString;
        }
        declare var SVGAElement: {
            prototype: SVGAElement;
            new(): SVGAElement;
        }
        
        interface SVGStylable {
            className: SVGAnimatedString;
            style: CSSStyleDeclaration;
        }
        
        interface SVGTransformable extends SVGLocatable {
            transform: SVGAnimatedTransformList;
        }
        
        interface HTMLFrameSetElement extends HTMLElement {
            ononline: (ev: Event) => any;
            /**
              * Sets or retrieves the border color of the object.
              */
            borderColor: any;
            /**
              * Sets or retrieves the frame heights of the object.
              */
            rows: string;
            /**
              * Sets or retrieves the frame widths of the object.
              */
            cols: string;
            /**
              * Fires when the object loses the input focus.
              */
            onblur: (ev: FocusEvent) => any;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            /**
              * Fires when the object receives focus.
              */
            onfocus: (ev: FocusEvent) => any;
            onmessage: (ev: MessageEvent) => any;
            onerror: (ev: ErrorEvent) => any;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            onresize: (ev: UIEvent) => any;
            name: string;
            onafterprint: (ev: Event) => any;
            onbeforeprint: (ev: Event) => any;
            onoffline: (ev: Event) => any;
            border: string;
            onunload: (ev: Event) => any;
            onhashchange: (ev: Event) => any;
            onload: (ev: Event) => any;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            onstorage: (ev: StorageEvent) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLFrameSetElement: {
            prototype: HTMLFrameSetElement;
            new(): HTMLFrameSetElement;
        }
        
        interface Screen extends EventTarget {
            width: number;
            deviceXDPI: number;
            fontSmoothingEnabled: boolean;
            bufferDepth: number;
            logicalXDPI: number;
            systemXDPI: number;
            availHeight: number;
            height: number;
            logicalYDPI: number;
            systemYDPI: number;
            updateInterval: number;
            colorDepth: number;
            availWidth: number;
            deviceYDPI: number;
            pixelDepth: number;
            msOrientation: string;
            onmsorientationchange: (ev: any) => any;
            msLockOrientation(orientation: string): boolean;
            msLockOrientation(orientations: string[]): boolean;
            msUnlockOrientation(): void;
            addEventListener(type: "msorientationchange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var Screen: {
            prototype: Screen;
            new(): Screen;
        }
        
        interface Coordinates {
            altitudeAccuracy: number;
            longitude: number;
            latitude: number;
            speed: number;
            heading: number;
            altitude: number;
            accuracy: number;
        }
        declare var Coordinates: {
            prototype: Coordinates;
            new(): Coordinates;
        }
        
        interface NavigatorGeolocation {
            geolocation: Geolocation;
        }
        
        interface NavigatorContentUtils {
        }
        
        interface EventListener {
            (evt: Event): void;
        }
        
        interface SVGLangSpace {
            xmllang: string;
            xmlspace: string;
        }
        
        interface DataTransfer {
            effectAllowed: string;
            dropEffect: string;
            types: DOMStringList;
            files: FileList;
            clearData(format?: string): boolean;
            setData(format: string, data: string): boolean;
            getData(format: string): string;
        }
        declare var DataTransfer: {
            prototype: DataTransfer;
            new(): DataTransfer;
        }
        
        interface FocusEvent extends UIEvent {
            relatedTarget: EventTarget;
            initFocusEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, relatedTargetArg: EventTarget): void;
        }
        declare var FocusEvent: {
            prototype: FocusEvent;
            new(): FocusEvent;
        }
        
        interface Range {
            startOffset: number;
            collapsed: boolean;
            endOffset: number;
            startContainer: Node;
            endContainer: Node;
            commonAncestorContainer: Node;
            setStart(refNode: Node, offset: number): void;
            setEndBefore(refNode: Node): void;
            setStartBefore(refNode: Node): void;
            selectNode(refNode: Node): void;
            detach(): void;
            getBoundingClientRect(): ClientRect;
            toString(): string;
            compareBoundaryPoints(how: number, sourceRange: Range): number;
            insertNode(newNode: Node): void;
            collapse(toStart: boolean): void;
            selectNodeContents(refNode: Node): void;
            cloneContents(): DocumentFragment;
            setEnd(refNode: Node, offset: number): void;
            cloneRange(): Range;
            getClientRects(): ClientRectList;
            surroundContents(newParent: Node): void;
            deleteContents(): void;
            setStartAfter(refNode: Node): void;
            extractContents(): DocumentFragment;
            setEndAfter(refNode: Node): void;
            createContextualFragment(fragment: string): DocumentFragment;
            END_TO_END: number;
            START_TO_START: number;
            START_TO_END: number;
            END_TO_START: number;
        }
        declare var Range: {
            prototype: Range;
            new(): Range;
            END_TO_END: number;
            START_TO_START: number;
            START_TO_END: number;
            END_TO_START: number;
        }
        
        interface SVGPoint {
            y: number;
            x: number;
            matrixTransform(matrix: SVGMatrix): SVGPoint;
        }
        declare var SVGPoint: {
            prototype: SVGPoint;
            new(): SVGPoint;
        }
        
        interface MSPluginsCollection {
            length: number;
            refresh(reload?: boolean): void;
        }
        declare var MSPluginsCollection: {
            prototype: MSPluginsCollection;
            new(): MSPluginsCollection;
        }
        
        interface SVGAnimatedNumberList {
            animVal: SVGNumberList;
            baseVal: SVGNumberList;
        }
        declare var SVGAnimatedNumberList: {
            prototype: SVGAnimatedNumberList;
            new(): SVGAnimatedNumberList;
        }
        
        interface SVGSVGElement extends SVGElement, SVGStylable, SVGZoomAndPan, DocumentEvent, SVGLangSpace, SVGLocatable, SVGTests, SVGFitToViewBox, SVGExternalResourcesRequired {
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            contentStyleType: string;
            onzoom: (ev: any) => any;
            y: SVGAnimatedLength;
            viewport: SVGRect;
            onerror: (ev: ErrorEvent) => any;
            pixelUnitToMillimeterY: number;
            onresize: (ev: UIEvent) => any;
            screenPixelToMillimeterY: number;
            height: SVGAnimatedLength;
            onabort: (ev: UIEvent) => any;
            contentScriptType: string;
            pixelUnitToMillimeterX: number;
            currentTranslate: SVGPoint;
            onunload: (ev: Event) => any;
            currentScale: number;
            onscroll: (ev: UIEvent) => any;
            screenPixelToMillimeterX: number;
            setCurrentTime(seconds: number): void;
            createSVGLength(): SVGLength;
            getIntersectionList(rect: SVGRect, referenceElement: SVGElement): NodeList;
            unpauseAnimations(): void;
            createSVGRect(): SVGRect;
            checkIntersection(element: SVGElement, rect: SVGRect): boolean;
            unsuspendRedrawAll(): void;
            pauseAnimations(): void;
            suspendRedraw(maxWaitMilliseconds: number): number;
            deselectAll(): void;
            createSVGAngle(): SVGAngle;
            getEnclosureList(rect: SVGRect, referenceElement: SVGElement): NodeList;
            createSVGTransform(): SVGTransform;
            unsuspendRedraw(suspendHandleID: number): void;
            forceRedraw(): void;
            getCurrentTime(): number;
            checkEnclosure(element: SVGElement, rect: SVGRect): boolean;
            createSVGMatrix(): SVGMatrix;
            createSVGPoint(): SVGPoint;
            createSVGNumber(): SVGNumber;
            createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;
            getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
            getElementById(elementId: string): Element;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "zoom", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var SVGSVGElement: {
            prototype: SVGSVGElement;
            new(): SVGSVGElement;
        }
        
        interface HTMLLabelElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves the object to which the given label object is assigned.
              */
            htmlFor: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
        }
        declare var HTMLLabelElement: {
            prototype: HTMLLabelElement;
            new(): HTMLLabelElement;
        }
        
        interface MSResourceMetadata {
            protocol: string;
            fileSize: string;
            fileUpdatedDate: string;
            nameProp: string;
            fileCreatedDate: string;
            fileModifiedDate: string;
            mimeType: string;
        }
        
        interface HTMLLegendElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            align: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
        }
        declare var HTMLLegendElement: {
            prototype: HTMLLegendElement;
            new(): HTMLLegendElement;
        }
        
        interface HTMLDirectoryElement extends HTMLElement, DOML2DeprecatedListSpaceReduction, DOML2DeprecatedListNumberingAndBulletStyle {
        }
        declare var HTMLDirectoryElement: {
            prototype: HTMLDirectoryElement;
            new(): HTMLDirectoryElement;
        }
        
        interface SVGAnimatedInteger {
            animVal: number;
            baseVal: number;
        }
        declare var SVGAnimatedInteger: {
            prototype: SVGAnimatedInteger;
            new(): SVGAnimatedInteger;
        }
        
        interface SVGTextElement extends SVGTextPositioningElement, SVGTransformable {
        }
        declare var SVGTextElement: {
            prototype: SVGTextElement;
            new(): SVGTextElement;
        }
        
        interface SVGTSpanElement extends SVGTextPositioningElement {
        }
        declare var SVGTSpanElement: {
            prototype: SVGTSpanElement;
            new(): SVGTSpanElement;
        }
        
        interface HTMLLIElement extends HTMLElement, DOML2DeprecatedListNumberingAndBulletStyle {
            /**
              * Sets or retrieves the value of a list item.
              */
            value: number;
        }
        declare var HTMLLIElement: {
            prototype: HTMLLIElement;
            new(): HTMLLIElement;
        }
        
        interface SVGPathSegLinetoVerticalAbs extends SVGPathSeg {
            y: number;
        }
        declare var SVGPathSegLinetoVerticalAbs: {
            prototype: SVGPathSegLinetoVerticalAbs;
            new(): SVGPathSegLinetoVerticalAbs;
        }
        
        interface MSStorageExtensions {
            remainingSpace: number;
        }
        
        interface SVGStyleElement extends SVGElement, SVGLangSpace {
            media: string;
            type: string;
            title: string;
        }
        declare var SVGStyleElement: {
            prototype: SVGStyleElement;
            new(): SVGStyleElement;
        }
        
        interface MSCurrentStyleCSSProperties extends MSCSSProperties {
            blockDirection: string;
            clipBottom: string;
            clipLeft: string;
            clipRight: string;
            clipTop: string;
            hasLayout: string;
        }
        declare var MSCurrentStyleCSSProperties: {
            prototype: MSCurrentStyleCSSProperties;
            new(): MSCurrentStyleCSSProperties;
        }
        
        interface MSHTMLCollectionExtensions {
            urns(urn: any): any;
            tags(tagName: any): any;
        }
        
        interface Storage extends MSStorageExtensions {
            length: number;
            getItem(key: string): any;
            [key: string]: any;
            setItem(key: string, data: string): void;
            clear(): void;
            removeItem(key: string): void;
            key(index: number): string;
            [index: number]: string;
        }
        declare var Storage: {
            prototype: Storage;
            new(): Storage;
        }
        
        interface HTMLIFrameElement extends HTMLElement, GetSVGDocument, MSDataBindingExtensions {
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Sets or retrieves whether the frame can be scrolled.
              */
            scrolling: string;
            /**
              * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.
              */
            marginHeight: string;
            /**
              * Sets or retrieves the left and right margin widths before displaying the text in a frame.
              */
            marginWidth: string;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            /**
              * Sets or retrieves whether the user can resize the frame.
              */
            noResize: boolean;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * Retrieves the object of the specified.
              */
            contentWindow: Window;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the frame name.
              */
            name: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Sets or retrieves the horizontal margin for the object.
              */
            hspace: number;
            /**
              * Sets or retrieves a URI to a long description of the object.
              */
            longDesc: string;
            /**
              * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied.
              */
            security: any;
            /**
              * Raised when the object has been completely received from the server.
              */
            onload: (ev: Event) => any;
            sandbox: DOMSettableTokenList;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLIFrameElement: {
            prototype: HTMLIFrameElement;
            new(): HTMLIFrameElement;
        }
        
        interface TextRangeCollection {
            length: number;
            item(index: number): TextRange;
            [index: number]: TextRange;
        }
        declare var TextRangeCollection: {
            prototype: TextRangeCollection;
            new(): TextRangeCollection;
        }
        
        interface HTMLBodyElement extends HTMLElement, DOML2DeprecatedBackgroundStyle, DOML2DeprecatedBackgroundColorStyle {
            scroll: string;
            ononline: (ev: Event) => any;
            onblur: (ev: FocusEvent) => any;
            noWrap: boolean;
            onfocus: (ev: FocusEvent) => any;
            onmessage: (ev: MessageEvent) => any;
            text: any;
            onerror: (ev: ErrorEvent) => any;
            bgProperties: string;
            onresize: (ev: UIEvent) => any;
            link: any;
            aLink: any;
            bottomMargin: any;
            topMargin: any;
            onafterprint: (ev: Event) => any;
            vLink: any;
            onbeforeprint: (ev: Event) => any;
            onoffline: (ev: Event) => any;
            onunload: (ev: Event) => any;
            onhashchange: (ev: Event) => any;
            onload: (ev: Event) => any;
            rightMargin: any;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            leftMargin: any;
            onstorage: (ev: StorageEvent) => any;
            onpopstate: (ev: PopStateEvent) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            createTextRange(): TextRange;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLBodyElement: {
            prototype: HTMLBodyElement;
            new(): HTMLBodyElement;
        }
        
        interface DocumentType extends Node {
            name: string;
            notations: NamedNodeMap;
            systemId: string;
            internalSubset: string;
            entities: NamedNodeMap;
            publicId: string;
        }
        declare var DocumentType: {
            prototype: DocumentType;
            new(): DocumentType;
        }
        
        interface SVGRadialGradientElement extends SVGGradientElement {
            cx: SVGAnimatedLength;
            r: SVGAnimatedLength;
            cy: SVGAnimatedLength;
            fx: SVGAnimatedLength;
            fy: SVGAnimatedLength;
        }
        declare var SVGRadialGradientElement: {
            prototype: SVGRadialGradientElement;
            new(): SVGRadialGradientElement;
        }
        
        interface MutationEvent extends Event {
            newValue: string;
            attrChange: number;
            attrName: string;
            prevValue: string;
            relatedNode: Node;
            initMutationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, relatedNodeArg: Node, prevValueArg: string, newValueArg: string, attrNameArg: string, attrChangeArg: number): void;
            MODIFICATION: number;
            REMOVAL: number;
            ADDITION: number;
        }
        declare var MutationEvent: {
            prototype: MutationEvent;
            new(): MutationEvent;
            MODIFICATION: number;
            REMOVAL: number;
            ADDITION: number;
        }
        
        interface DragEvent extends MouseEvent {
            dataTransfer: DataTransfer;
            initDragEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, dataTransferArg: DataTransfer): void;
            msConvertURL(file: File, targetType: string, targetURL?: string): void;
        }
        declare var DragEvent: {
            prototype: DragEvent;
            new(): DragEvent;
        }
        
        interface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment, DOML2DeprecatedBackgroundColorStyle {
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: HTMLCollection;
            /**
              * Removes the specified row (tr) from the element and from the rows collection.
              * @param index Number that specifies the zero-based position in the rows collection of the row to remove.
              */
            deleteRow(index?: number): void;
            /**
              * Moves a table row to a new position.
              * @param indexFrom Number that specifies the index in the rows collection of the table row that is moved.
              * @param indexTo Number that specifies where the row is moved within the rows collection.
              */
            moveRow(indexFrom?: number, indexTo?: number): any;
            /**
              * Creates a new row (tr) in the table, and adds the row to the rows collection.
              * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
              */
            insertRow(index?: number): HTMLElement;
        }
        declare var HTMLTableSectionElement: {
            prototype: HTMLTableSectionElement;
            new(): HTMLTableSectionElement;
        }
        
        interface DOML2DeprecatedListNumberingAndBulletStyle {
            type: string;
        }
        
        interface HTMLInputElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            status: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            /**
              * Gets or sets the starting position or offset of a text selection.
              */
            selectionStart: number;
            indeterminate: boolean;
            readOnly: boolean;
            size: number;
            loop: number;
            /**
              * Gets or sets the end position or offset of a text selection.
              */
            selectionEnd: number;
            /**
              * Sets or retrieves the URL of the virtual reality modeling language (VRML) world to be displayed in the window.
              */
            vrml: string;
            /**
              * Sets or retrieves a lower resolution image to display.
              */
            lowsrc: string;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * Sets or retrieves a comma-separated list of content types.
              */
            accept: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves the state of the check box or radio button.
              */
            defaultChecked: boolean;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Returns the value of the data at the cursor's current position.
              */
            value: string;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            border: string;
            dynsrc: string;
            /**
              * Sets or retrieves the state of the check box or radio button.
              */
            checked: boolean;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            hspace: number;
            /**
              * Sets or retrieves the maximum number of characters that the user can enter in a text control.
              */
            maxLength: number;
            /**
              * Returns the content type of the object.
              */
            type: string;
            /**
              * Sets or retrieves the initial contents of the object.
              */
            defaultValue: string;
            /**
              * Retrieves whether the object is fully loaded.
              */
            complete: boolean;
            start: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a FileList object on a file type input object.
              */
            files: FileList;
            /**
              * Defines the maximum acceptable value for an input element with type="number".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field.
              */
            max: string;
            /**
              * Overrides the target attribute on a form element.
              */
            formTarget: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Defines an increment or jump between values that you want to allow the user to enter. When used with the max and min attributes, lets you control the range and increment (for example, allow only even numbers) that the user can enter into an input field.
              */
            step: string;
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Used to override the encoding (formEnctype attribute) specified on the form element.
              */
            formEnctype: string;
            /**
              * Returns the input field value as a number.
              */
            valueAsNumber: number;
            /**
              * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.
              */
            placeholder: string;
            /**
              * Overrides the submit method attribute previously specified on a form element.
              */
            formMethod: string;
            /**
              * Specifies the ID of a pre-defined datalist of options for an input element.
              */
            list: HTMLElement;
            /**
              * Specifies whether autocomplete is applied to an editable text field.
              */
            autocomplete: string;
            /**
              * Defines the minimum acceptable value for an input element with type="number". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field.
              */
            min: string;
            /**
              * Overrides the action attribute (where the data on a form is sent) on the parent form element.
              */
            formAction: string;
            /**
              * Gets or sets a string containing a regular expression that the user's input must match.
              */
            pattern: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option.
              */
            formNoValidate: string;
            /**
              * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.
              */
            multiple: boolean;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Sets the start and end positions of a selection in a text field.
              * @param start The offset into the text field for the start of the selection.
              * @param end The offset into the text field for the end of the selection.
              */
            setSelectionRange(start: number, end: number): void;
            /**
              * Makes the selection equal to the current object.
              */
            select(): void;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Decrements a range input control's value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control's step value multiplied by the parameter's value.
              * @param n Value to decrement the value by.
              */
            stepDown(n?: number): void;
            /**
              * Increments a range input control's value by the value given by the Step attribute. If the optional parameter is used, will increment the input control's value by that value.
              * @param n Value to increment the value by.
              */
            stepUp(n?: number): void;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLInputElement: {
            prototype: HTMLInputElement;
            new(): HTMLInputElement;
        }
        
        interface HTMLAnchorElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rel: string;
            /**
              * Contains the protocol of the URL.
              */
            protocol: string;
            /**
              * Sets or retrieves the substring of the href property that follows the question mark.
              */
            search: string;
            /**
              * Sets or retrieves the coordinates of the object.
              */
            coords: string;
            /**
              * Contains the hostname of a URL.
              */
            hostname: string;
            /**
              * Contains the pathname of the URL.
              */
            pathname: string;
            Methods: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            protocolLong: string;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            name: string;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Sets or retrieves the language code of the object.
              */
            hreflang: string;
            /**
              * Sets or retrieves the port number associated with a URL.
              */
            port: string;
            /**
              * Contains the hostname and port values of the URL.
              */
            host: string;
            /**
              * Contains the anchor portion of the URL including the hash sign (#).
              */
            hash: string;
            nameProp: string;
            urn: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rev: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            shape: string;
            type: string;
            mimeType: string;
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
            /** 
              * Returns a string representation of an object.
              */
            toString(): string;
        }
        declare var HTMLAnchorElement: {
            prototype: HTMLAnchorElement;
            new(): HTMLAnchorElement;
        }
        
        interface HTMLParamElement extends HTMLElement {
            /**
              * Sets or retrieves the value of an input parameter for an element.
              */
            value: string;
            /**
              * Sets or retrieves the name of an input parameter for an element.
              */
            name: string;
            /**
              * Sets or retrieves the content type of the resource designated by the value attribute.
              */
            type: string;
            /**
              * Sets or retrieves the data type of the value attribute.
              */
            valueType: string;
        }
        declare var HTMLParamElement: {
            prototype: HTMLParamElement;
            new(): HTMLParamElement;
        }
        
        interface SVGImageElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired, SVGURIReference {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
        }
        declare var SVGImageElement: {
            prototype: SVGImageElement;
            new(): SVGImageElement;
        }
        
        interface SVGAnimatedNumber {
            animVal: number;
            baseVal: number;
        }
        declare var SVGAnimatedNumber: {
            prototype: SVGAnimatedNumber;
            new(): SVGAnimatedNumber;
        }
        
        interface PerformanceTiming {
            redirectStart: number;
            domainLookupEnd: number;
            responseStart: number;
            domComplete: number;
            domainLookupStart: number;
            loadEventStart: number;
            msFirstPaint: number;
            unloadEventEnd: number;
            fetchStart: number;
            requestStart: number;
            domInteractive: number;
            navigationStart: number;
            connectEnd: number;
            loadEventEnd: number;
            connectStart: number;
            responseEnd: number;
            domLoading: number;
            redirectEnd: number;
            unloadEventStart: number;
            domContentLoadedEventStart: number;
            domContentLoadedEventEnd: number;
            toJSON(): any;
        }
        declare var PerformanceTiming: {
            prototype: PerformanceTiming;
            new(): PerformanceTiming;
        }
        
        interface HTMLPreElement extends HTMLElement, DOML2DeprecatedTextFlowControl {
            /**
              * Sets or gets a value that you can use to implement your own width functionality for the object.
              */
            width: number;
            /**
              * Indicates a citation by rendering text in italic type.
              */
            cite: string;
        }
        declare var HTMLPreElement: {
            prototype: HTMLPreElement;
            new(): HTMLPreElement;
        }
        
        interface EventException {
            code: number;
            message: string;
            name: string;
            toString(): string;
            DISPATCH_REQUEST_ERR: number;
            UNSPECIFIED_EVENT_TYPE_ERR: number;
        }
        declare var EventException: {
            prototype: EventException;
            new(): EventException;
            DISPATCH_REQUEST_ERR: number;
            UNSPECIFIED_EVENT_TYPE_ERR: number;
        }
        
        interface MSNavigatorDoNotTrack {
            msDoNotTrack: string;
            removeSiteSpecificTrackingException(args: ExceptionInformation): void;
            removeWebWideTrackingException(args: ExceptionInformation): void;
            storeWebWideTrackingException(args: StoreExceptionsInformation): void;
            storeSiteSpecificTrackingException(args: StoreSiteSpecificExceptionsInformation): void;
            confirmSiteSpecificTrackingException(args: ConfirmSiteSpecificExceptionsInformation): boolean;
            confirmWebWideTrackingException(args: ExceptionInformation): boolean;
        }
        
        interface NavigatorOnLine {
            onLine: boolean;
        }
        
        interface WindowLocalStorage {
            localStorage: Storage;
        }
        
        interface SVGMetadataElement extends SVGElement {
        }
        declare var SVGMetadataElement: {
            prototype: SVGMetadataElement;
            new(): SVGMetadataElement;
        }
        
        interface SVGPathSegArcRel extends SVGPathSeg {
            y: number;
            sweepFlag: boolean;
            r2: number;
            x: number;
            angle: number;
            r1: number;
            largeArcFlag: boolean;
        }
        declare var SVGPathSegArcRel: {
            prototype: SVGPathSegArcRel;
            new(): SVGPathSegArcRel;
        }
        
        interface SVGPathSegMovetoAbs extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegMovetoAbs: {
            prototype: SVGPathSegMovetoAbs;
            new(): SVGPathSegMovetoAbs;
        }
        
        interface SVGStringList {
            numberOfItems: number;
            replaceItem(newItem: string, index: number): string;
            getItem(index: number): string;
            clear(): void;
            appendItem(newItem: string): string;
            initialize(newItem: string): string;
            removeItem(index: number): string;
            insertItemBefore(newItem: string, index: number): string;
        }
        declare var SVGStringList: {
            prototype: SVGStringList;
            new(): SVGStringList;
        }
        
        interface XDomainRequest {
            timeout: number;
            onerror: (ev: ErrorEvent) => any;
            onload: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            ontimeout: (ev: Event) => any;
            responseText: string;
            contentType: string;
            open(method: string, url: string): void;
            abort(): void;
            send(data?: any): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeout", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var XDomainRequest: {
            prototype: XDomainRequest;
            new(): XDomainRequest;
            create(): XDomainRequest;
        }
        
        interface DOML2DeprecatedBackgroundColorStyle {
            bgColor: any;
        }
        
        interface ElementTraversal {
            childElementCount: number;
            previousElementSibling: Element;
            lastElementChild: Element;
            nextElementSibling: Element;
            firstElementChild: Element;
        }
        
        interface SVGLength {
            valueAsString: string;
            valueInSpecifiedUnits: number;
            value: number;
            unitType: number;
            newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;
            convertToSpecifiedUnits(unitType: number): void;
            SVG_LENGTHTYPE_NUMBER: number;
            SVG_LENGTHTYPE_CM: number;
            SVG_LENGTHTYPE_PC: number;
            SVG_LENGTHTYPE_PERCENTAGE: number;
            SVG_LENGTHTYPE_MM: number;
            SVG_LENGTHTYPE_PT: number;
            SVG_LENGTHTYPE_IN: number;
            SVG_LENGTHTYPE_EMS: number;
            SVG_LENGTHTYPE_PX: number;
            SVG_LENGTHTYPE_UNKNOWN: number;
            SVG_LENGTHTYPE_EXS: number;
        }
        declare var SVGLength: {
            prototype: SVGLength;
            new(): SVGLength;
            SVG_LENGTHTYPE_NUMBER: number;
            SVG_LENGTHTYPE_CM: number;
            SVG_LENGTHTYPE_PC: number;
            SVG_LENGTHTYPE_PERCENTAGE: number;
            SVG_LENGTHTYPE_MM: number;
            SVG_LENGTHTYPE_PT: number;
            SVG_LENGTHTYPE_IN: number;
            SVG_LENGTHTYPE_EMS: number;
            SVG_LENGTHTYPE_PX: number;
            SVG_LENGTHTYPE_UNKNOWN: number;
            SVG_LENGTHTYPE_EXS: number;
        }
        
        interface SVGPolygonElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGAnimatedPoints, SVGTests, SVGExternalResourcesRequired {
        }
        declare var SVGPolygonElement: {
            prototype: SVGPolygonElement;
            new(): SVGPolygonElement;
        }
        
        interface HTMLPhraseElement extends HTMLElement {
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
        }
        declare var HTMLPhraseElement: {
            prototype: HTMLPhraseElement;
            new(): HTMLPhraseElement;
        }
        
        interface NavigatorStorageUtils {
        }
        
        interface SVGPathSegCurvetoCubicRel extends SVGPathSeg {
            y: number;
            y1: number;
            x2: number;
            x: number;
            x1: number;
            y2: number;
        }
        declare var SVGPathSegCurvetoCubicRel: {
            prototype: SVGPathSegCurvetoCubicRel;
            new(): SVGPathSegCurvetoCubicRel;
        }
        
        interface SVGTextContentElement extends SVGElement, SVGStylable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            textLength: SVGAnimatedLength;
            lengthAdjust: SVGAnimatedEnumeration;
            getCharNumAtPosition(point: SVGPoint): number;
            getStartPositionOfChar(charnum: number): SVGPoint;
            getExtentOfChar(charnum: number): SVGRect;
            getComputedTextLength(): number;
            getSubStringLength(charnum: number, nchars: number): number;
            selectSubString(charnum: number, nchars: number): void;
            getNumberOfChars(): number;
            getRotationOfChar(charnum: number): number;
            getEndPositionOfChar(charnum: number): SVGPoint;
            LENGTHADJUST_SPACING: number;
            LENGTHADJUST_SPACINGANDGLYPHS: number;
            LENGTHADJUST_UNKNOWN: number;
        }
        declare var SVGTextContentElement: {
            prototype: SVGTextContentElement;
            new(): SVGTextContentElement;
            LENGTHADJUST_SPACING: number;
            LENGTHADJUST_SPACINGANDGLYPHS: number;
            LENGTHADJUST_UNKNOWN: number;
        }
        
        interface DOML2DeprecatedColorProperty {
            color: string;
        }
        
        interface Location {
            hash: string;
            protocol: string;
            search: string;
            href: string;
            hostname: string;
            port: string;
            pathname: string;
            host: string;
            reload(flag?: boolean): void;
            replace(url: string): void;
            assign(url: string): void;
            toString(): string;
        }
        declare var Location: {
            prototype: Location;
            new(): Location;
        }
        
        interface HTMLTitleElement extends HTMLElement {
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
        }
        declare var HTMLTitleElement: {
            prototype: HTMLTitleElement;
            new(): HTMLTitleElement;
        }
        
        interface HTMLStyleElement extends HTMLElement, LinkStyle {
            /**
              * Sets or retrieves the media type.
              */
            media: string;
            /**
              * Retrieves the CSS language in which the style sheet is written.
              */
            type: string;
        }
        declare var HTMLStyleElement: {
            prototype: HTMLStyleElement;
            new(): HTMLStyleElement;
        }
        
        interface PerformanceEntry {
            name: string;
            startTime: number;
            duration: number;
            entryType: string;
        }
        declare var PerformanceEntry: {
            prototype: PerformanceEntry;
            new(): PerformanceEntry;
        }
        
        interface SVGTransform {
            type: number;
            angle: number;
            matrix: SVGMatrix;
            setTranslate(tx: number, ty: number): void;
            setScale(sx: number, sy: number): void;
            setMatrix(matrix: SVGMatrix): void;
            setSkewY(angle: number): void;
            setRotate(angle: number, cx: number, cy: number): void;
            setSkewX(angle: number): void;
            SVG_TRANSFORM_SKEWX: number;
            SVG_TRANSFORM_UNKNOWN: number;
            SVG_TRANSFORM_SCALE: number;
            SVG_TRANSFORM_TRANSLATE: number;
            SVG_TRANSFORM_MATRIX: number;
            SVG_TRANSFORM_ROTATE: number;
            SVG_TRANSFORM_SKEWY: number;
        }
        declare var SVGTransform: {
            prototype: SVGTransform;
            new(): SVGTransform;
            SVG_TRANSFORM_SKEWX: number;
            SVG_TRANSFORM_UNKNOWN: number;
            SVG_TRANSFORM_SCALE: number;
            SVG_TRANSFORM_TRANSLATE: number;
            SVG_TRANSFORM_MATRIX: number;
            SVG_TRANSFORM_ROTATE: number;
            SVG_TRANSFORM_SKEWY: number;
        }
        
        interface UIEvent extends Event {
            detail: number;
            view: Window;
            initUIEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number): void;
        }
        declare var UIEvent: {
            prototype: UIEvent;
            new(): UIEvent;
        }
        
        interface SVGURIReference {
            href: SVGAnimatedString;
        }
        
        interface SVGPathSeg {
            pathSegType: number;
            pathSegTypeAsLetter: string;
            PATHSEG_MOVETO_REL: number;
            PATHSEG_LINETO_VERTICAL_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_REL: number;
            PATHSEG_CURVETO_CUBIC_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_ABS: number;
            PATHSEG_LINETO_ABS: number;
            PATHSEG_CLOSEPATH: number;
            PATHSEG_LINETO_HORIZONTAL_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;
            PATHSEG_LINETO_REL: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;
            PATHSEG_ARC_REL: number;
            PATHSEG_CURVETO_CUBIC_REL: number;
            PATHSEG_UNKNOWN: number;
            PATHSEG_LINETO_VERTICAL_ABS: number;
            PATHSEG_ARC_ABS: number;
            PATHSEG_MOVETO_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;
        }
        declare var SVGPathSeg: {
            prototype: SVGPathSeg;
            new(): SVGPathSeg;
            PATHSEG_MOVETO_REL: number;
            PATHSEG_LINETO_VERTICAL_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_REL: number;
            PATHSEG_CURVETO_CUBIC_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_ABS: number;
            PATHSEG_LINETO_ABS: number;
            PATHSEG_CLOSEPATH: number;
            PATHSEG_LINETO_HORIZONTAL_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;
            PATHSEG_LINETO_REL: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;
            PATHSEG_ARC_REL: number;
            PATHSEG_CURVETO_CUBIC_REL: number;
            PATHSEG_UNKNOWN: number;
            PATHSEG_LINETO_VERTICAL_ABS: number;
            PATHSEG_ARC_ABS: number;
            PATHSEG_MOVETO_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;
        }
        
        interface WheelEvent extends MouseEvent {
            deltaZ: number;
            deltaX: number;
            deltaMode: number;
            deltaY: number;
            initWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, deltaXArg: number, deltaYArg: number, deltaZArg: number, deltaMode: number): void;
            getCurrentPoint(element: Element): void;
            DOM_DELTA_PIXEL: number;
            DOM_DELTA_LINE: number;
            DOM_DELTA_PAGE: number;
        }
        declare var WheelEvent: {
            prototype: WheelEvent;
            new(): WheelEvent;
            DOM_DELTA_PIXEL: number;
            DOM_DELTA_LINE: number;
            DOM_DELTA_PAGE: number;
        }
        
        interface MSEventAttachmentTarget {
            attachEvent(event: string, listener: EventListener): boolean;
            detachEvent(event: string, listener: EventListener): void;
        }
        
        interface SVGNumber {
            value: number;
        }
        declare var SVGNumber: {
            prototype: SVGNumber;
            new(): SVGNumber;
        }
        
        interface SVGPathElement extends SVGElement, SVGStylable, SVGAnimatedPathData, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            getPathSegAtLength(distance: number): number;
            getPointAtLength(distance: number): SVGPoint;
            createSVGPathSegCurvetoQuadraticAbs(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticAbs;
            createSVGPathSegLinetoRel(x: number, y: number): SVGPathSegLinetoRel;
            createSVGPathSegCurvetoQuadraticRel(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticRel;
            createSVGPathSegCurvetoCubicAbs(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicAbs;
            createSVGPathSegLinetoAbs(x: number, y: number): SVGPathSegLinetoAbs;
            createSVGPathSegClosePath(): SVGPathSegClosePath;
            createSVGPathSegCurvetoCubicRel(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicRel;
            createSVGPathSegCurvetoQuadraticSmoothRel(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothRel;
            createSVGPathSegMovetoRel(x: number, y: number): SVGPathSegMovetoRel;
            createSVGPathSegCurvetoCubicSmoothAbs(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothAbs;
            createSVGPathSegMovetoAbs(x: number, y: number): SVGPathSegMovetoAbs;
            createSVGPathSegLinetoVerticalRel(y: number): SVGPathSegLinetoVerticalRel;
            createSVGPathSegArcRel(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcRel;
            createSVGPathSegCurvetoQuadraticSmoothAbs(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothAbs;
            createSVGPathSegLinetoHorizontalRel(x: number): SVGPathSegLinetoHorizontalRel;
            getTotalLength(): number;
            createSVGPathSegCurvetoCubicSmoothRel(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothRel;
            createSVGPathSegLinetoHorizontalAbs(x: number): SVGPathSegLinetoHorizontalAbs;
            createSVGPathSegLinetoVerticalAbs(y: number): SVGPathSegLinetoVerticalAbs;
            createSVGPathSegArcAbs(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcAbs;
        }
        declare var SVGPathElement: {
            prototype: SVGPathElement;
            new(): SVGPathElement;
        }
        
        interface MSCompatibleInfo {
            version: string;
            userAgent: string;
        }
        declare var MSCompatibleInfo: {
            prototype: MSCompatibleInfo;
            new(): MSCompatibleInfo;
        }
        
        interface Text extends CharacterData, MSNodeExtensions {
            wholeText: string;
            splitText(offset: number): Text;
            replaceWholeText(content: string): Text;
        }
        declare var Text: {
            prototype: Text;
            new(): Text;
        }
        
        interface SVGAnimatedRect {
            animVal: SVGRect;
            baseVal: SVGRect;
        }
        declare var SVGAnimatedRect: {
            prototype: SVGAnimatedRect;
            new(): SVGAnimatedRect;
        }
        
        interface CSSNamespaceRule extends CSSRule {
            namespaceURI: string;
            prefix: string;
        }
        declare var CSSNamespaceRule: {
            prototype: CSSNamespaceRule;
            new(): CSSNamespaceRule;
        }
        
        interface SVGPathSegList {
            numberOfItems: number;
            replaceItem(newItem: SVGPathSeg, index: number): SVGPathSeg;
            getItem(index: number): SVGPathSeg;
            clear(): void;
            appendItem(newItem: SVGPathSeg): SVGPathSeg;
            initialize(newItem: SVGPathSeg): SVGPathSeg;
            removeItem(index: number): SVGPathSeg;
            insertItemBefore(newItem: SVGPathSeg, index: number): SVGPathSeg;
        }
        declare var SVGPathSegList: {
            prototype: SVGPathSegList;
            new(): SVGPathSegList;
        }
        
        interface HTMLUnknownElement extends HTMLElement, MSDataBindingRecordSetReadonlyExtensions {
        }
        declare var HTMLUnknownElement: {
            prototype: HTMLUnknownElement;
            new(): HTMLUnknownElement;
        }
        
        interface HTMLAudioElement extends HTMLMediaElement {
        }
        declare var HTMLAudioElement: {
            prototype: HTMLAudioElement;
            new(): HTMLAudioElement;
        }
        
        interface MSImageResourceExtensions {
            dynsrc: string;
            vrml: string;
            lowsrc: string;
            start: string;
            loop: number;
        }
        
        interface PositionError {
            code: number;
            message: string;
            toString(): string;
            POSITION_UNAVAILABLE: number;
            PERMISSION_DENIED: number;
            TIMEOUT: number;
        }
        declare var PositionError: {
            prototype: PositionError;
            new(): PositionError;
            POSITION_UNAVAILABLE: number;
            PERMISSION_DENIED: number;
            TIMEOUT: number;
        }
        
        interface HTMLTableCellElement extends HTMLElement, HTMLTableAlignment, DOML2DeprecatedBackgroundStyle, DOML2DeprecatedBackgroundColorStyle {
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            /**
              * Sets or retrieves a list of header cells that provide information for the object.
              */
            headers: string;
            /**
              * Retrieves the position of the object in the cells collection of a row.
              */
            cellIndex: number;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorLight: any;
            /**
              * Sets or retrieves the number columns in the table that the object should span.
              */
            colSpan: number;
            /**
              * Sets or retrieves the border color of the object. 
              */
            borderColor: any;
            /**
              * Sets or retrieves a comma-delimited list of conceptual categories associated with the object.
              */
            axis: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
            /**
              * Sets or retrieves abbreviated text for the object.
              */
            abbr: string;
            /**
              * Sets or retrieves how many rows in a table the cell should span.
              */
            rowSpan: number;
            /**
              * Sets or retrieves the group of cells in a table to which the object's information applies.
              */
            scope: string;
            /**
              * Sets or retrieves the color for one of the two colors used to draw the 3-D border of the object.
              */
            borderColorDark: any;
        }
        declare var HTMLTableCellElement: {
            prototype: HTMLTableCellElement;
            new(): HTMLTableCellElement;
        }
        
        interface SVGElementInstance extends EventTarget {
            previousSibling: SVGElementInstance;
            parentNode: SVGElementInstance;
            lastChild: SVGElementInstance;
            nextSibling: SVGElementInstance;
            childNodes: SVGElementInstanceList;
            correspondingUseElement: SVGUseElement;
            correspondingElement: SVGElement;
            firstChild: SVGElementInstance;
        }
        declare var SVGElementInstance: {
            prototype: SVGElementInstance;
            new(): SVGElementInstance;
        }
        
        interface MSNamespaceInfoCollection {
            length: number;
            add(namespace?: string, urn?: string, implementationUrl?: any): any;
            item(index: any): any;
            // [index: any]: any;
        }
        declare var MSNamespaceInfoCollection: {
            prototype: MSNamespaceInfoCollection;
            new(): MSNamespaceInfoCollection;
        }
        
        interface SVGCircleElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            cx: SVGAnimatedLength;
            r: SVGAnimatedLength;
            cy: SVGAnimatedLength;
        }
        declare var SVGCircleElement: {
            prototype: SVGCircleElement;
            new(): SVGCircleElement;
        }
        
        interface StyleSheetList {
            length: number;
            item(index?: number): StyleSheet;
            [index: number]: StyleSheet;
        }
        declare var StyleSheetList: {
            prototype: StyleSheetList;
            new(): StyleSheetList;
        }
        
        interface CSSImportRule extends CSSRule {
            styleSheet: CSSStyleSheet;
            href: string;
            media: MediaList;
        }
        declare var CSSImportRule: {
            prototype: CSSImportRule;
            new(): CSSImportRule;
        }
        
        interface CustomEvent extends Event {
            detail: any;
            initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: any): void;
        }
        declare var CustomEvent: {
            prototype: CustomEvent;
            new(): CustomEvent;
        }
        
        interface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty {
            /**
              * Sets or retrieves the current typeface family.
              */
            face: string;
            /**
              * Sets or retrieves the font size of the object.
              */
            size: number;
        }
        declare var HTMLBaseFontElement: {
            prototype: HTMLBaseFontElement;
            new(): HTMLBaseFontElement;
        }
        
        interface HTMLTextAreaElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Retrieves or sets the text in the entry field of the textArea element.
              */
            value: string;
            /**
              * Sets or retrieves the value indicating whether the control is selected.
              */
            status: any;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Gets or sets the starting position or offset of a text selection.
              */
            selectionStart: number;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: number;
            /**
              * Sets or retrieves the width of the object.
              */
            cols: number;
            /**
              * Sets or retrieves the value indicated whether the content of the object is read-only.
              */
            readOnly: boolean;
            /**
              * Sets or retrieves how to handle wordwrapping in the object.
              */
            wrap: string;
            /**
              * Gets or sets the end position or offset of a text selection.
              */
            selectionEnd: number;
            /**
              * Retrieves the type of control.
              */
            type: string;
            /**
              * Sets or retrieves the initial contents of the object.
              */
            defaultValue: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Sets or retrieves the maximum number of characters that the user can enter in a text control.
              */
            maxLength: number;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.
              */
            placeholder: string;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Sets the start and end positions of a selection in a text field.
              * @param start The offset into the text field for the start of the selection.
              * @param end The offset into the text field for the end of the selection.
              */
            setSelectionRange(start: number, end: number): void;
            /**
              * Highlights the input area of a form element.
              */
            select(): void;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLTextAreaElement: {
            prototype: HTMLTextAreaElement;
            new(): HTMLTextAreaElement;
        }
        
        interface Geolocation {
            clearWatch(watchId: number): void;
            getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): void;
            watchPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): number;
        }
        declare var Geolocation: {
            prototype: Geolocation;
            new(): Geolocation;
        }
        
        interface DOML2DeprecatedMarginStyle {
            vspace: number;
            hspace: number;
        }
        
        interface MSWindowModeless {
            dialogTop: any;
            dialogLeft: any;
            dialogWidth: any;
            dialogHeight: any;
            menuArguments: any;
        }
        
        interface DOML2DeprecatedAlignmentStyle {
            align: string;
        }
        
        interface HTMLMarqueeElement extends HTMLElement, MSDataBindingExtensions, DOML2DeprecatedBackgroundColorStyle {
            width: string;
            onbounce: (ev: Event) => any;
            vspace: number;
            trueSpeed: boolean;
            scrollAmount: number;
            scrollDelay: number;
            behavior: string;
            height: string;
            loop: number;
            direction: string;
            hspace: number;
            onstart: (ev: Event) => any;
            onfinish: (ev: Event) => any;
            stop(): void;
            start(): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "bounce", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "start", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "finish", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLMarqueeElement: {
            prototype: HTMLMarqueeElement;
            new(): HTMLMarqueeElement;
        }
        
        interface SVGRect {
            y: number;
            width: number;
            x: number;
            height: number;
        }
        declare var SVGRect: {
            prototype: SVGRect;
            new(): SVGRect;
        }
        
        interface MSNodeExtensions {
            swapNode(otherNode: Node): Node;
            removeNode(deep?: boolean): Node;
            replaceNode(replacement: Node): Node;
        }
        
        interface History {
            length: number;
            state: any;
            back(distance?: any): void;
            forward(distance?: any): void;
            go(delta?: any): void;
            replaceState(statedata: any, title: string, url?: string): void;
            pushState(statedata: any, title: string, url?: string): void;
        }
        declare var History: {
            prototype: History;
            new(): History;
        }
        
        interface SVGPathSegCurvetoCubicAbs extends SVGPathSeg {
            y: number;
            y1: number;
            x2: number;
            x: number;
            x1: number;
            y2: number;
        }
        declare var SVGPathSegCurvetoCubicAbs: {
            prototype: SVGPathSegCurvetoCubicAbs;
            new(): SVGPathSegCurvetoCubicAbs;
        }
        
        interface SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {
            y: number;
            y1: number;
            x: number;
            x1: number;
        }
        declare var SVGPathSegCurvetoQuadraticAbs: {
            prototype: SVGPathSegCurvetoQuadraticAbs;
            new(): SVGPathSegCurvetoQuadraticAbs;
        }
        
        interface TimeRanges {
            length: number;
            start(index: number): number;
            end(index: number): number;
        }
        declare var TimeRanges: {
            prototype: TimeRanges;
            new(): TimeRanges;
        }
        
        interface CSSRule {
            cssText: string;
            parentStyleSheet: CSSStyleSheet;
            parentRule: CSSRule;
            type: number;
            IMPORT_RULE: number;
            MEDIA_RULE: number;
            STYLE_RULE: number;
            NAMESPACE_RULE: number;
            PAGE_RULE: number;
            UNKNOWN_RULE: number;
            FONT_FACE_RULE: number;
            CHARSET_RULE: number;
            KEYFRAMES_RULE: number;
            KEYFRAME_RULE: number;
            VIEWPORT_RULE: number;
        }
        declare var CSSRule: {
            prototype: CSSRule;
            new(): CSSRule;
            IMPORT_RULE: number;
            MEDIA_RULE: number;
            STYLE_RULE: number;
            NAMESPACE_RULE: number;
            PAGE_RULE: number;
            UNKNOWN_RULE: number;
            FONT_FACE_RULE: number;
            CHARSET_RULE: number;
            KEYFRAMES_RULE: number;
            KEYFRAME_RULE: number;
            VIEWPORT_RULE: number;
        }
        
        interface SVGPathSegLinetoAbs extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegLinetoAbs: {
            prototype: SVGPathSegLinetoAbs;
            new(): SVGPathSegLinetoAbs;
        }
        
        interface HTMLModElement extends HTMLElement {
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
        }
        declare var HTMLModElement: {
            prototype: HTMLModElement;
            new(): HTMLModElement;
        }
        
        interface SVGMatrix {
            e: number;
            c: number;
            a: number;
            b: number;
            d: number;
            f: number;
            multiply(secondMatrix: SVGMatrix): SVGMatrix;
            flipY(): SVGMatrix;
            skewY(angle: number): SVGMatrix;
            inverse(): SVGMatrix;
            scaleNonUniform(scaleFactorX: number, scaleFactorY: number): SVGMatrix;
            rotate(angle: number): SVGMatrix;
            flipX(): SVGMatrix;
            translate(x: number, y: number): SVGMatrix;
            scale(scaleFactor: number): SVGMatrix;
            rotateFromVector(x: number, y: number): SVGMatrix;
            skewX(angle: number): SVGMatrix;
        }
        declare var SVGMatrix: {
            prototype: SVGMatrix;
            new(): SVGMatrix;
        }
        
        interface MSPopupWindow {
            document: Document;
            isOpen: boolean;
            show(x: number, y: number, w: number, h: number, element?: any): void;
            hide(): void;
        }
        declare var MSPopupWindow: {
            prototype: MSPopupWindow;
            new(): MSPopupWindow;
        }
        
        interface BeforeUnloadEvent extends Event {
            returnValue: string;
        }
        declare var BeforeUnloadEvent: {
            prototype: BeforeUnloadEvent;
            new(): BeforeUnloadEvent;
        }
        
        interface SVGUseElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired, SVGURIReference {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            animatedInstanceRoot: SVGElementInstance;
            instanceRoot: SVGElementInstance;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
        }
        declare var SVGUseElement: {
            prototype: SVGUseElement;
            new(): SVGUseElement;
        }
        
        interface Event {
            timeStamp: number;
            defaultPrevented: boolean;
            isTrusted: boolean;
            currentTarget: EventTarget;
            cancelBubble: boolean;
            target: EventTarget;
            eventPhase: number;
            cancelable: boolean;
            type: string;
            srcElement: Element;
            bubbles: boolean;
            initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean): void;
            stopPropagation(): void;
            stopImmediatePropagation(): void;
            preventDefault(): void;
            CAPTURING_PHASE: number;
            AT_TARGET: number;
            BUBBLING_PHASE: number;
        }
        declare var Event: {
            prototype: Event;
            new(): Event;
            CAPTURING_PHASE: number;
            AT_TARGET: number;
            BUBBLING_PHASE: number;
        }
        
        interface ImageData {
            width: number;
            data: number[];
            height: number;
        }
        declare var ImageData: {
            prototype: ImageData;
            new(): ImageData;
        }
        
        interface HTMLTableColElement extends HTMLElement, HTMLTableAlignment {
            /**
              * Sets or retrieves the width of the object.
              */
            width: any;
            /**
              * Sets or retrieves the alignment of the object relative to the display or table.
              */
            align: string;
            /**
              * Sets or retrieves the number of columns in the group.
              */
            span: number;
        }
        declare var HTMLTableColElement: {
            prototype: HTMLTableColElement;
            new(): HTMLTableColElement;
        }
        
        interface SVGException {
            code: number;
            message: string;
            name: string;
            toString(): string;
            SVG_MATRIX_NOT_INVERTABLE: number;
            SVG_WRONG_TYPE_ERR: number;
            SVG_INVALID_VALUE_ERR: number;
        }
        declare var SVGException: {
            prototype: SVGException;
            new(): SVGException;
            SVG_MATRIX_NOT_INVERTABLE: number;
            SVG_WRONG_TYPE_ERR: number;
            SVG_INVALID_VALUE_ERR: number;
        }
        
        interface SVGLinearGradientElement extends SVGGradientElement {
            y1: SVGAnimatedLength;
            x2: SVGAnimatedLength;
            x1: SVGAnimatedLength;
            y2: SVGAnimatedLength;
        }
        declare var SVGLinearGradientElement: {
            prototype: SVGLinearGradientElement;
            new(): SVGLinearGradientElement;
        }
        
        interface HTMLTableAlignment {
            /**
              * Sets or retrieves a value that you can use to implement your own ch functionality for the object.
              */
            ch: string;
            /**
              * Sets or retrieves how text and other content are vertically aligned within the object that contains them.
              */
            vAlign: string;
            /**
              * Sets or retrieves a value that you can use to implement your own chOff functionality for the object.
              */
            chOff: string;
        }
        
        interface SVGAnimatedEnumeration {
            animVal: number;
            baseVal: number;
        }
        declare var SVGAnimatedEnumeration: {
            prototype: SVGAnimatedEnumeration;
            new(): SVGAnimatedEnumeration;
        }
        
        interface DOML2DeprecatedSizeProperty {
            size: number;
        }
        
        interface HTMLUListElement extends HTMLElement, DOML2DeprecatedListSpaceReduction, DOML2DeprecatedListNumberingAndBulletStyle {
        }
        declare var HTMLUListElement: {
            prototype: HTMLUListElement;
            new(): HTMLUListElement;
        }
        
        interface SVGRectElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            ry: SVGAnimatedLength;
            rx: SVGAnimatedLength;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
        }
        declare var SVGRectElement: {
            prototype: SVGRectElement;
            new(): SVGRectElement;
        }
        
        interface ErrorEventHandler {
            (event: Event, source: string, fileno: number, columnNumber: number): void;
        }
        
        interface HTMLDivElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves how the object is aligned with adjacent text. 
              */
            align: string;
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        declare var HTMLDivElement: {
            prototype: HTMLDivElement;
            new(): HTMLDivElement;
        }
        
        interface DOML2DeprecatedBorderStyle {
            border: string;
        }
        
        interface NamedNodeMap {
            length: number;
            removeNamedItemNS(namespaceURI: string, localName: string): Attr;
            item(index: number): Attr;
            [index: number]: Attr;
            removeNamedItem(name: string): Attr;
            getNamedItem(name: string): Attr;
            // [name: string]: Attr;
            setNamedItem(arg: Attr): Attr;
            getNamedItemNS(namespaceURI: string, localName: string): Attr;
            setNamedItemNS(arg: Attr): Attr;
        }
        declare var NamedNodeMap: {
            prototype: NamedNodeMap;
            new(): NamedNodeMap;
        }
        
        interface MediaList {
            length: number;
            mediaText: string;
            deleteMedium(oldMedium: string): void;
            appendMedium(newMedium: string): void;
            item(index: number): string;
            [index: number]: string;
            toString(): string;
        }
        declare var MediaList: {
            prototype: MediaList;
            new(): MediaList;
        }
        
        interface SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegCurvetoQuadraticSmoothAbs: {
            prototype: SVGPathSegCurvetoQuadraticSmoothAbs;
            new(): SVGPathSegCurvetoQuadraticSmoothAbs;
        }
        
        interface SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {
            y: number;
            x2: number;
            x: number;
            y2: number;
        }
        declare var SVGPathSegCurvetoCubicSmoothRel: {
            prototype: SVGPathSegCurvetoCubicSmoothRel;
            new(): SVGPathSegCurvetoCubicSmoothRel;
        }
        
        interface SVGLengthList {
            numberOfItems: number;
            replaceItem(newItem: SVGLength, index: number): SVGLength;
            getItem(index: number): SVGLength;
            clear(): void;
            appendItem(newItem: SVGLength): SVGLength;
            initialize(newItem: SVGLength): SVGLength;
            removeItem(index: number): SVGLength;
            insertItemBefore(newItem: SVGLength, index: number): SVGLength;
        }
        declare var SVGLengthList: {
            prototype: SVGLengthList;
            new(): SVGLengthList;
        }
        
        interface ProcessingInstruction extends Node {
            target: string;
            data: string;
        }
        declare var ProcessingInstruction: {
            prototype: ProcessingInstruction;
            new(): ProcessingInstruction;
        }
        
        interface MSWindowExtensions {
            status: string;
            onmouseleave: (ev: MouseEvent) => any;
            screenLeft: number;
            offscreenBuffering: any;
            maxConnectionsPerServer: number;
            onmouseenter: (ev: MouseEvent) => any;
            clipboardData: DataTransfer;
            defaultStatus: string;
            clientInformation: Navigator;
            closed: boolean;
            onhelp: (ev: Event) => any;
            external: External;
            event: MSEventObj;
            onfocusout: (ev: FocusEvent) => any;
            screenTop: number;
            onfocusin: (ev: FocusEvent) => any;
            showModelessDialog(url?: string, argument?: any, options?: any): Window;
            navigate(url: string): void;
            resizeBy(x?: number, y?: number): void;
            item(index: any): any;
            resizeTo(x?: number, y?: number): void;
            createPopup(arguments?: any): MSPopupWindow;
            toStaticHTML(html: string): string;
            execScript(code: string, language?: string): any;
            msWriteProfilerMark(profilerMarkName: string): void;
            moveTo(x?: number, y?: number): void;
            moveBy(x?: number, y?: number): void;
            showHelp(url: string, helpArg?: any, features?: string): void;
            captureEvents(): void;
            releaseEvents(): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        
        interface MSBehaviorUrnsCollection {
            length: number;
            item(index: number): string;
        }
        declare var MSBehaviorUrnsCollection: {
            prototype: MSBehaviorUrnsCollection;
            new(): MSBehaviorUrnsCollection;
        }
        
        interface CSSFontFaceRule extends CSSRule {
            style: CSSStyleDeclaration;
        }
        declare var CSSFontFaceRule: {
            prototype: CSSFontFaceRule;
            new(): CSSFontFaceRule;
        }
        
        interface DOML2DeprecatedBackgroundStyle {
            background: string;
        }
        
        interface TextEvent extends UIEvent {
            inputMethod: number;
            data: string;
            locale: string;
            initTextEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, inputMethod: number, locale: string): void;
            DOM_INPUT_METHOD_KEYBOARD: number;
            DOM_INPUT_METHOD_DROP: number;
            DOM_INPUT_METHOD_IME: number;
            DOM_INPUT_METHOD_SCRIPT: number;
            DOM_INPUT_METHOD_VOICE: number;
            DOM_INPUT_METHOD_UNKNOWN: number;
            DOM_INPUT_METHOD_PASTE: number;
            DOM_INPUT_METHOD_HANDWRITING: number;
            DOM_INPUT_METHOD_OPTION: number;
            DOM_INPUT_METHOD_MULTIMODAL: number;
        }
        declare var TextEvent: {
            prototype: TextEvent;
            new(): TextEvent;
            DOM_INPUT_METHOD_KEYBOARD: number;
            DOM_INPUT_METHOD_DROP: number;
            DOM_INPUT_METHOD_IME: number;
            DOM_INPUT_METHOD_SCRIPT: number;
            DOM_INPUT_METHOD_VOICE: number;
            DOM_INPUT_METHOD_UNKNOWN: number;
            DOM_INPUT_METHOD_PASTE: number;
            DOM_INPUT_METHOD_HANDWRITING: number;
            DOM_INPUT_METHOD_OPTION: number;
            DOM_INPUT_METHOD_MULTIMODAL: number;
        }
        
        interface DocumentFragment extends Node, NodeSelector, MSEventAttachmentTarget, MSNodeExtensions {
        }
        declare var DocumentFragment: {
            prototype: DocumentFragment;
            new(): DocumentFragment;
        }
        
        interface SVGPolylineElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGAnimatedPoints, SVGTests, SVGExternalResourcesRequired {
        }
        declare var SVGPolylineElement: {
            prototype: SVGPolylineElement;
            new(): SVGPolylineElement;
        }
        
        interface SVGAnimatedPathData {
            pathSegList: SVGPathSegList;
        }
        
        interface Position {
            timestamp: Date;
            coords: Coordinates;
        }
        declare var Position: {
            prototype: Position;
            new(): Position;
        }
        
        interface BookmarkCollection {
            length: number;
            item(index: number): any;
            [index: number]: any;
        }
        declare var BookmarkCollection: {
            prototype: BookmarkCollection;
            new(): BookmarkCollection;
        }
        
        interface PerformanceMark extends PerformanceEntry {
        }
        declare var PerformanceMark: {
            prototype: PerformanceMark;
            new(): PerformanceMark;
        }
        
        interface CSSPageRule extends CSSRule {
            pseudoClass: string;
            selectorText: string;
            selector: string;
            style: CSSStyleDeclaration;
        }
        declare var CSSPageRule: {
            prototype: CSSPageRule;
            new(): CSSPageRule;
        }
        
        interface HTMLBRElement extends HTMLElement {
            /**
              * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document.
              */
            clear: string;
        }
        declare var HTMLBRElement: {
            prototype: HTMLBRElement;
            new(): HTMLBRElement;
        }
        
        interface MSNavigatorExtensions {
            userLanguage: string;
            plugins: MSPluginsCollection;
            cookieEnabled: boolean;
            appCodeName: string;
            cpuClass: string;
            appMinorVersion: string;
            connectionSpeed: number;
            browserLanguage: string;
            mimeTypes: MSMimeTypesCollection;
            systemLanguage: string;
            language: string;
            javaEnabled(): boolean;
            taintEnabled(): boolean;
        }
        
        interface HTMLSpanElement extends HTMLElement, MSDataBindingExtensions {
        }
        declare var HTMLSpanElement: {
            prototype: HTMLSpanElement;
            new(): HTMLSpanElement;
        }
        
        interface HTMLHeadElement extends HTMLElement {
            profile: string;
        }
        declare var HTMLHeadElement: {
            prototype: HTMLHeadElement;
            new(): HTMLHeadElement;
        }
        
        interface HTMLHeadingElement extends HTMLElement, DOML2DeprecatedTextFlowControl {
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
        }
        declare var HTMLHeadingElement: {
            prototype: HTMLHeadingElement;
            new(): HTMLHeadingElement;
        }
        
        interface HTMLFormElement extends HTMLElement, MSHTMLCollectionExtensions {
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Sets or retrieves a list of character encodings for input data that must be accepted by the server processing the form.
              */
            acceptCharset: string;
            /**
              * Sets or retrieves the encoding type for the form.
              */
            enctype: string;
            /**
              * Retrieves a collection, in source order, of all controls in a given form.
              */
            elements: HTMLCollection;
            /**
              * Sets or retrieves the URL to which the form content is sent for processing.
              */
            action: string;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Sets or retrieves how to send the form data to the server.
              */
            method: string;
            /**
              * Sets or retrieves the MIME encoding for the form.
              */
            encoding: string;
            /**
              * Specifies whether autocomplete is applied to an editable text field.
              */
            autocomplete: string;
            /**
              * Designates a form that is not validated when submitted.
              */
            noValidate: boolean;
            /**
              * Fires when the user resets a form.
              */
            reset(): void;
            /**
              * Retrieves a form object or an object from an elements collection.
              * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is a Number, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.
              * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.
              */
            item(name?: any, index?: any): any;
            /**
              * Fires when a FORM is about to be submitted.
              */
            submit(): void;
            /**
              * Retrieves a form object or an object from an elements collection.
              */
            namedItem(name: string): any;
            [name: string]: any;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
        }
        declare var HTMLFormElement: {
            prototype: HTMLFormElement;
            new(): HTMLFormElement;
        }
        
        interface SVGZoomAndPan {
            zoomAndPan: number;
            SVG_ZOOMANDPAN_MAGNIFY: number;
            SVG_ZOOMANDPAN_UNKNOWN: number;
            SVG_ZOOMANDPAN_DISABLE: number;
        }
        declare var SVGZoomAndPan: SVGZoomAndPan;
        
        interface HTMLMediaElement extends HTMLElement {
            /**
              * Gets the earliest possible position, in seconds, that the playback can begin.
              */
            initialTime: number;
            /**
              * Gets TimeRanges for the current media resource that has been played.
              */
            played: TimeRanges;
            /**
              * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement.
              */
            currentSrc: string;
            readyState: any;
            /**
              * The autobuffer element is not supported by Internet Explorer 9. Use the preload element instead.
              */
            autobuffer: boolean;
            /**
              * Gets or sets a flag to specify whether playback should restart after it completes.
              */
            loop: boolean;
            /**
              * Gets information about whether the playback has ended or not.
              */
            ended: boolean;
            /**
              * Gets a collection of buffered time ranges.
              */
            buffered: TimeRanges;
            /**
              * Returns an object representing the current error state of the audio or video element.
              */
            error: MediaError;
            /**
              * Returns a TimeRanges object that represents the ranges of the current media resource that can be seeked.
              */
            seekable: TimeRanges;
            /**
              * Gets or sets a value that indicates whether to start playing the media automatically.
              */
            autoplay: boolean;
            /**
              * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player).
              */
            controls: boolean;
            /**
              * Gets or sets the volume level for audio portions of the media element.
              */
            volume: number;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            /**
              * Gets or sets the current rate of speed for the media resource to play. This speed is expressed as a multiple of the normal speed of the media resource.
              */
            playbackRate: number;
            /**
              * Returns the duration in seconds of the current media resource. A NaN value is returned if duration is not available, or Infinity if the media resource is streaming.
              */
            duration: number;
            /**
              * Gets or sets a flag that indicates whether the audio (either audio or the audio track on video media) is muted.
              */
            muted: boolean;
            /**
              * Gets or sets the default playback rate when the user is not using fast forward or reverse for a video or audio resource.
              */
            defaultPlaybackRate: number;
            /**
              * Gets a flag that specifies whether playback is paused.
              */
            paused: boolean;
            /**
              * Gets a flag that indicates whether the the client is currently moving to a new playback position in the media resource.
              */
            seeking: boolean;
            /**
              * Gets or sets the current playback position, in seconds.
              */
            currentTime: number;
            /**
              * Gets or sets the current playback position, in seconds.
              */
            preload: string;
            /**
              * Gets the current network activity for the element.
              */
            networkState: number;
            /**
              * Specifies the purpose of the audio or video media, such as background audio or alerts.
              */
            msAudioCategory: string;
            /**
              * Specifies whether or not to enable low-latency playback on the media element.
              */
            msRealTime: boolean;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            textTracks: TextTrackList;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            /**
              * Returns an AudioTrackList object with the audio tracks for a given video element.
              */
            audioTracks: AudioTrackList;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Specifies the output device id that the audio will be sent to.
              */
            msAudioDeviceType: string;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            onmsneedkey: (ev: MSMediaKeyNeededEvent) => any;
            /**
              * Gets the MSMediaKeys object, which is used for decrypting media data, that is associated with this media element.
              */
            msKeys: MSMediaKeys;
            msGraphicsTrustStatus: MSGraphicsTrust;
            /**
              * Pauses the current playback and sets paused to TRUE. This can be used to test whether the media is playing or paused. You can also use the pause or play events to tell whether the media is playing or not.
              */
            pause(): void;
            /**
              * Loads and starts playback of a media resource.
              */
            play(): void;
            /**
              * Fires immediately after the client loads the object.
              */
            load(): void;
            /**
              * Returns a string that specifies whether the client can play a given media resource type.
              */
            canPlayType(type: string): string;
            /**
              * Clears all effects from the media pipeline.
              */
            msClearEffects(): void;
            /**
              * Specifies the media protection manager for a given media pipeline.
              */
            msSetMediaProtectionManager(mediaProtectionManager?: any): void;
            /**
              * Inserts the specified audio effect into media pipeline.
              */
            msInsertAudioEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;
            msSetMediaKeys(mediaKeys: MSMediaKeys): void;
            addTextTrack(kind: string, label?: string, language?: string): TextTrack;
            HAVE_METADATA: number;
            HAVE_CURRENT_DATA: number;
            HAVE_NOTHING: number;
            NETWORK_NO_SOURCE: number;
            HAVE_ENOUGH_DATA: number;
            NETWORK_EMPTY: number;
            NETWORK_LOADING: number;
            NETWORK_IDLE: number;
            HAVE_FUTURE_DATA: number;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLMediaElement: {
            prototype: HTMLMediaElement;
            new(): HTMLMediaElement;
            HAVE_METADATA: number;
            HAVE_CURRENT_DATA: number;
            HAVE_NOTHING: number;
            NETWORK_NO_SOURCE: number;
            HAVE_ENOUGH_DATA: number;
            NETWORK_EMPTY: number;
            NETWORK_LOADING: number;
            NETWORK_IDLE: number;
            HAVE_FUTURE_DATA: number;
        }
        
        interface ElementCSSInlineStyle {
            runtimeStyle: MSStyleCSSProperties;
            currentStyle: MSCurrentStyleCSSProperties;
            doScroll(component?: any): void;
            componentFromPoint(x: number, y: number): string;
        }
        
        interface DOMParser {
            parseFromString(source: string, mimeType: string): Document;
        }
        declare var DOMParser: {
            prototype: DOMParser;
            new(): DOMParser;
        }
        
        interface MSMimeTypesCollection {
            length: number;
        }
        declare var MSMimeTypesCollection: {
            prototype: MSMimeTypesCollection;
            new(): MSMimeTypesCollection;
        }
        
        interface StyleSheet {
            disabled: boolean;
            ownerNode: Node;
            parentStyleSheet: StyleSheet;
            href: string;
            media: MediaList;
            type: string;
            title: string;
        }
        declare var StyleSheet: {
            prototype: StyleSheet;
            new(): StyleSheet;
        }
        
        interface SVGTextPathElement extends SVGTextContentElement, SVGURIReference {
            startOffset: SVGAnimatedLength;
            method: SVGAnimatedEnumeration;
            spacing: SVGAnimatedEnumeration;
            TEXTPATH_SPACINGTYPE_EXACT: number;
            TEXTPATH_METHODTYPE_STRETCH: number;
            TEXTPATH_SPACINGTYPE_AUTO: number;
            TEXTPATH_SPACINGTYPE_UNKNOWN: number;
            TEXTPATH_METHODTYPE_UNKNOWN: number;
            TEXTPATH_METHODTYPE_ALIGN: number;
        }
        declare var SVGTextPathElement: {
            prototype: SVGTextPathElement;
            new(): SVGTextPathElement;
            TEXTPATH_SPACINGTYPE_EXACT: number;
            TEXTPATH_METHODTYPE_STRETCH: number;
            TEXTPATH_SPACINGTYPE_AUTO: number;
            TEXTPATH_SPACINGTYPE_UNKNOWN: number;
            TEXTPATH_METHODTYPE_UNKNOWN: number;
            TEXTPATH_METHODTYPE_ALIGN: number;
        }
        
        interface HTMLDTElement extends HTMLElement {
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        declare var HTMLDTElement: {
            prototype: HTMLDTElement;
            new(): HTMLDTElement;
        }
        
        interface NodeList {
            length: number;
            item(index: number): Node;
            [index: number]: Node;
        }
        declare var NodeList: {
            prototype: NodeList;
            new(): NodeList;
        }
        
        interface XMLSerializer {
            serializeToString(target: Node): string;
        }
        declare var XMLSerializer: {
            prototype: XMLSerializer;
            new(): XMLSerializer;
        }
        
        interface PerformanceMeasure extends PerformanceEntry {
        }
        declare var PerformanceMeasure: {
            prototype: PerformanceMeasure;
            new(): PerformanceMeasure;
        }
        
        interface SVGGradientElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGExternalResourcesRequired, SVGURIReference {
            spreadMethod: SVGAnimatedEnumeration;
            gradientTransform: SVGAnimatedTransformList;
            gradientUnits: SVGAnimatedEnumeration;
            SVG_SPREADMETHOD_REFLECT: number;
            SVG_SPREADMETHOD_PAD: number;
            SVG_SPREADMETHOD_UNKNOWN: number;
            SVG_SPREADMETHOD_REPEAT: number;
        }
        declare var SVGGradientElement: {
            prototype: SVGGradientElement;
            new(): SVGGradientElement;
            SVG_SPREADMETHOD_REFLECT: number;
            SVG_SPREADMETHOD_PAD: number;
            SVG_SPREADMETHOD_UNKNOWN: number;
            SVG_SPREADMETHOD_REPEAT: number;
        }
        
        interface NodeFilter {
            acceptNode(n: Node): number;
            SHOW_ENTITY_REFERENCE: number;
            SHOW_NOTATION: number;
            SHOW_ENTITY: number;
            SHOW_DOCUMENT: number;
            SHOW_PROCESSING_INSTRUCTION: number;
            FILTER_REJECT: number;
            SHOW_CDATA_SECTION: number;
            FILTER_ACCEPT: number;
            SHOW_ALL: number;
            SHOW_DOCUMENT_TYPE: number;
            SHOW_TEXT: number;
            SHOW_ELEMENT: number;
            SHOW_COMMENT: number;
            FILTER_SKIP: number;
            SHOW_ATTRIBUTE: number;
            SHOW_DOCUMENT_FRAGMENT: number;
        }
        declare var NodeFilter: NodeFilter;
        
        interface SVGNumberList {
            numberOfItems: number;
            replaceItem(newItem: SVGNumber, index: number): SVGNumber;
            getItem(index: number): SVGNumber;
            clear(): void;
            appendItem(newItem: SVGNumber): SVGNumber;
            initialize(newItem: SVGNumber): SVGNumber;
            removeItem(index: number): SVGNumber;
            insertItemBefore(newItem: SVGNumber, index: number): SVGNumber;
        }
        declare var SVGNumberList: {
            prototype: SVGNumberList;
            new(): SVGNumberList;
        }
        
        interface MediaError {
            code: number;
            msExtendedCode: number;
            MEDIA_ERR_ABORTED: number;
            MEDIA_ERR_NETWORK: number;
            MEDIA_ERR_SRC_NOT_SUPPORTED: number;
            MEDIA_ERR_DECODE: number;
            MS_MEDIA_ERR_ENCRYPTED: number;
        }
        declare var MediaError: {
            prototype: MediaError;
            new(): MediaError;
            MEDIA_ERR_ABORTED: number;
            MEDIA_ERR_NETWORK: number;
            MEDIA_ERR_SRC_NOT_SUPPORTED: number;
            MEDIA_ERR_DECODE: number;
            MS_MEDIA_ERR_ENCRYPTED: number;
        }
        
        interface HTMLFieldSetElement extends HTMLElement {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLFieldSetElement: {
            prototype: HTMLFieldSetElement;
            new(): HTMLFieldSetElement;
        }
        
        interface HTMLBGSoundElement extends HTMLElement {
            /**
              * Sets or gets the value indicating how the volume of the background sound is divided between the left speaker and the right speaker.
              */
            balance: any;
            /**
              * Sets or gets the volume setting for the sound. 
              */
            volume: any;
            /**
              * Sets or gets the URL of a sound to play.
              */
            src: string;
            /**
              * Sets or retrieves the number of times a sound or video clip will loop when activated.
              */
            loop: number;
        }
        declare var HTMLBGSoundElement: {
            prototype: HTMLBGSoundElement;
            new(): HTMLBGSoundElement;
        }
        
        interface Comment extends CharacterData {
            text: string;
        }
        declare var Comment: {
            prototype: Comment;
            new(): Comment;
        }
        
        interface PerformanceResourceTiming extends PerformanceEntry {
            redirectStart: number;
            redirectEnd: number;
            domainLookupEnd: number;
            responseStart: number;
            domainLookupStart: number;
            fetchStart: number;
            requestStart: number;
            connectEnd: number;
            connectStart: number;
            initiatorType: string;
            responseEnd: number;
        }
        declare var PerformanceResourceTiming: {
            prototype: PerformanceResourceTiming;
            new(): PerformanceResourceTiming;
        }
        
        interface CanvasPattern {
        }
        declare var CanvasPattern: {
            prototype: CanvasPattern;
            new(): CanvasPattern;
        }
        
        interface HTMLHRElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves whether the horizontal rule is drawn with 3-D shading.
              */
            noShade: boolean;
        }
        declare var HTMLHRElement: {
            prototype: HTMLHRElement;
            new(): HTMLHRElement;
        }
        
        interface HTMLObjectElement extends HTMLElement, GetSVGDocument, DOML2DeprecatedMarginStyle, DOML2DeprecatedBorderStyle, DOML2DeprecatedAlignmentStyle, MSDataBindingExtensions, MSDataBindingRecordSetExtensions {
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Sets or retrieves the Internet media type for the code associated with the object.
              */
            codeType: string;
            /**
              * Retrieves the contained object.
              */
            object: any;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the URL of the file containing the compiled Java class.
              */
            code: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.
              */
            archive: string;
            /**
              * Sets or retrieves a message to be displayed while an object is loading.
              */
            standby: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves the class identifier for the object.
              */
            classid: string;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Sets or retrieves the URL that references the data of the object.
              */
            data: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Gets or sets the optional alternative HTML script to execute if the object fails to load.
              */
            altHtml: string;
            /**
              * Sets or retrieves the URL of the component.
              */
            codeBase: string;
            declare: boolean;
            /**
              * Sets or retrieves the MIME type of the object.
              */
            type: string;
            /**
              * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.
              */
            BaseHref: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            readyState: number;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        declare var HTMLObjectElement: {
            prototype: HTMLObjectElement;
            new(): HTMLObjectElement;
        }
        
        interface HTMLEmbedElement extends HTMLElement, GetSVGDocument {
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Retrieves the palette used for the embedded document.
              */
            palette: string;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            hidden: string;
            /**
              * Retrieves the URL of the plug-in used to view an embedded document.
              */
            pluginspage: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Sets or retrieves the height and width units of the embed object.
              */
            units: string;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            readyState: string;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
        }
        declare var HTMLEmbedElement: {
            prototype: HTMLEmbedElement;
            new(): HTMLEmbedElement;
        }
        
        interface StorageEvent extends Event {
            oldValue: any;
            newValue: any;
            url: string;
            storageArea: Storage;
            key: string;
            initStorageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, keyArg: string, oldValueArg: any, newValueArg: any, urlArg: string, storageAreaArg: Storage): void;
        }
        declare var StorageEvent: {
            prototype: StorageEvent;
            new(): StorageEvent;
        }
        
        interface CharacterData extends Node {
            length: number;
            data: string;
            deleteData(offset: number, count: number): void;
            replaceData(offset: number, count: number, arg: string): void;
            appendData(arg: string): void;
            insertData(offset: number, arg: string): void;
            substringData(offset: number, count: number): string;
        }
        declare var CharacterData: {
            prototype: CharacterData;
            new(): CharacterData;
        }
        
        interface HTMLOptGroupElement extends HTMLElement, MSDataBindingExtensions {
            /**
              * Sets or retrieves the ordinal position of an option in a list box.
              */
            index: number;
            /**
              * Sets or retrieves the status of an option.
              */
            defaultSelected: boolean;
            /**
              * Sets or retrieves the text string specified by the option tag.
              */
            text: string;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves a value that you can use to implement your own label functionality for the object.
              */
            label: string;
            /**
              * Sets or retrieves whether the option in the list box is the default item.
              */
            selected: boolean;
        }
        declare var HTMLOptGroupElement: {
            prototype: HTMLOptGroupElement;
            new(): HTMLOptGroupElement;
        }
        
        interface HTMLIsIndexElement extends HTMLElement {
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the URL to which the form content is sent for processing.
              */
            action: string;
            prompt: string;
        }
        declare var HTMLIsIndexElement: {
            prototype: HTMLIsIndexElement;
            new(): HTMLIsIndexElement;
        }
        
        interface SVGPathSegLinetoRel extends SVGPathSeg {
            y: number;
            x: number;
        }
        declare var SVGPathSegLinetoRel: {
            prototype: SVGPathSegLinetoRel;
            new(): SVGPathSegLinetoRel;
        }
        
        interface DOMException {
            code: number;
            message: string;
            name: string;
            toString(): string;
            HIERARCHY_REQUEST_ERR: number;
            NO_MODIFICATION_ALLOWED_ERR: number;
            INVALID_MODIFICATION_ERR: number;
            NAMESPACE_ERR: number;
            INVALID_CHARACTER_ERR: number;
            TYPE_MISMATCH_ERR: number;
            ABORT_ERR: number;
            INVALID_STATE_ERR: number;
            SECURITY_ERR: number;
            NETWORK_ERR: number;
            WRONG_DOCUMENT_ERR: number;
            QUOTA_EXCEEDED_ERR: number;
            INDEX_SIZE_ERR: number;
            DOMSTRING_SIZE_ERR: number;
            SYNTAX_ERR: number;
            SERIALIZE_ERR: number;
            VALIDATION_ERR: number;
            NOT_FOUND_ERR: number;
            URL_MISMATCH_ERR: number;
            PARSE_ERR: number;
            NO_DATA_ALLOWED_ERR: number;
            NOT_SUPPORTED_ERR: number;
            INVALID_ACCESS_ERR: number;
            INUSE_ATTRIBUTE_ERR: number;
            INVALID_NODE_TYPE_ERR: number;
            DATA_CLONE_ERR: number;
            TIMEOUT_ERR: number;
        }
        declare var DOMException: {
            prototype: DOMException;
            new(): DOMException;
            HIERARCHY_REQUEST_ERR: number;
            NO_MODIFICATION_ALLOWED_ERR: number;
            INVALID_MODIFICATION_ERR: number;
            NAMESPACE_ERR: number;
            INVALID_CHARACTER_ERR: number;
            TYPE_MISMATCH_ERR: number;
            ABORT_ERR: number;
            INVALID_STATE_ERR: number;
            SECURITY_ERR: number;
            NETWORK_ERR: number;
            WRONG_DOCUMENT_ERR: number;
            QUOTA_EXCEEDED_ERR: number;
            INDEX_SIZE_ERR: number;
            DOMSTRING_SIZE_ERR: number;
            SYNTAX_ERR: number;
            SERIALIZE_ERR: number;
            VALIDATION_ERR: number;
            NOT_FOUND_ERR: number;
            URL_MISMATCH_ERR: number;
            PARSE_ERR: number;
            NO_DATA_ALLOWED_ERR: number;
            NOT_SUPPORTED_ERR: number;
            INVALID_ACCESS_ERR: number;
            INUSE_ATTRIBUTE_ERR: number;
            INVALID_NODE_TYPE_ERR: number;
            DATA_CLONE_ERR: number;
            TIMEOUT_ERR: number;
        }
        
        interface SVGAnimatedBoolean {
            animVal: boolean;
            baseVal: boolean;
        }
        declare var SVGAnimatedBoolean: {
            prototype: SVGAnimatedBoolean;
            new(): SVGAnimatedBoolean;
        }
        
        interface MSCompatibleInfoCollection {
            length: number;
            item(index: number): MSCompatibleInfo;
        }
        declare var MSCompatibleInfoCollection: {
            prototype: MSCompatibleInfoCollection;
            new(): MSCompatibleInfoCollection;
        }
        
        interface SVGSwitchElement extends SVGElement, SVGStylable, SVGTransformable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
        }
        declare var SVGSwitchElement: {
            prototype: SVGSwitchElement;
            new(): SVGSwitchElement;
        }
        
        interface SVGPreserveAspectRatio {
            align: number;
            meetOrSlice: number;
            SVG_PRESERVEASPECTRATIO_NONE: number;
            SVG_PRESERVEASPECTRATIO_XMINYMID: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMINYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;
            SVG_MEETORSLICE_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMINYMIN: number;
            SVG_MEETORSLICE_MEET: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;
            SVG_MEETORSLICE_SLICE: number;
            SVG_PRESERVEASPECTRATIO_UNKNOWN: number;
        }
        declare var SVGPreserveAspectRatio: {
            prototype: SVGPreserveAspectRatio;
            new(): SVGPreserveAspectRatio;
            SVG_PRESERVEASPECTRATIO_NONE: number;
            SVG_PRESERVEASPECTRATIO_XMINYMID: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMINYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;
            SVG_MEETORSLICE_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMINYMIN: number;
            SVG_MEETORSLICE_MEET: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;
            SVG_MEETORSLICE_SLICE: number;
            SVG_PRESERVEASPECTRATIO_UNKNOWN: number;
        }
        
        interface Attr extends Node {
            expando: boolean;
            specified: boolean;
            ownerElement: Element;
            value: string;
            name: string;
        }
        declare var Attr: {
            prototype: Attr;
            new(): Attr;
        }
        
        interface PerformanceNavigation {
            redirectCount: number;
            type: number;
            toJSON(): any;
            TYPE_RELOAD: number;
            TYPE_RESERVED: number;
            TYPE_BACK_FORWARD: number;
            TYPE_NAVIGATE: number;
        }
        declare var PerformanceNavigation: {
            prototype: PerformanceNavigation;
            new(): PerformanceNavigation;
            TYPE_RELOAD: number;
            TYPE_RESERVED: number;
            TYPE_BACK_FORWARD: number;
            TYPE_NAVIGATE: number;
        }
        
        interface SVGStopElement extends SVGElement, SVGStylable {
            offset: SVGAnimatedNumber;
        }
        declare var SVGStopElement: {
            prototype: SVGStopElement;
            new(): SVGStopElement;
        }
        
        interface PositionCallback {
            (position: Position): void;
        }
        
        interface SVGSymbolElement extends SVGElement, SVGStylable, SVGLangSpace, SVGFitToViewBox, SVGExternalResourcesRequired {
        }
        declare var SVGSymbolElement: {
            prototype: SVGSymbolElement;
            new(): SVGSymbolElement;
        }
        
        interface SVGElementInstanceList {
            length: number;
            item(index: number): SVGElementInstance;
        }
        declare var SVGElementInstanceList: {
            prototype: SVGElementInstanceList;
            new(): SVGElementInstanceList;
        }
        
        interface CSSRuleList {
            length: number;
            item(index: number): CSSRule;
            [index: number]: CSSRule;
        }
        declare var CSSRuleList: {
            prototype: CSSRuleList;
            new(): CSSRuleList;
        }
        
        interface MSDataBindingRecordSetExtensions {
            recordset: any;
            namedRecordset(dataMember: string, hierarchy?: any): any;
        }
        
        interface LinkStyle {
            styleSheet: StyleSheet;
            sheet: StyleSheet;
        }
        
        interface HTMLVideoElement extends HTMLMediaElement {
            /**
              * Gets or sets the width of the video element.
              */
            width: number;
            /**
              * Gets the intrinsic width of a video in CSS pixels, or zero if the dimensions are not known.
              */
            videoWidth: number;
            /**
              * Gets the intrinsic height of a video in CSS pixels, or zero if the dimensions are not known.
              */
            videoHeight: number;
            /**
              * Gets or sets the height of the video element.
              */
            height: number;
            /**
              * Gets or sets a URL of an image to display, for example, like a movie poster. This can be a still frame from the video, or another image if no video data is available.
              */
            poster: string;
            msIsStereo3D: boolean;
            msStereo3DPackingMode: string;
            onMSVideoOptimalLayoutChanged: (ev: any) => any;
            onMSVideoFrameStepCompleted: (ev: any) => any;
            msStereo3DRenderMode: string;
            msIsLayoutOptimalForPlayback: boolean;
            msHorizontalMirror: boolean;
            onMSVideoFormatChanged: (ev: any) => any;
            msZoom: boolean;
            msInsertVideoEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;
            msSetVideoRectangle(left: number, top: number, right: number, bottom: number): void;
            msFrameStep(forward: boolean): void;
            getVideoPlaybackQuality(): VideoPlaybackQuality;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgotpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mslostpointercapture", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "move", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetchanged", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsdelete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "losecapture", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "controlselect", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "layoutcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "filterchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "datasetcomplete", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "errorupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cellchange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowexit", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "rowsinserted", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "propertychange", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "moveend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeeditfocus", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "afterupdate", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resizeend", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dataavailable", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "movestart", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "rowenter", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mscontentzoom", listener: (ev: MSEventObj) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "msmanipulationstatechanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoOptimalLayoutChanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoFrameStepCompleted", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoFormatChanged", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var HTMLVideoElement: {
            prototype: HTMLVideoElement;
            new(): HTMLVideoElement;
        }
        
        interface ClientRectList {
            length: number;
            item(index: number): ClientRect;
            [index: number]: ClientRect;
        }
        declare var ClientRectList: {
            prototype: ClientRectList;
            new(): ClientRectList;
        }
        
        interface SVGMaskElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLangSpace, SVGTests, SVGExternalResourcesRequired {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            maskUnits: SVGAnimatedEnumeration;
            maskContentUnits: SVGAnimatedEnumeration;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
        }
        declare var SVGMaskElement: {
            prototype: SVGMaskElement;
            new(): SVGMaskElement;
        }
        
        interface External {
        }
        declare var External: {
            prototype: External;
            new(): External;
        }
        
        interface MSGestureEvent extends UIEvent {
            offsetY: number;
            translationY: number;
            velocityExpansion: number;
            velocityY: number;
            velocityAngular: number;
            translationX: number;
            velocityX: number;
            hwTimestamp: number;
            offsetX: number;
            screenX: number;
            rotation: number;
            expansion: number;
            clientY: number;
            screenY: number;
            scale: number;
            gestureObject: any;
            clientX: number;
            initGestureEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, offsetXArg: number, offsetYArg: number, translationXArg: number, translationYArg: number, scaleArg: number, expansionArg: number, rotationArg: number, velocityXArg: number, velocityYArg: number, velocityExpansionArg: number, velocityAngularArg: number, hwTimestampArg: number): void;
            MSGESTURE_FLAG_BEGIN: number;
            MSGESTURE_FLAG_END: number;
            MSGESTURE_FLAG_CANCEL: number;
            MSGESTURE_FLAG_INERTIA: number;
            MSGESTURE_FLAG_NONE: number;
        }
        declare var MSGestureEvent: {
            prototype: MSGestureEvent;
            new(): MSGestureEvent;
            MSGESTURE_FLAG_BEGIN: number;
            MSGESTURE_FLAG_END: number;
            MSGESTURE_FLAG_CANCEL: number;
            MSGESTURE_FLAG_INERTIA: number;
            MSGESTURE_FLAG_NONE: number;
        }
        
        interface ErrorEvent extends Event {
            colno: number;
            filename: string;
            error: any;
            lineno: number;
            message: string;
            initErrorEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, messageArg: string, filenameArg: string, linenoArg: number): void;
        }
        declare var ErrorEvent: {
            prototype: ErrorEvent;
            new(): ErrorEvent;
        }
        
        interface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLangSpace, SVGURIReference, SVGExternalResourcesRequired {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            filterResX: SVGAnimatedInteger;
            filterUnits: SVGAnimatedEnumeration;
            primitiveUnits: SVGAnimatedEnumeration;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
            filterResY: SVGAnimatedInteger;
            setFilterRes(filterResX: number, filterResY: number): void;
        }
        declare var SVGFilterElement: {
            prototype: SVGFilterElement;
            new(): SVGFilterElement;
        }
        
        interface TrackEvent extends Event {
            track: any;
        }
        declare var TrackEvent: {
            prototype: TrackEvent;
            new(): TrackEvent;
        }
        
        interface SVGFEMergeNodeElement extends SVGElement {
            in1: SVGAnimatedString;
        }
        declare var SVGFEMergeNodeElement: {
            prototype: SVGFEMergeNodeElement;
            new(): SVGFEMergeNodeElement;
        }
        
        interface SVGFEFloodElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
        }
        declare var SVGFEFloodElement: {
            prototype: SVGFEFloodElement;
            new(): SVGFEFloodElement;
        }
        
        interface MSGesture {
            target: Element;
            addPointer(pointerId: number): void;
            stop(): void;
        }
        declare var MSGesture: {
            prototype: MSGesture;
            new(): MSGesture;
        }
        
        interface TextTrackCue extends EventTarget {
            onenter: (ev: Event) => any;
            track: TextTrack;
            endTime: number;
            text: string;
            pauseOnExit: boolean;
            id: string;
            startTime: number;
            onexit: (ev: Event) => any;
            getCueAsHTML(): DocumentFragment;
            addEventListener(type: "enter", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "exit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var TextTrackCue: {
            prototype: TextTrackCue;
            new(startTime: number, endTime: number, text: string): TextTrackCue;
        }
        
        interface MSStreamReader extends MSBaseReader {
            error: DOMError;
            readAsArrayBuffer(stream: MSStream, size?: number): void;
            readAsBlob(stream: MSStream, size?: number): void;
            readAsDataURL(stream: MSStream, size?: number): void;
            readAsText(stream: MSStream, encoding?: string, size?: number): void;
        }
        declare var MSStreamReader: {
            prototype: MSStreamReader;
            new(): MSStreamReader;
        }
        
        interface DOMTokenList {
            length: number;
            contains(token: string): boolean;
            remove(token: string): void;
            toggle(token: string): boolean;
            add(token: string): void;
            item(index: number): string;
            [index: number]: string;
            toString(): string;
        }
        declare var DOMTokenList: {
            prototype: DOMTokenList;
            new(): DOMTokenList;
        }
        
        interface SVGFEFuncAElement extends SVGComponentTransferFunctionElement {
        }
        declare var SVGFEFuncAElement: {
            prototype: SVGFEFuncAElement;
            new(): SVGFEFuncAElement;
        }
        
        interface SVGFETileElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
        }
        declare var SVGFETileElement: {
            prototype: SVGFETileElement;
            new(): SVGFETileElement;
        }
        
        interface SVGFEBlendElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in2: SVGAnimatedString;
            mode: SVGAnimatedEnumeration;
            in1: SVGAnimatedString;
            SVG_FEBLEND_MODE_DARKEN: number;
            SVG_FEBLEND_MODE_UNKNOWN: number;
            SVG_FEBLEND_MODE_MULTIPLY: number;
            SVG_FEBLEND_MODE_NORMAL: number;
            SVG_FEBLEND_MODE_SCREEN: number;
            SVG_FEBLEND_MODE_LIGHTEN: number;
        }
        declare var SVGFEBlendElement: {
            prototype: SVGFEBlendElement;
            new(): SVGFEBlendElement;
            SVG_FEBLEND_MODE_DARKEN: number;
            SVG_FEBLEND_MODE_UNKNOWN: number;
            SVG_FEBLEND_MODE_MULTIPLY: number;
            SVG_FEBLEND_MODE_NORMAL: number;
            SVG_FEBLEND_MODE_SCREEN: number;
            SVG_FEBLEND_MODE_LIGHTEN: number;
        }
        
        interface MessageChannel {
            port2: MessagePort;
            port1: MessagePort;
        }
        declare var MessageChannel: {
            prototype: MessageChannel;
            new(): MessageChannel;
        }
        
        interface SVGFEMergeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
        }
        declare var SVGFEMergeElement: {
            prototype: SVGFEMergeElement;
            new(): SVGFEMergeElement;
        }
        
        interface TransitionEvent extends Event {
            propertyName: string;
            elapsedTime: number;
            initTransitionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, propertyNameArg: string, elapsedTimeArg: number): void;
        }
        declare var TransitionEvent: {
            prototype: TransitionEvent;
            new(): TransitionEvent;
        }
        
        interface MediaQueryList {
            matches: boolean;
            media: string;
            addListener(listener: MediaQueryListListener): void;
            removeListener(listener: MediaQueryListListener): void;
        }
        declare var MediaQueryList: {
            prototype: MediaQueryList;
            new(): MediaQueryList;
        }
        
        interface DOMError {
            name: string;
            toString(): string;
        }
        declare var DOMError: {
            prototype: DOMError;
            new(): DOMError;
        }
        
        interface CloseEvent extends Event {
            wasClean: boolean;
            reason: string;
            code: number;
            initCloseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, wasCleanArg: boolean, codeArg: number, reasonArg: string): void;
        }
        declare var CloseEvent: {
            prototype: CloseEvent;
            new(): CloseEvent;
        }
        
        interface WebSocket extends EventTarget {
            protocol: string;
            readyState: number;
            bufferedAmount: number;
            onopen: (ev: Event) => any;
            extensions: string;
            onmessage: (ev: MessageEvent) => any;
            onclose: (ev: CloseEvent) => any;
            onerror: (ev: ErrorEvent) => any;
            binaryType: string;
            url: string;
            close(code?: number, reason?: string): void;
            send(data: any): void;
            OPEN: number;
            CLOSING: number;
            CONNECTING: number;
            CLOSED: number;
            addEventListener(type: "open", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "close", listener: (ev: CloseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var WebSocket: {
            prototype: WebSocket;
            new(url: string, protocols?: string): WebSocket;
            new(url: string, protocols?: string[]): WebSocket;
            OPEN: number;
            CLOSING: number;
            CONNECTING: number;
            CLOSED: number;
        }
        
        interface SVGFEPointLightElement extends SVGElement {
            y: SVGAnimatedNumber;
            x: SVGAnimatedNumber;
            z: SVGAnimatedNumber;
        }
        declare var SVGFEPointLightElement: {
            prototype: SVGFEPointLightElement;
            new(): SVGFEPointLightElement;
        }
        
        interface ProgressEvent extends Event {
            loaded: number;
            lengthComputable: boolean;
            total: number;
            initProgressEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, lengthComputableArg: boolean, loadedArg: number, totalArg: number): void;
        }
        declare var ProgressEvent: {
            prototype: ProgressEvent;
            new(): ProgressEvent;
        }
        
        interface IDBObjectStore {
            indexNames: DOMStringList;
            name: string;
            transaction: IDBTransaction;
            keyPath: string;
            count(key?: any): IDBRequest;
            add(value: any, key?: any): IDBRequest;
            clear(): IDBRequest;
            createIndex(name: string, keyPath: string, optionalParameters?: any): IDBIndex;
            put(value: any, key?: any): IDBRequest;
            openCursor(range?: any, direction?: string): IDBRequest;
            deleteIndex(indexName: string): void;
            index(name: string): IDBIndex;
            get(key: any): IDBRequest;
            delete(key: any): IDBRequest;
        }
        declare var IDBObjectStore: {
            prototype: IDBObjectStore;
            new(): IDBObjectStore;
        }
        
        interface SVGFEGaussianBlurElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            stdDeviationX: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            stdDeviationY: SVGAnimatedNumber;
            setStdDeviation(stdDeviationX: number, stdDeviationY: number): void;
        }
        declare var SVGFEGaussianBlurElement: {
            prototype: SVGFEGaussianBlurElement;
            new(): SVGFEGaussianBlurElement;
        }
        
        interface SVGFilterPrimitiveStandardAttributes extends SVGStylable {
            y: SVGAnimatedLength;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            height: SVGAnimatedLength;
            result: SVGAnimatedString;
        }
        
        interface IDBVersionChangeEvent extends Event {
            newVersion: number;
            oldVersion: number;
        }
        declare var IDBVersionChangeEvent: {
            prototype: IDBVersionChangeEvent;
            new(): IDBVersionChangeEvent;
        }
        
        interface IDBIndex {
            unique: boolean;
            name: string;
            keyPath: string;
            objectStore: IDBObjectStore;
            count(key?: any): IDBRequest;
            getKey(key: any): IDBRequest;
            openKeyCursor(range?: IDBKeyRange, direction?: string): IDBRequest;
            get(key: any): IDBRequest;
            openCursor(range?: IDBKeyRange, direction?: string): IDBRequest;
        }
        declare var IDBIndex: {
            prototype: IDBIndex;
            new(): IDBIndex;
        }
        
        interface FileList {
            length: number;
            item(index: number): File;
            [index: number]: File;
        }
        declare var FileList: {
            prototype: FileList;
            new(): FileList;
        }
        
        interface IDBCursor {
            source: any;
            direction: string;
            key: any;
            primaryKey: any;
            advance(count: number): void;
            delete(): IDBRequest;
            continue(key?: any): void;
            update(value: any): IDBRequest;
            PREV: string;
            PREV_NO_DUPLICATE: string;
            NEXT: string;
            NEXT_NO_DUPLICATE: string;
        }
        declare var IDBCursor: {
            prototype: IDBCursor;
            new(): IDBCursor;
            PREV: string;
            PREV_NO_DUPLICATE: string;
            NEXT: string;
            NEXT_NO_DUPLICATE: string;
        }
        
        interface SVGFESpecularLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            kernelUnitLengthY: SVGAnimatedNumber;
            surfaceScale: SVGAnimatedNumber;
            specularExponent: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            kernelUnitLengthX: SVGAnimatedNumber;
            specularConstant: SVGAnimatedNumber;
        }
        declare var SVGFESpecularLightingElement: {
            prototype: SVGFESpecularLightingElement;
            new(): SVGFESpecularLightingElement;
        }
        
        interface File extends Blob {
            lastModifiedDate: any;
            name: string;
        }
        declare var File: {
            prototype: File;
            new(): File;
        }
        
        interface URL {
            revokeObjectURL(url: string): void;
            createObjectURL(object: any, options?: ObjectURLOptions): string;
        }
        declare var URL: URL;
        
        interface IDBCursorWithValue extends IDBCursor {
            value: any;
        }
        declare var IDBCursorWithValue: {
            prototype: IDBCursorWithValue;
            new(): IDBCursorWithValue;
        }
        
        interface XMLHttpRequestEventTarget extends EventTarget {
            onprogress: (ev: ProgressEvent) => any;
            onerror: (ev: ErrorEvent) => any;
            onload: (ev: Event) => any;
            ontimeout: (ev: Event) => any;
            onabort: (ev: UIEvent) => any;
            onloadstart: (ev: Event) => any;
            onloadend: (ev: ProgressEvent) => any;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeout", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var XMLHttpRequestEventTarget: {
            prototype: XMLHttpRequestEventTarget;
            new(): XMLHttpRequestEventTarget;
        }
        
        interface IDBEnvironment {
            msIndexedDB: IDBFactory;
            indexedDB: IDBFactory;
        }
        
        interface AudioTrackList extends EventTarget {
            length: number;
            onchange: (ev: Event) => any;
            onaddtrack: (ev: TrackEvent) => any;
            onremovetrack: (ev: any /*PluginArray*/) => any;
            getTrackById(id: string): AudioTrack;
            item(index: number): AudioTrack;
            [index: number]: AudioTrack;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "removetrack", listener: (ev: any /*PluginArray*/) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var AudioTrackList: {
            prototype: AudioTrackList;
            new(): AudioTrackList;
        }
        
        interface MSBaseReader extends EventTarget {
            onprogress: (ev: ProgressEvent) => any;
            readyState: number;
            onabort: (ev: UIEvent) => any;
            onloadend: (ev: ProgressEvent) => any;
            onerror: (ev: ErrorEvent) => any;
            onload: (ev: Event) => any;
            onloadstart: (ev: Event) => any;
            result: any;
            abort(): void;
            LOADING: number;
            EMPTY: number;
            DONE: number;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        
        interface SVGFEMorphologyElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            operator: SVGAnimatedEnumeration;
            radiusX: SVGAnimatedNumber;
            radiusY: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;
            SVG_MORPHOLOGY_OPERATOR_ERODE: number;
            SVG_MORPHOLOGY_OPERATOR_DILATE: number;
        }
        declare var SVGFEMorphologyElement: {
            prototype: SVGFEMorphologyElement;
            new(): SVGFEMorphologyElement;
            SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;
            SVG_MORPHOLOGY_OPERATOR_ERODE: number;
            SVG_MORPHOLOGY_OPERATOR_DILATE: number;
        }
        
        interface SVGFEFuncRElement extends SVGComponentTransferFunctionElement {
        }
        declare var SVGFEFuncRElement: {
            prototype: SVGFEFuncRElement;
            new(): SVGFEFuncRElement;
        }
        
        interface WindowTimersExtension {
            msSetImmediate(expression: any, ...args: any[]): number;
            clearImmediate(handle: number): void;
            msClearImmediate(handle: number): void;
            setImmediate(expression: any, ...args: any[]): number;
        }
        
        interface SVGFEDisplacementMapElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in2: SVGAnimatedString;
            xChannelSelector: SVGAnimatedEnumeration;
            yChannelSelector: SVGAnimatedEnumeration;
            scale: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            SVG_CHANNEL_B: number;
            SVG_CHANNEL_R: number;
            SVG_CHANNEL_G: number;
            SVG_CHANNEL_UNKNOWN: number;
            SVG_CHANNEL_A: number;
        }
        declare var SVGFEDisplacementMapElement: {
            prototype: SVGFEDisplacementMapElement;
            new(): SVGFEDisplacementMapElement;
            SVG_CHANNEL_B: number;
            SVG_CHANNEL_R: number;
            SVG_CHANNEL_G: number;
            SVG_CHANNEL_UNKNOWN: number;
            SVG_CHANNEL_A: number;
        }
        
        interface AnimationEvent extends Event {
            animationName: string;
            elapsedTime: number;
            initAnimationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, animationNameArg: string, elapsedTimeArg: number): void;
        }
        declare var AnimationEvent: {
            prototype: AnimationEvent;
            new(): AnimationEvent;
        }
        
        interface SVGComponentTransferFunctionElement extends SVGElement {
            tableValues: SVGAnimatedNumberList;
            slope: SVGAnimatedNumber;
            type: SVGAnimatedEnumeration;
            exponent: SVGAnimatedNumber;
            amplitude: SVGAnimatedNumber;
            intercept: SVGAnimatedNumber;
            offset: SVGAnimatedNumber;
            SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;
            SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;
            SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;
            SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;
        }
        declare var SVGComponentTransferFunctionElement: {
            prototype: SVGComponentTransferFunctionElement;
            new(): SVGComponentTransferFunctionElement;
            SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;
            SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;
            SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;
            SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;
        }
        
        interface MSRangeCollection {
            length: number;
            item(index: number): Range;
            [index: number]: Range;
        }
        declare var MSRangeCollection: {
            prototype: MSRangeCollection;
            new(): MSRangeCollection;
        }
        
        interface SVGFEDistantLightElement extends SVGElement {
            azimuth: SVGAnimatedNumber;
            elevation: SVGAnimatedNumber;
        }
        declare var SVGFEDistantLightElement: {
            prototype: SVGFEDistantLightElement;
            new(): SVGFEDistantLightElement;
        }
        
        interface SVGFEFuncBElement extends SVGComponentTransferFunctionElement {
        }
        declare var SVGFEFuncBElement: {
            prototype: SVGFEFuncBElement;
            new(): SVGFEFuncBElement;
        }
        
        interface IDBKeyRange {
            upper: any;
            upperOpen: boolean;
            lower: any;
            lowerOpen: boolean;
        }
        declare var IDBKeyRange: {
            prototype: IDBKeyRange;
            new(): IDBKeyRange;
            bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange;
            only(value: any): IDBKeyRange;
            lowerBound(bound: any, open?: boolean): IDBKeyRange;
            upperBound(bound: any, open?: boolean): IDBKeyRange;
        }
        
        interface WindowConsole {
            console: Console;
        }
        
        interface IDBTransaction extends EventTarget {
            oncomplete: (ev: Event) => any;
            db: IDBDatabase;
            mode: string;
            error: DOMError;
            onerror: (ev: ErrorEvent) => any;
            onabort: (ev: UIEvent) => any;
            abort(): void;
            objectStore(name: string): IDBObjectStore;
            READ_ONLY: string;
            VERSION_CHANGE: string;
            READ_WRITE: string;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var IDBTransaction: {
            prototype: IDBTransaction;
            new(): IDBTransaction;
            READ_ONLY: string;
            VERSION_CHANGE: string;
            READ_WRITE: string;
        }
        
        interface AudioTrack {
            kind: string;
            language: string;
            id: string;
            label: string;
            enabled: boolean;
            sourceBuffer: SourceBuffer;
        }
        declare var AudioTrack: {
            prototype: AudioTrack;
            new(): AudioTrack;
        }
        
        interface SVGFEConvolveMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            orderY: SVGAnimatedInteger;
            kernelUnitLengthY: SVGAnimatedNumber;
            orderX: SVGAnimatedInteger;
            preserveAlpha: SVGAnimatedBoolean;
            kernelMatrix: SVGAnimatedNumberList;
            edgeMode: SVGAnimatedEnumeration;
            kernelUnitLengthX: SVGAnimatedNumber;
            bias: SVGAnimatedNumber;
            targetX: SVGAnimatedInteger;
            targetY: SVGAnimatedInteger;
            divisor: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            SVG_EDGEMODE_WRAP: number;
            SVG_EDGEMODE_DUPLICATE: number;
            SVG_EDGEMODE_UNKNOWN: number;
            SVG_EDGEMODE_NONE: number;
        }
        declare var SVGFEConvolveMatrixElement: {
            prototype: SVGFEConvolveMatrixElement;
            new(): SVGFEConvolveMatrixElement;
            SVG_EDGEMODE_WRAP: number;
            SVG_EDGEMODE_DUPLICATE: number;
            SVG_EDGEMODE_UNKNOWN: number;
            SVG_EDGEMODE_NONE: number;
        }
        
        interface TextTrackCueList {
            length: number;
            item(index: number): TextTrackCue;
            [index: number]: TextTrackCue;
            getCueById(id: string): TextTrackCue;
        }
        declare var TextTrackCueList: {
            prototype: TextTrackCueList;
            new(): TextTrackCueList;
        }
        
        interface CSSKeyframesRule extends CSSRule {
            name: string;
            cssRules: CSSRuleList;
            findRule(rule: string): CSSKeyframeRule;
            deleteRule(rule: string): void;
            appendRule(rule: string): void;
        }
        declare var CSSKeyframesRule: {
            prototype: CSSKeyframesRule;
            new(): CSSKeyframesRule;
        }
        
        interface SVGFETurbulenceElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            baseFrequencyX: SVGAnimatedNumber;
            numOctaves: SVGAnimatedInteger;
            type: SVGAnimatedEnumeration;
            baseFrequencyY: SVGAnimatedNumber;
            stitchTiles: SVGAnimatedEnumeration;
            seed: SVGAnimatedNumber;
            SVG_STITCHTYPE_UNKNOWN: number;
            SVG_STITCHTYPE_NOSTITCH: number;
            SVG_TURBULENCE_TYPE_UNKNOWN: number;
            SVG_TURBULENCE_TYPE_TURBULENCE: number;
            SVG_TURBULENCE_TYPE_FRACTALNOISE: number;
            SVG_STITCHTYPE_STITCH: number;
        }
        declare var SVGFETurbulenceElement: {
            prototype: SVGFETurbulenceElement;
            new(): SVGFETurbulenceElement;
            SVG_STITCHTYPE_UNKNOWN: number;
            SVG_STITCHTYPE_NOSTITCH: number;
            SVG_TURBULENCE_TYPE_UNKNOWN: number;
            SVG_TURBULENCE_TYPE_TURBULENCE: number;
            SVG_TURBULENCE_TYPE_FRACTALNOISE: number;
            SVG_STITCHTYPE_STITCH: number;
        }
        
        interface TextTrackList extends EventTarget {
            length: number;
            onaddtrack: (ev: TrackEvent) => any;
            item(index: number): TextTrack;
            [index: number]: TextTrack;
            addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var TextTrackList: {
            prototype: TextTrackList;
            new(): TextTrackList;
        }
        
        interface SVGFEFuncGElement extends SVGComponentTransferFunctionElement {
        }
        declare var SVGFEFuncGElement: {
            prototype: SVGFEFuncGElement;
            new(): SVGFEFuncGElement;
        }
        
        interface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            type: SVGAnimatedEnumeration;
            values: SVGAnimatedNumberList;
            SVG_FECOLORMATRIX_TYPE_SATURATE: number;
            SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;
            SVG_FECOLORMATRIX_TYPE_MATRIX: number;
            SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;
            SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;
        }
        declare var SVGFEColorMatrixElement: {
            prototype: SVGFEColorMatrixElement;
            new(): SVGFEColorMatrixElement;
            SVG_FECOLORMATRIX_TYPE_SATURATE: number;
            SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;
            SVG_FECOLORMATRIX_TYPE_MATRIX: number;
            SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;
            SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;
        }
        
        interface SVGFESpotLightElement extends SVGElement {
            pointsAtY: SVGAnimatedNumber;
            y: SVGAnimatedNumber;
            limitingConeAngle: SVGAnimatedNumber;
            specularExponent: SVGAnimatedNumber;
            x: SVGAnimatedNumber;
            pointsAtZ: SVGAnimatedNumber;
            z: SVGAnimatedNumber;
            pointsAtX: SVGAnimatedNumber;
        }
        declare var SVGFESpotLightElement: {
            prototype: SVGFESpotLightElement;
            new(): SVGFESpotLightElement;
        }
        
        interface WindowBase64 {
            btoa(rawString: string): string;
            atob(encodedString: string): string;
        }
        
        interface IDBDatabase extends EventTarget {
            version: string;
            name: string;
            objectStoreNames: DOMStringList;
            onerror: (ev: ErrorEvent) => any;
            onabort: (ev: UIEvent) => any;
            createObjectStore(name: string, optionalParameters?: any): IDBObjectStore;
            close(): void;
            transaction(storeNames: any, mode?: string): IDBTransaction;
            deleteObjectStore(name: string): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var IDBDatabase: {
            prototype: IDBDatabase;
            new(): IDBDatabase;
        }
        
        interface DOMStringList {
            length: number;
            contains(str: string): boolean;
            item(index: number): string;
            [index: number]: string;
        }
        declare var DOMStringList: {
            prototype: DOMStringList;
            new(): DOMStringList;
        }
        
        interface IDBOpenDBRequest extends IDBRequest {
            onupgradeneeded: (ev: IDBVersionChangeEvent) => any;
            onblocked: (ev: Event) => any;
            addEventListener(type: "success", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "upgradeneeded", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blocked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var IDBOpenDBRequest: {
            prototype: IDBOpenDBRequest;
            new(): IDBOpenDBRequest;
        }
        
        interface HTMLProgressElement extends HTMLElement {
            /**
              * Sets or gets the current value of a progress element. The value must be a non-negative number between 0 and the max value.
              */
            value: number;
            /**
              * Defines the maximum, or "done" value for a progress element.
              */
            max: number;
            /**
              * Returns the quotient of value/max when the value attribute is set (determinate progress bar), or -1 when the value attribute is missing (indeterminate progress bar).
              */
            position: number;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
        }
        declare var HTMLProgressElement: {
            prototype: HTMLProgressElement;
            new(): HTMLProgressElement;
        }
        
        interface MSLaunchUriCallback {
            (): void;
        }
        
        interface SVGFEOffsetElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            dy: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            dx: SVGAnimatedNumber;
        }
        declare var SVGFEOffsetElement: {
            prototype: SVGFEOffsetElement;
            new(): SVGFEOffsetElement;
        }
        
        interface MSUnsafeFunctionCallback {
            (): any;
        }
        
        interface TextTrack extends EventTarget {
            language: string;
            mode: any;
            readyState: number;
            activeCues: TextTrackCueList;
            cues: TextTrackCueList;
            oncuechange: (ev: Event) => any;
            kind: string;
            onload: (ev: Event) => any;
            onerror: (ev: ErrorEvent) => any;
            label: string;
            addCue(cue: TextTrackCue): void;
            removeCue(cue: TextTrackCue): void;
            ERROR: number;
            SHOWING: number;
            LOADING: number;
            LOADED: number;
            NONE: number;
            HIDDEN: number;
            DISABLED: number;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var TextTrack: {
            prototype: TextTrack;
            new(): TextTrack;
            ERROR: number;
            SHOWING: number;
            LOADING: number;
            LOADED: number;
            NONE: number;
            HIDDEN: number;
            DISABLED: number;
        }
        
        interface MediaQueryListListener {
            (mql: MediaQueryList): void;
        }
        
        interface IDBRequest extends EventTarget {
            source: any;
            onsuccess: (ev: Event) => any;
            error: DOMError;
            transaction: IDBTransaction;
            onerror: (ev: ErrorEvent) => any;
            readyState: string;
            result: any;
            addEventListener(type: "success", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var IDBRequest: {
            prototype: IDBRequest;
            new(): IDBRequest;
        }
        
        interface MessagePort extends EventTarget {
            onmessage: (ev: MessageEvent) => any;
            close(): void;
            postMessage(message?: any, ports?: any): void;
            start(): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var MessagePort: {
            prototype: MessagePort;
            new(): MessagePort;
        }
        
        interface FileReader extends MSBaseReader {
            error: DOMError;
            readAsArrayBuffer(blob: Blob): void;
            readAsDataURL(blob: Blob): void;
            readAsText(blob: Blob, encoding?: string): void;
        }
        declare var FileReader: {
            prototype: FileReader;
            new(): FileReader;
        }
        
        interface ApplicationCache extends EventTarget {
            status: number;
            ondownloading: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            onupdateready: (ev: Event) => any;
            oncached: (ev: Event) => any;
            onobsolete: (ev: Event) => any;
            onerror: (ev: ErrorEvent) => any;
            onchecking: (ev: Event) => any;
            onnoupdate: (ev: Event) => any;
            swapCache(): void;
            abort(): void;
            update(): void;
            CHECKING: number;
            UNCACHED: number;
            UPDATEREADY: number;
            DOWNLOADING: number;
            IDLE: number;
            OBSOLETE: number;
            addEventListener(type: "downloading", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "updateready", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cached", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "obsolete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "checking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "noupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var ApplicationCache: {
            prototype: ApplicationCache;
            new(): ApplicationCache;
            CHECKING: number;
            UNCACHED: number;
            UPDATEREADY: number;
            DOWNLOADING: number;
            IDLE: number;
            OBSOLETE: number;
        }
        
        interface FrameRequestCallback {
            (time: number): void;
        }
        
        interface PopStateEvent extends Event {
            state: any;
            initPopStateEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, stateArg: any): void;
        }
        declare var PopStateEvent: {
            prototype: PopStateEvent;
            new(): PopStateEvent;
        }
        
        interface CSSKeyframeRule extends CSSRule {
            keyText: string;
            style: CSSStyleDeclaration;
        }
        declare var CSSKeyframeRule: {
            prototype: CSSKeyframeRule;
            new(): CSSKeyframeRule;
        }
        
        interface MSFileSaver {
            msSaveBlob(blob: any, defaultName?: string): boolean;
            msSaveOrOpenBlob(blob: any, defaultName?: string): boolean;
        }
        
        interface MSStream {
            type: string;
            msDetachStream(): any;
            msClose(): void;
        }
        declare var MSStream: {
            prototype: MSStream;
            new(): MSStream;
        }
        
        interface MSBlobBuilder {
            append(data: any, endings?: string): void;
            getBlob(contentType?: string): Blob;
        }
        declare var MSBlobBuilder: {
            prototype: MSBlobBuilder;
            new(): MSBlobBuilder;
        }
        
        interface DOMSettableTokenList extends DOMTokenList {
            value: string;
        }
        declare var DOMSettableTokenList: {
            prototype: DOMSettableTokenList;
            new(): DOMSettableTokenList;
        }
        
        interface IDBFactory {
            open(name: string, version?: number): IDBOpenDBRequest;
            cmp(first: any, second: any): number;
            deleteDatabase(name: string): IDBOpenDBRequest;
        }
        declare var IDBFactory: {
            prototype: IDBFactory;
            new(): IDBFactory;
        }
        
        interface MSPointerEvent extends MouseEvent {
            width: number;
            rotation: number;
            pressure: number;
            pointerType: any;
            isPrimary: boolean;
            tiltY: number;
            height: number;
            intermediatePoints: any;
            currentPoint: any;
            tiltX: number;
            hwTimestamp: number;
            pointerId: number;
            initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;
            getCurrentPoint(element: Element): void;
            getIntermediatePoints(element: Element): void;
            MSPOINTER_TYPE_PEN: number;
            MSPOINTER_TYPE_MOUSE: number;
            MSPOINTER_TYPE_TOUCH: number;
        }
        declare var MSPointerEvent: {
            prototype: MSPointerEvent;
            new(): MSPointerEvent;
            MSPOINTER_TYPE_PEN: number;
            MSPOINTER_TYPE_MOUSE: number;
            MSPOINTER_TYPE_TOUCH: number;
        }
        
        interface MSManipulationEvent extends UIEvent {
            lastState: number;
            currentState: number;
            initMSManipulationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, lastState: number, currentState: number): void;
            MS_MANIPULATION_STATE_STOPPED: number;
            MS_MANIPULATION_STATE_ACTIVE: number;
            MS_MANIPULATION_STATE_INERTIA: number;
            MS_MANIPULATION_STATE_SELECTING: number;
            MS_MANIPULATION_STATE_COMMITTED: number;
            MS_MANIPULATION_STATE_PRESELECT: number;
            MS_MANIPULATION_STATE_DRAGGING: number;
            MS_MANIPULATION_STATE_CANCELLED: number;
        }
        declare var MSManipulationEvent: {
            prototype: MSManipulationEvent;
            new(): MSManipulationEvent;
            MS_MANIPULATION_STATE_STOPPED: number;
            MS_MANIPULATION_STATE_ACTIVE: number;
            MS_MANIPULATION_STATE_INERTIA: number;
            MS_MANIPULATION_STATE_SELECTING: number;
            MS_MANIPULATION_STATE_COMMITTED: number;
            MS_MANIPULATION_STATE_PRESELECT: number;
            MS_MANIPULATION_STATE_DRAGGING: number;
            MS_MANIPULATION_STATE_CANCELLED: number;
        }
        
        interface FormData {
            append(name: any, value: any, blobName?: string): void;
        }
        declare var FormData: {
            prototype: FormData;
            new(): FormData;
        }
        
        interface HTMLDataListElement extends HTMLElement {
            options: HTMLCollection;
        }
        declare var HTMLDataListElement: {
            prototype: HTMLDataListElement;
            new(): HTMLDataListElement;
        }
        
        interface SVGFEImageElement extends SVGElement, SVGLangSpace, SVGFilterPrimitiveStandardAttributes, SVGURIReference, SVGExternalResourcesRequired {
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
        }
        declare var SVGFEImageElement: {
            prototype: SVGFEImageElement;
            new(): SVGFEImageElement;
        }
        
        interface AbstractWorker extends EventTarget {
            onerror: (ev: ErrorEvent) => any;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        
        interface SVGFECompositeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            operator: SVGAnimatedEnumeration;
            in2: SVGAnimatedString;
            k2: SVGAnimatedNumber;
            k1: SVGAnimatedNumber;
            k3: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            k4: SVGAnimatedNumber;
            SVG_FECOMPOSITE_OPERATOR_OUT: number;
            SVG_FECOMPOSITE_OPERATOR_OVER: number;
            SVG_FECOMPOSITE_OPERATOR_XOR: number;
            SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;
            SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;
            SVG_FECOMPOSITE_OPERATOR_IN: number;
            SVG_FECOMPOSITE_OPERATOR_ATOP: number;
        }
        declare var SVGFECompositeElement: {
            prototype: SVGFECompositeElement;
            new(): SVGFECompositeElement;
            SVG_FECOMPOSITE_OPERATOR_OUT: number;
            SVG_FECOMPOSITE_OPERATOR_OVER: number;
            SVG_FECOMPOSITE_OPERATOR_XOR: number;
            SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;
            SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;
            SVG_FECOMPOSITE_OPERATOR_IN: number;
            SVG_FECOMPOSITE_OPERATOR_ATOP: number;
        }
        
        interface ValidityState {
            customError: boolean;
            valueMissing: boolean;
            stepMismatch: boolean;
            rangeUnderflow: boolean;
            rangeOverflow: boolean;
            typeMismatch: boolean;
            patternMismatch: boolean;
            tooLong: boolean;
            valid: boolean;
        }
        declare var ValidityState: {
            prototype: ValidityState;
            new(): ValidityState;
        }
        
        interface HTMLTrackElement extends HTMLElement {
            kind: string;
            src: string;
            srclang: string;
            track: TextTrack;
            label: string;
            default: boolean;
            readyState: number;
            ERROR: number;
            LOADING: number;
            LOADED: number;
            NONE: number;
        }
        declare var HTMLTrackElement: {
            prototype: HTMLTrackElement;
            new(): HTMLTrackElement;
            ERROR: number;
            LOADING: number;
            LOADED: number;
            NONE: number;
        }
        
        interface MSApp {
            createFileFromStorageFile(storageFile: any): File;
            createBlobFromRandomAccessStream(type: string, seeker: any): Blob;
            createStreamFromInputStream(type: string, inputStream: any): MSStream;
            terminateApp(exceptionObject: any): void;
            createDataPackage(object: any): any;
            execUnsafeLocalFunction(unsafeFunction: MSUnsafeFunctionCallback): any;
            getHtmlPrintDocumentSource(htmlDoc: any): any;
            addPublicLocalApplicationUri(uri: string): void;
            createDataPackageFromSelection(): any;
            getViewOpener(): MSAppView;
            suppressSubdownloadCredentialPrompts(suppress: boolean): void;
            execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void;
            isTaskScheduledAtPriorityOrHigher(priority: string): boolean;
            execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any;
            createNewView(uri: string): MSAppView;
            getCurrentPriority(): string;
            NORMAL: string;
            HIGH: string;
            IDLE: string;
            CURRENT: string;
        }
        declare var MSApp: MSApp;
        
        interface SVGFEComponentTransferElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
        }
        declare var SVGFEComponentTransferElement: {
            prototype: SVGFEComponentTransferElement;
            new(): SVGFEComponentTransferElement;
        }
        
        interface SVGFEDiffuseLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            kernelUnitLengthY: SVGAnimatedNumber;
            surfaceScale: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            kernelUnitLengthX: SVGAnimatedNumber;
            diffuseConstant: SVGAnimatedNumber;
        }
        declare var SVGFEDiffuseLightingElement: {
            prototype: SVGFEDiffuseLightingElement;
            new(): SVGFEDiffuseLightingElement;
        }
        
        interface MSCSSMatrix {
            m24: number;
            m34: number;
            a: number;
            d: number;
            m32: number;
            m41: number;
            m11: number;
            f: number;
            e: number;
            m23: number;
            m14: number;
            m33: number;
            m22: number;
            m21: number;
            c: number;
            m12: number;
            b: number;
            m42: number;
            m31: number;
            m43: number;
            m13: number;
            m44: number;
            multiply(secondMatrix: MSCSSMatrix): MSCSSMatrix;
            skewY(angle: number): MSCSSMatrix;
            setMatrixValue(value: string): void;
            inverse(): MSCSSMatrix;
            rotateAxisAngle(x: number, y: number, z: number, angle: number): MSCSSMatrix;
            toString(): string;
            rotate(angleX: number, angleY?: number, angleZ?: number): MSCSSMatrix;
            translate(x: number, y: number, z?: number): MSCSSMatrix;
            scale(scaleX: number, scaleY?: number, scaleZ?: number): MSCSSMatrix;
            skewX(angle: number): MSCSSMatrix;
        }
        declare var MSCSSMatrix: {
            prototype: MSCSSMatrix;
            new(text?: string): MSCSSMatrix;
        }
        
        interface Worker extends AbstractWorker {
            onmessage: (ev: MessageEvent) => any;
            postMessage(message: any, ports?: any): void;
            terminate(): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var Worker: {
            prototype: Worker;
            new(stringUrl: string): Worker;
        }
        
        interface MSExecAtPriorityFunctionCallback {
            (...args: any[]): any;
        }
        
        interface MSGraphicsTrust {
            status: string;
            constrictionActive: boolean;
        }
        declare var MSGraphicsTrust: {
            prototype: MSGraphicsTrust;
            new(): MSGraphicsTrust;
        }
        
        interface SubtleCrypto {
            unwrapKey(wrappedKey: ArrayBufferView, keyAlgorithm: any, keyEncryptionKey: Key, extractable?: boolean, keyUsages?: string[]): KeyOperation;
            encrypt(algorithm: any, key: Key, buffer?: ArrayBufferView): CryptoOperation;
            importKey(format: string, keyData: ArrayBufferView, algorithm: any, extractable?: boolean, keyUsages?: string[]): KeyOperation;
            wrapKey(key: Key, keyEncryptionKey: Key, keyWrappingAlgorithm: any): KeyOperation;
            verify(algorithm: any, key: Key, signature: ArrayBufferView, buffer?: ArrayBufferView): CryptoOperation;
            deriveKey(algorithm: any, baseKey: Key, derivedKeyType: any, extractable?: boolean, keyUsages?: string[]): KeyOperation;
            digest(algorithm: any, buffer?: ArrayBufferView): CryptoOperation;
            exportKey(format: string, key: Key): KeyOperation;
            generateKey(algorithm: any, extractable?: boolean, keyUsages?: string[]): KeyOperation;
            sign(algorithm: any, key: Key, buffer?: ArrayBufferView): CryptoOperation;
            decrypt(algorithm: any, key: Key, buffer?: ArrayBufferView): CryptoOperation;
        }
        declare var SubtleCrypto: {
            prototype: SubtleCrypto;
            new(): SubtleCrypto;
        }
        
        interface Crypto extends RandomSource {
            subtle: SubtleCrypto;
        }
        declare var Crypto: {
            prototype: Crypto;
            new(): Crypto;
        }
        
        interface VideoPlaybackQuality {
            totalFrameDelay: number;
            creationTime: number;
            totalVideoFrames: number;
            droppedVideoFrames: number;
        }
        declare var VideoPlaybackQuality: {
            prototype: VideoPlaybackQuality;
            new(): VideoPlaybackQuality;
        }
        
        interface GlobalEventHandlers {
            onpointerenter: (ev: PointerEvent) => any;
            onpointerout: (ev: PointerEvent) => any;
            onpointerdown: (ev: PointerEvent) => any;
            onpointerup: (ev: PointerEvent) => any;
            onpointercancel: (ev: PointerEvent) => any;
            onpointerover: (ev: PointerEvent) => any;
            onpointermove: (ev: PointerEvent) => any;
            onpointerleave: (ev: PointerEvent) => any;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        
        interface Key {
            algorithm: Algorithm;
            type: string;
            extractable: boolean;
            keyUsage: string[];
        }
        declare var Key: {
            prototype: Key;
            new(): Key;
        }
        
        interface DeviceAcceleration {
            y: number;
            x: number;
            z: number;
        }
        declare var DeviceAcceleration: {
            prototype: DeviceAcceleration;
            new(): DeviceAcceleration;
        }
        
        interface HTMLAllCollection extends HTMLCollection {
            namedItem(name: string): Element;
            // [name: string]: Element;
        }
        declare var HTMLAllCollection: {
            prototype: HTMLAllCollection;
            new(): HTMLAllCollection;
        }
        
        interface AesGcmEncryptResult {
            ciphertext: ArrayBuffer;
            tag: ArrayBuffer;
        }
        declare var AesGcmEncryptResult: {
            prototype: AesGcmEncryptResult;
            new(): AesGcmEncryptResult;
        }
        
        interface NavigationCompletedEvent extends NavigationEvent {
            webErrorStatus: number;
            isSuccess: boolean;
        }
        declare var NavigationCompletedEvent: {
            prototype: NavigationCompletedEvent;
            new(): NavigationCompletedEvent;
        }
        
        interface MutationRecord {
            oldValue: string;
            previousSibling: Node;
            addedNodes: NodeList;
            attributeName: string;
            removedNodes: NodeList;
            target: Node;
            nextSibling: Node;
            attributeNamespace: string;
            type: string;
        }
        declare var MutationRecord: {
            prototype: MutationRecord;
            new(): MutationRecord;
        }
        
        interface MimeTypeArray {
            length: number;
            item(index: number): Plugin;
            [index: number]: Plugin;
            namedItem(type: string): Plugin;
            // [type: string]: Plugin;
        }
        declare var MimeTypeArray: {
            prototype: MimeTypeArray;
            new(): MimeTypeArray;
        }
        
        interface KeyOperation extends EventTarget {
            oncomplete: (ev: Event) => any;
            onerror: (ev: ErrorEvent) => any;
            result: any;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var KeyOperation: {
            prototype: KeyOperation;
            new(): KeyOperation;
        }
        
        interface DOMStringMap {
        }
        declare var DOMStringMap: {
            prototype: DOMStringMap;
            new(): DOMStringMap;
        }
        
        interface DeviceOrientationEvent extends Event {
            gamma: number;
            alpha: number;
            absolute: boolean;
            beta: number;
            initDeviceOrientationEvent(type: string, bubbles: boolean, cancelable: boolean, alpha: number, beta: number, gamma: number, absolute: boolean): void;
        }
        declare var DeviceOrientationEvent: {
            prototype: DeviceOrientationEvent;
            new(): DeviceOrientationEvent;
        }
        
        interface MSMediaKeys {
            keySystem: string;
            createSession(type: string, initData: Uint8Array, cdmData?: Uint8Array): MSMediaKeySession;
        }
        declare var MSMediaKeys: {
            prototype: MSMediaKeys;
            new(keySystem: string): MSMediaKeys;
            isTypeSupported(keySystem: string, type?: string): boolean;
        }
        
        interface MSMediaKeyMessageEvent extends Event {
            destinationURL: string;
            message: Uint8Array;
        }
        declare var MSMediaKeyMessageEvent: {
            prototype: MSMediaKeyMessageEvent;
            new(): MSMediaKeyMessageEvent;
        }
        
        interface MSHTMLWebViewElement extends HTMLElement {
            documentTitle: string;
            width: number;
            src: string;
            canGoForward: boolean;
            height: number;
            canGoBack: boolean;
            navigateWithHttpRequestMessage(requestMessage: any): void;
            goBack(): void;
            navigate(uri: string): void;
            stop(): void;
            navigateToString(contents: string): void;
            captureSelectedContentToDataPackageAsync(): MSWebViewAsyncOperation;
            capturePreviewToBlobAsync(): MSWebViewAsyncOperation;
            refresh(): void;
            goForward(): void;
            navigateToLocalStreamUri(source: string, streamResolver: any): void;
            invokeScriptAsync(scriptName: string, ...args: any[]): MSWebViewAsyncOperation;
            buildLocalStreamUri(contentIdentifier: string, relativePath: string): string;
        }
        declare var MSHTMLWebViewElement: {
            prototype: MSHTMLWebViewElement;
            new(): MSHTMLWebViewElement;
        }
        
        interface NavigationEvent extends Event {
            uri: string;
        }
        declare var NavigationEvent: {
            prototype: NavigationEvent;
            new(): NavigationEvent;
        }
        
        interface RandomSource {
            getRandomValues(array: ArrayBufferView): ArrayBufferView;
        }
        
        interface SourceBuffer extends EventTarget {
            updating: boolean;
            appendWindowStart: number;
            appendWindowEnd: number;
            buffered: TimeRanges;
            timestampOffset: number;
            audioTracks: AudioTrackList;
            appendBuffer(data: ArrayBuffer): void;
            remove(start: number, end: number): void;
            abort(): void;
            appendStream(stream: MSStream, maxSize?: number): void;
        }
        declare var SourceBuffer: {
            prototype: SourceBuffer;
            new(): SourceBuffer;
        }
        
        interface MSInputMethodContext extends EventTarget {
            oncandidatewindowshow: (ev: any) => any;
            target: HTMLElement;
            compositionStartOffset: number;
            oncandidatewindowhide: (ev: any) => any;
            oncandidatewindowupdate: (ev: any) => any;
            compositionEndOffset: number;
            getCompositionAlternatives(): string[];
            getCandidateWindowClientRect(): ClientRect;
            hasComposition(): boolean;
            isCandidateWindowVisible(): boolean;
            addEventListener(type: "candidatewindowshow", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "candidatewindowhide", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: "candidatewindowupdate", listener: (ev: any) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var MSInputMethodContext: {
            prototype: MSInputMethodContext;
            new(): MSInputMethodContext;
        }
        
        interface DeviceRotationRate {
            gamma: number;
            alpha: number;
            beta: number;
        }
        declare var DeviceRotationRate: {
            prototype: DeviceRotationRate;
            new(): DeviceRotationRate;
        }
        
        interface PluginArray {
            length: number;
            refresh(reload?: boolean): void;
            item(index: number): Plugin;
            [index: number]: Plugin;
            namedItem(name: string): Plugin;
            // [name: string]: Plugin;
        }
        declare var PluginArray: {
            prototype: PluginArray;
            new(): PluginArray;
        }
        
        interface MSMediaKeyError {
            systemCode: number;
            code: number;
            MS_MEDIA_KEYERR_SERVICE: number;
            MS_MEDIA_KEYERR_HARDWARECHANGE: number;
            MS_MEDIA_KEYERR_OUTPUT: number;
            MS_MEDIA_KEYERR_DOMAIN: number;
            MS_MEDIA_KEYERR_UNKNOWN: number;
            MS_MEDIA_KEYERR_CLIENT: number;
        }
        declare var MSMediaKeyError: {
            prototype: MSMediaKeyError;
            new(): MSMediaKeyError;
            MS_MEDIA_KEYERR_SERVICE: number;
            MS_MEDIA_KEYERR_HARDWARECHANGE: number;
            MS_MEDIA_KEYERR_OUTPUT: number;
            MS_MEDIA_KEYERR_DOMAIN: number;
            MS_MEDIA_KEYERR_UNKNOWN: number;
            MS_MEDIA_KEYERR_CLIENT: number;
        }
        
        interface Plugin {
            length: number;
            filename: string;
            version: string;
            name: string;
            description: string;
            item(index: number): MimeType;
            [index: number]: MimeType;
            namedItem(type: string): MimeType;
            // [type: string]: MimeType;
        }
        declare var Plugin: {
            prototype: Plugin;
            new(): Plugin;
        }
        
        interface MediaSource extends EventTarget {
            sourceBuffers: SourceBufferList;
            duration: number;
            readyState: string;
            activeSourceBuffers: SourceBufferList;
            addSourceBuffer(type: string): SourceBuffer;
            endOfStream(error?: string): void;
            removeSourceBuffer(sourceBuffer: SourceBuffer): void;
        }
        declare var MediaSource: {
            prototype: MediaSource;
            new(): MediaSource;
            isTypeSupported(type: string): boolean;
        }
        
        interface SourceBufferList extends EventTarget {
            length: number;
            item(index: number): SourceBuffer;
            [index: number]: SourceBuffer;
        }
        declare var SourceBufferList: {
            prototype: SourceBufferList;
            new(): SourceBufferList;
        }
        
        interface XMLDocument extends Document {
        }
        declare var XMLDocument: {
            prototype: XMLDocument;
            new(): XMLDocument;
        }
        
        interface DeviceMotionEvent extends Event {
            rotationRate: DeviceRotationRate;
            acceleration: DeviceAcceleration;
            interval: number;
            accelerationIncludingGravity: DeviceAcceleration;
            initDeviceMotionEvent(type: string, bubbles: boolean, cancelable: boolean, acceleration: DeviceAccelerationDict, accelerationIncludingGravity: DeviceAccelerationDict, rotationRate: DeviceRotationRateDict, interval: number): void;
        }
        declare var DeviceMotionEvent: {
            prototype: DeviceMotionEvent;
            new(): DeviceMotionEvent;
        }
        
        interface MimeType {
            enabledPlugin: Plugin;
            suffixes: string;
            type: string;
            description: string;
        }
        declare var MimeType: {
            prototype: MimeType;
            new(): MimeType;
        }
        
        interface PointerEvent extends MouseEvent {
            width: number;
            rotation: number;
            pressure: number;
            pointerType: any;
            isPrimary: boolean;
            tiltY: number;
            height: number;
            intermediatePoints: any;
            currentPoint: any;
            tiltX: number;
            hwTimestamp: number;
            pointerId: number;
            initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;
            getCurrentPoint(element: Element): void;
            getIntermediatePoints(element: Element): void;
        }
        declare var PointerEvent: {
            prototype: PointerEvent;
            new(): PointerEvent;
        }
        
        interface MSDocumentExtensions {
            captureEvents(): void;
            releaseEvents(): void;
        }
        
        interface MutationObserver {
            observe(target: Node, options: MutationObserverInit): void;
            takeRecords(): MutationRecord[];
            disconnect(): void;
        }
        declare var MutationObserver: {
            prototype: MutationObserver;
            new (callback: (arr: MutationRecord[], observer: MutationObserver)=>any): MutationObserver;
        }
        
        interface MSWebViewAsyncOperation extends EventTarget {
            target: MSHTMLWebViewElement;
            oncomplete: (ev: Event) => any;
            error: DOMError;
            onerror: (ev: ErrorEvent) => any;
            readyState: number;
            type: number;
            result: any;
            start(): void;
            ERROR: number;
            TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;
            TYPE_INVOKE_SCRIPT: number;
            COMPLETED: number;
            TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;
            STARTED: number;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var MSWebViewAsyncOperation: {
            prototype: MSWebViewAsyncOperation;
            new(): MSWebViewAsyncOperation;
            ERROR: number;
            TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;
            TYPE_INVOKE_SCRIPT: number;
            COMPLETED: number;
            TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;
            STARTED: number;
        }
        
        interface ScriptNotifyEvent extends Event {
            value: string;
            callingUri: string;
        }
        declare var ScriptNotifyEvent: {
            prototype: ScriptNotifyEvent;
            new(): ScriptNotifyEvent;
        }
        
        interface PerformanceNavigationTiming extends PerformanceEntry {
            redirectStart: number;
            domainLookupEnd: number;
            responseStart: number;
            domComplete: number;
            domainLookupStart: number;
            loadEventStart: number;
            unloadEventEnd: number;
            fetchStart: number;
            requestStart: number;
            domInteractive: number;
            navigationStart: number;
            connectEnd: number;
            loadEventEnd: number;
            connectStart: number;
            responseEnd: number;
            domLoading: number;
            redirectEnd: number;
            redirectCount: number;
            unloadEventStart: number;
            domContentLoadedEventStart: number;
            domContentLoadedEventEnd: number;
            type: string;
        }
        declare var PerformanceNavigationTiming: {
            prototype: PerformanceNavigationTiming;
            new(): PerformanceNavigationTiming;
        }
        
        interface MSMediaKeyNeededEvent extends Event {
            initData: Uint8Array;
        }
        declare var MSMediaKeyNeededEvent: {
            prototype: MSMediaKeyNeededEvent;
            new(): MSMediaKeyNeededEvent;
        }
        
        interface LongRunningScriptDetectedEvent extends Event {
            stopPageScriptExecution: boolean;
            executionTime: number;
        }
        declare var LongRunningScriptDetectedEvent: {
            prototype: LongRunningScriptDetectedEvent;
            new(): LongRunningScriptDetectedEvent;
        }
        
        interface MSAppView {
            viewId: number;
            close(): void;
            postMessage(message: any, targetOrigin: string, ports?: any): void;
        }
        declare var MSAppView: {
            prototype: MSAppView;
            new(): MSAppView;
        }
        
        interface PerfWidgetExternal {
            maxCpuSpeed: number;
            independentRenderingEnabled: boolean;
            irDisablingContentString: string;
            irStatusAvailable: boolean;
            performanceCounter: number;
            averagePaintTime: number;
            activeNetworkRequestCount: number;
            paintRequestsPerSecond: number;
            extraInformationEnabled: boolean;
            performanceCounterFrequency: number;
            averageFrameTime: number;
            repositionWindow(x: number, y: number): void;
            getRecentMemoryUsage(last: number): any;
            getMemoryUsage(): number;
            resizeWindow(width: number, height: number): void;
            getProcessCpuUsage(): number;
            removeEventListener(eventType: string, callback: (ev: any) => any): void;
            getRecentCpuUsage(last: number): any;
            addEventListener(eventType: string, callback: (ev: any) => any): void;
            getRecentFrames(last: number): any;
            getRecentPaintRequests(last: number): any;
        }
        declare var PerfWidgetExternal: {
            prototype: PerfWidgetExternal;
            new(): PerfWidgetExternal;
        }
        
        interface PageTransitionEvent extends Event {
            persisted: boolean;
        }
        declare var PageTransitionEvent: {
            prototype: PageTransitionEvent;
            new(): PageTransitionEvent;
        }
        
        interface MutationCallback {
            (mutations: MutationRecord[], observer: MutationObserver): void;
        }
        
        interface HTMLDocument extends Document {
        }
        declare var HTMLDocument: {
            prototype: HTMLDocument;
            new(): HTMLDocument;
        }
        
        interface KeyPair {
            privateKey: Key;
            publicKey: Key;
        }
        declare var KeyPair: {
            prototype: KeyPair;
            new(): KeyPair;
        }
        
        interface MSMediaKeySession extends EventTarget {
            sessionId: string;
            error: MSMediaKeyError;
            keySystem: string;
            close(): void;
            update(key: Uint8Array): void;
        }
        declare var MSMediaKeySession: {
            prototype: MSMediaKeySession;
            new(): MSMediaKeySession;
        }
        
        interface UnviewableContentIdentifiedEvent extends NavigationEvent {
            referrer: string;
        }
        declare var UnviewableContentIdentifiedEvent: {
            prototype: UnviewableContentIdentifiedEvent;
            new(): UnviewableContentIdentifiedEvent;
        }
        
        interface CryptoOperation extends EventTarget {
            algorithm: Algorithm;
            oncomplete: (ev: Event) => any;
            onerror: (ev: ErrorEvent) => any;
            onprogress: (ev: ProgressEvent) => any;
            onabort: (ev: UIEvent) => any;
            key: Key;
            result: any;
            abort(): void;
            finish(): void;
            process(buffer: ArrayBufferView): void;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        }
        declare var CryptoOperation: {
            prototype: CryptoOperation;
            new(): CryptoOperation;
        }
        
        interface WebGLTexture extends WebGLObject {
        }
        declare var WebGLTexture: {
            prototype: WebGLTexture;
            new(): WebGLTexture;
        }
        
        interface OES_texture_float {
        }
        declare var OES_texture_float: {
            prototype: OES_texture_float;
            new(): OES_texture_float;
        }
        
        interface WebGLContextEvent extends Event {
            statusMessage: string;
        }
        declare var WebGLContextEvent: {
            prototype: WebGLContextEvent;
            new(): WebGLContextEvent;
        }
        
        interface WebGLRenderbuffer extends WebGLObject {
        }
        declare var WebGLRenderbuffer: {
            prototype: WebGLRenderbuffer;
            new(): WebGLRenderbuffer;
        }
        
        interface WebGLUniformLocation {
        }
        declare var WebGLUniformLocation: {
            prototype: WebGLUniformLocation;
            new(): WebGLUniformLocation;
        }
        
        interface WebGLActiveInfo {
            name: string;
            type: number;
            size: number;
        }
        declare var WebGLActiveInfo: {
            prototype: WebGLActiveInfo;
            new(): WebGLActiveInfo;
        }
        
        interface WEBGL_compressed_texture_s3tc {
            COMPRESSED_RGBA_S3TC_DXT1_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT5_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT3_EXT: number;
            COMPRESSED_RGB_S3TC_DXT1_EXT: number;
        }
        declare var WEBGL_compressed_texture_s3tc: {
            prototype: WEBGL_compressed_texture_s3tc;
            new(): WEBGL_compressed_texture_s3tc;
            COMPRESSED_RGBA_S3TC_DXT1_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT5_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT3_EXT: number;
            COMPRESSED_RGB_S3TC_DXT1_EXT: number;
        }
        
        interface WebGLRenderingContext {
            drawingBufferWidth: number;
            drawingBufferHeight: number;
            canvas: HTMLCanvasElement;
            getUniformLocation(program: WebGLProgram, name: string): WebGLUniformLocation;
            bindTexture(target: number, texture: WebGLTexture): void;
            bufferData(target: number, data: ArrayBufferView, usage: number): void;
            bufferData(target: number, data: ArrayBuffer, usage: number): void;
            bufferData(target: number, size: number, usage: number): void;
            depthMask(flag: boolean): void;
            getUniform(program: WebGLProgram, location: WebGLUniformLocation): any;
            vertexAttrib3fv(indx: number, values: number[]): void;
            vertexAttrib3fv(indx: number, values: Float32Array): void;
            linkProgram(program: WebGLProgram): void;
            getSupportedExtensions(): string[];
            bufferSubData(target: number, offset: number, data: ArrayBuffer): void;
            bufferSubData(target: number, offset: number, data: ArrayBufferView): void;
            vertexAttribPointer(indx: number, size: number, type: number, normalized: boolean, stride: number, offset: number): void;
            polygonOffset(factor: number, units: number): void;
            blendColor(red: number, green: number, blue: number, alpha: number): void;
            createTexture(): WebGLTexture;
            hint(target: number, mode: number): void;
            getVertexAttrib(index: number, pname: number): any;
            enableVertexAttribArray(index: number): void;
            depthRange(zNear: number, zFar: number): void;
            cullFace(mode: number): void;
            createFramebuffer(): WebGLFramebuffer;
            uniformMatrix4fv(location: WebGLUniformLocation, transpose: boolean, value: number[]): void;
            uniformMatrix4fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array): void;
            framebufferTexture2D(target: number, attachment: number, textarget: number, texture: WebGLTexture, level: number): void;
            deleteFramebuffer(framebuffer: WebGLFramebuffer): void;
            colorMask(red: boolean, green: boolean, blue: boolean, alpha: boolean): void;
            compressedTexImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, data: ArrayBufferView): void;
            uniformMatrix2fv(location: WebGLUniformLocation, transpose: boolean, value: number[]): void;
            uniformMatrix2fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array): void;
            getExtension(name: string): any;
            createProgram(): WebGLProgram;
            deleteShader(shader: WebGLShader): void;
            getAttachedShaders(program: WebGLProgram): WebGLShader[];
            enable(cap: number): void;
            blendEquation(mode: number): void;
            texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels: ArrayBufferView): void;
            texImage2D(target: number, level: number, internalformat: number, format: number, type: number, image: HTMLImageElement): void;
            texImage2D(target: number, level: number, internalformat: number, format: number, type: number, canvas: HTMLCanvasElement): void;
            texImage2D(target: number, level: number, internalformat: number, format: number, type: number, video: HTMLVideoElement): void;
            texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageData): void;
            createBuffer(): WebGLBuffer;
            deleteTexture(texture: WebGLTexture): void;
            useProgram(program: WebGLProgram): void;
            vertexAttrib2fv(indx: number, values: number[]): void;
            vertexAttrib2fv(indx: number, values: Float32Array): void;
            checkFramebufferStatus(target: number): number;
            frontFace(mode: number): void;
            getBufferParameter(target: number, pname: number): any;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView): void;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, image: HTMLImageElement): void;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, canvas: HTMLCanvasElement): void;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, video: HTMLVideoElement): void;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageData): void;
            copyTexImage2D(target: number, level: number, internalformat: number, x: number, y: number, width: number, height: number, border: number): void;
            getVertexAttribOffset(index: number, pname: number): number;
            disableVertexAttribArray(index: number): void;
            blendFunc(sfactor: number, dfactor: number): void;
            drawElements(mode: number, count: number, type: number, offset: number): void;
            isFramebuffer(framebuffer: WebGLFramebuffer): boolean;
            uniform3iv(location: WebGLUniformLocation, v: number[]): void;
            uniform3iv(location: WebGLUniformLocation, v: Int32Array): void;
            lineWidth(width: number): void;
            getShaderInfoLog(shader: WebGLShader): string;
            getTexParameter(target: number, pname: number): any;
            getParameter(pname: number): any;
            getShaderPrecisionFormat(shadertype: number, precisiontype: number): WebGLShaderPrecisionFormat;
            getContextAttributes(): WebGLContextAttributes;
            vertexAttrib1f(indx: number, x: number): void;
            bindFramebuffer(target: number, framebuffer: WebGLFramebuffer): void;
            compressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, data: ArrayBufferView): void;
            isContextLost(): boolean;
            uniform1iv(location: WebGLUniformLocation, v: number[]): void;
            uniform1iv(location: WebGLUniformLocation, v: Int32Array): void;
            getRenderbufferParameter(target: number, pname: number): any;
            uniform2fv(location: WebGLUniformLocation, v: number[]): void;
            uniform2fv(location: WebGLUniformLocation, v: Float32Array): void;
            isTexture(texture: WebGLTexture): boolean;
            getError(): number;
            shaderSource(shader: WebGLShader, source: string): void;
            deleteRenderbuffer(renderbuffer: WebGLRenderbuffer): void;
            stencilMask(mask: number): void;
            bindBuffer(target: number, buffer: WebGLBuffer): void;
            getAttribLocation(program: WebGLProgram, name: string): number;
            uniform3i(location: WebGLUniformLocation, x: number, y: number, z: number): void;
            blendEquationSeparate(modeRGB: number, modeAlpha: number): void;
            clear(mask: number): void;
            blendFuncSeparate(srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number): void;
            stencilFuncSeparate(face: number, func: number, ref: number, mask: number): void;
            readPixels(x: number, y: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView): void;
            scissor(x: number, y: number, width: number, height: number): void;
            uniform2i(location: WebGLUniformLocation, x: number, y: number): void;
            getActiveAttrib(program: WebGLProgram, index: number): WebGLActiveInfo;
            getShaderSource(shader: WebGLShader): string;
            generateMipmap(target: number): void;
            bindAttribLocation(program: WebGLProgram, index: number, name: string): void;
            uniform1fv(location: WebGLUniformLocation, v: number[]): void;
            uniform1fv(location: WebGLUniformLocation, v: Float32Array): void;
            uniform2iv(location: WebGLUniformLocation, v: number[]): void;
            uniform2iv(location: WebGLUniformLocation, v: Int32Array): void;
            stencilOp(fail: number, zfail: number, zpass: number): void;
            uniform4fv(location: WebGLUniformLocation, v: number[]): void;
            uniform4fv(location: WebGLUniformLocation, v: Float32Array): void;
            vertexAttrib1fv(indx: number, values: number[]): void;
            vertexAttrib1fv(indx: number, values: Float32Array): void;
            flush(): void;
            uniform4f(location: WebGLUniformLocation, x: number, y: number, z: number, w: number): void;
            deleteProgram(program: WebGLProgram): void;
            isRenderbuffer(renderbuffer: WebGLRenderbuffer): boolean;
            uniform1i(location: WebGLUniformLocation, x: number): void;
            getProgramParameter(program: WebGLProgram, pname: number): any;
            getActiveUniform(program: WebGLProgram, index: number): WebGLActiveInfo;
            stencilFunc(func: number, ref: number, mask: number): void;
            pixelStorei(pname: number, param: number): void;
            disable(cap: number): void;
            vertexAttrib4fv(indx: number, values: number[]): void;
            vertexAttrib4fv(indx: number, values: Float32Array): void;
            createRenderbuffer(): WebGLRenderbuffer;
            isBuffer(buffer: WebGLBuffer): boolean;
            stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void;
            getFramebufferAttachmentParameter(target: number, attachment: number, pname: number): any;
            uniform4i(location: WebGLUniformLocation, x: number, y: number, z: number, w: number): void;
            sampleCoverage(value: number, invert: boolean): void;
            depthFunc(func: number): void;
            texParameterf(target: number, pname: number, param: number): void;
            vertexAttrib3f(indx: number, x: number, y: number, z: number): void;
            drawArrays(mode: number, first: number, count: number): void;
            texParameteri(target: number, pname: number, param: number): void;
            vertexAttrib4f(indx: number, x: number, y: number, z: number, w: number): void;
            getShaderParameter(shader: WebGLShader, pname: number): any;
            clearDepth(depth: number): void;
            activeTexture(texture: number): void;
            viewport(x: number, y: number, width: number, height: number): void;
            detachShader(program: WebGLProgram, shader: WebGLShader): void;
            uniform1f(location: WebGLUniformLocation, x: number): void;
            uniformMatrix3fv(location: WebGLUniformLocation, transpose: boolean, value: number[]): void;
            uniformMatrix3fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array): void;
            deleteBuffer(buffer: WebGLBuffer): void;
            copyTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, x: number, y: number, width: number, height: number): void;
            uniform3fv(location: WebGLUniformLocation, v: number[]): void;
            uniform3fv(location: WebGLUniformLocation, v: Float32Array): void;
            stencilMaskSeparate(face: number, mask: number): void;
            attachShader(program: WebGLProgram, shader: WebGLShader): void;
            compileShader(shader: WebGLShader): void;
            clearColor(red: number, green: number, blue: number, alpha: number): void;
            isShader(shader: WebGLShader): boolean;
            clearStencil(s: number): void;
            framebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: WebGLRenderbuffer): void;
            finish(): void;
            uniform2f(location: WebGLUniformLocation, x: number, y: number): void;
            renderbufferStorage(target: number, internalformat: number, width: number, height: number): void;
            uniform3f(location: WebGLUniformLocation, x: number, y: number, z: number): void;
            getProgramInfoLog(program: WebGLProgram): string;
            validateProgram(program: WebGLProgram): void;
            isEnabled(cap: number): boolean;
            vertexAttrib2f(indx: number, x: number, y: number): void;
            isProgram(program: WebGLProgram): boolean;
            createShader(type: number): WebGLShader;
            bindRenderbuffer(target: number, renderbuffer: WebGLRenderbuffer): void;
            uniform4iv(location: WebGLUniformLocation, v: number[]): void;
            uniform4iv(location: WebGLUniformLocation, v: Int32Array): void;
            DEPTH_FUNC: number;
            DEPTH_COMPONENT16: number;
            REPLACE: number;
            REPEAT: number;
            VERTEX_ATTRIB_ARRAY_ENABLED: number;
            FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;
            STENCIL_BUFFER_BIT: number;
            RENDERER: number;
            STENCIL_BACK_REF: number;
            TEXTURE26: number;
            RGB565: number;
            DITHER: number;
            CONSTANT_COLOR: number;
            GENERATE_MIPMAP_HINT: number;
            POINTS: number;
            DECR: number;
            INT_VEC3: number;
            TEXTURE28: number;
            ONE_MINUS_CONSTANT_ALPHA: number;
            BACK: number;
            RENDERBUFFER_STENCIL_SIZE: number;
            UNPACK_FLIP_Y_WEBGL: number;
            BLEND: number;
            TEXTURE9: number;
            ARRAY_BUFFER_BINDING: number;
            MAX_VIEWPORT_DIMS: number;
            INVALID_FRAMEBUFFER_OPERATION: number;
            TEXTURE: number;
            TEXTURE0: number;
            TEXTURE31: number;
            TEXTURE24: number;
            HIGH_INT: number;
            RENDERBUFFER_BINDING: number;
            BLEND_COLOR: number;
            FASTEST: number;
            STENCIL_WRITEMASK: number;
            ALIASED_POINT_SIZE_RANGE: number;
            TEXTURE12: number;
            DST_ALPHA: number;
            BLEND_EQUATION_RGB: number;
            FRAMEBUFFER_COMPLETE: number;
            NEAREST_MIPMAP_NEAREST: number;
            VERTEX_ATTRIB_ARRAY_SIZE: number;
            TEXTURE3: number;
            DEPTH_WRITEMASK: number;
            CONTEXT_LOST_WEBGL: number;
            INVALID_VALUE: number;
            TEXTURE_MAG_FILTER: number;
            ONE_MINUS_CONSTANT_COLOR: number;
            ONE_MINUS_SRC_ALPHA: number;
            TEXTURE_CUBE_MAP_POSITIVE_Z: number;
            NOTEQUAL: number;
            ALPHA: number;
            DEPTH_STENCIL: number;
            MAX_VERTEX_UNIFORM_VECTORS: number;
            DEPTH_COMPONENT: number;
            RENDERBUFFER_RED_SIZE: number;
            TEXTURE20: number;
            RED_BITS: number;
            RENDERBUFFER_BLUE_SIZE: number;
            SCISSOR_BOX: number;
            VENDOR: number;
            FRONT_AND_BACK: number;
            CONSTANT_ALPHA: number;
            VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;
            NEAREST: number;
            CULL_FACE: number;
            ALIASED_LINE_WIDTH_RANGE: number;
            TEXTURE19: number;
            FRONT: number;
            DEPTH_CLEAR_VALUE: number;
            GREEN_BITS: number;
            TEXTURE29: number;
            TEXTURE23: number;
            MAX_RENDERBUFFER_SIZE: number;
            STENCIL_ATTACHMENT: number;
            TEXTURE27: number;
            BOOL_VEC2: number;
            OUT_OF_MEMORY: number;
            MIRRORED_REPEAT: number;
            POLYGON_OFFSET_UNITS: number;
            TEXTURE_MIN_FILTER: number;
            STENCIL_BACK_PASS_DEPTH_PASS: number;
            LINE_LOOP: number;
            FLOAT_MAT3: number;
            TEXTURE14: number;
            LINEAR: number;
            RGB5_A1: number;
            ONE_MINUS_SRC_COLOR: number;
            SAMPLE_COVERAGE_INVERT: number;
            DONT_CARE: number;
            FRAMEBUFFER_BINDING: number;
            RENDERBUFFER_ALPHA_SIZE: number;
            STENCIL_REF: number;
            ZERO: number;
            DECR_WRAP: number;
            SAMPLE_COVERAGE: number;
            STENCIL_BACK_FUNC: number;
            TEXTURE30: number;
            VIEWPORT: number;
            STENCIL_BITS: number;
            FLOAT: number;
            COLOR_WRITEMASK: number;
            SAMPLE_COVERAGE_VALUE: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Y: number;
            STENCIL_BACK_FAIL: number;
            FLOAT_MAT4: number;
            UNSIGNED_SHORT_4_4_4_4: number;
            TEXTURE6: number;
            RENDERBUFFER_WIDTH: number;
            RGBA4: number;
            ALWAYS: number;
            BLEND_EQUATION_ALPHA: number;
            COLOR_BUFFER_BIT: number;
            TEXTURE_CUBE_MAP: number;
            DEPTH_BUFFER_BIT: number;
            STENCIL_CLEAR_VALUE: number;
            BLEND_EQUATION: number;
            RENDERBUFFER_GREEN_SIZE: number;
            NEAREST_MIPMAP_LINEAR: number;
            VERTEX_ATTRIB_ARRAY_TYPE: number;
            INCR_WRAP: number;
            ONE_MINUS_DST_COLOR: number;
            HIGH_FLOAT: number;
            BYTE: number;
            FRONT_FACE: number;
            SAMPLE_ALPHA_TO_COVERAGE: number;
            CCW: number;
            TEXTURE13: number;
            MAX_VERTEX_ATTRIBS: number;
            MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;
            TEXTURE_WRAP_T: number;
            UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;
            FLOAT_VEC2: number;
            LUMINANCE: number;
            GREATER: number;
            INT_VEC2: number;
            VALIDATE_STATUS: number;
            FRAMEBUFFER: number;
            FRAMEBUFFER_UNSUPPORTED: number;
            TEXTURE5: number;
            FUNC_SUBTRACT: number;
            BLEND_DST_ALPHA: number;
            SAMPLER_CUBE: number;
            ONE_MINUS_DST_ALPHA: number;
            LESS: number;
            TEXTURE_CUBE_MAP_POSITIVE_X: number;
            BLUE_BITS: number;
            DEPTH_TEST: number;
            VERTEX_ATTRIB_ARRAY_STRIDE: number;
            DELETE_STATUS: number;
            TEXTURE18: number;
            POLYGON_OFFSET_FACTOR: number;
            UNSIGNED_INT: number;
            TEXTURE_2D: number;
            DST_COLOR: number;
            FLOAT_MAT2: number;
            COMPRESSED_TEXTURE_FORMATS: number;
            MAX_FRAGMENT_UNIFORM_VECTORS: number;
            DEPTH_STENCIL_ATTACHMENT: number;
            LUMINANCE_ALPHA: number;
            CW: number;
            VERTEX_ATTRIB_ARRAY_NORMALIZED: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Z: number;
            LINEAR_MIPMAP_LINEAR: number;
            BUFFER_SIZE: number;
            SAMPLE_BUFFERS: number;
            TEXTURE15: number;
            ACTIVE_TEXTURE: number;
            VERTEX_SHADER: number;
            TEXTURE22: number;
            VERTEX_ATTRIB_ARRAY_POINTER: number;
            INCR: number;
            COMPILE_STATUS: number;
            MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;
            TEXTURE7: number;
            UNSIGNED_SHORT_5_5_5_1: number;
            DEPTH_BITS: number;
            RGBA: number;
            TRIANGLE_STRIP: number;
            COLOR_CLEAR_VALUE: number;
            BROWSER_DEFAULT_WEBGL: number;
            INVALID_ENUM: number;
            SCISSOR_TEST: number;
            LINE_STRIP: number;
            FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;
            STENCIL_FUNC: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;
            RENDERBUFFER_HEIGHT: number;
            TEXTURE8: number;
            TRIANGLES: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;
            STENCIL_BACK_VALUE_MASK: number;
            TEXTURE25: number;
            RENDERBUFFER: number;
            LEQUAL: number;
            TEXTURE1: number;
            STENCIL_INDEX8: number;
            FUNC_ADD: number;
            STENCIL_FAIL: number;
            BLEND_SRC_ALPHA: number;
            BOOL: number;
            ALPHA_BITS: number;
            LOW_INT: number;
            TEXTURE10: number;
            SRC_COLOR: number;
            MAX_VARYING_VECTORS: number;
            BLEND_DST_RGB: number;
            TEXTURE_BINDING_CUBE_MAP: number;
            STENCIL_INDEX: number;
            TEXTURE_BINDING_2D: number;
            MEDIUM_INT: number;
            SHADER_TYPE: number;
            POLYGON_OFFSET_FILL: number;
            DYNAMIC_DRAW: number;
            TEXTURE4: number;
            STENCIL_BACK_PASS_DEPTH_FAIL: number;
            STREAM_DRAW: number;
            MAX_CUBE_MAP_TEXTURE_SIZE: number;
            TEXTURE17: number;
            TRIANGLE_FAN: number;
            UNPACK_ALIGNMENT: number;
            CURRENT_PROGRAM: number;
            LINES: number;
            INVALID_OPERATION: number;
            FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;
            LINEAR_MIPMAP_NEAREST: number;
            CLAMP_TO_EDGE: number;
            RENDERBUFFER_DEPTH_SIZE: number;
            TEXTURE_WRAP_S: number;
            ELEMENT_ARRAY_BUFFER: number;
            UNSIGNED_SHORT_5_6_5: number;
            ACTIVE_UNIFORMS: number;
            FLOAT_VEC3: number;
            NO_ERROR: number;
            ATTACHED_SHADERS: number;
            DEPTH_ATTACHMENT: number;
            TEXTURE11: number;
            STENCIL_TEST: number;
            ONE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;
            STATIC_DRAW: number;
            GEQUAL: number;
            BOOL_VEC4: number;
            COLOR_ATTACHMENT0: number;
            PACK_ALIGNMENT: number;
            MAX_TEXTURE_SIZE: number;
            STENCIL_PASS_DEPTH_FAIL: number;
            CULL_FACE_MODE: number;
            TEXTURE16: number;
            STENCIL_BACK_WRITEMASK: number;
            SRC_ALPHA: number;
            UNSIGNED_SHORT: number;
            TEXTURE21: number;
            FUNC_REVERSE_SUBTRACT: number;
            SHADING_LANGUAGE_VERSION: number;
            EQUAL: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;
            BOOL_VEC3: number;
            SAMPLER_2D: number;
            TEXTURE_CUBE_MAP_NEGATIVE_X: number;
            MAX_TEXTURE_IMAGE_UNITS: number;
            TEXTURE_CUBE_MAP_POSITIVE_Y: number;
            RENDERBUFFER_INTERNAL_FORMAT: number;
            STENCIL_VALUE_MASK: number;
            ELEMENT_ARRAY_BUFFER_BINDING: number;
            ARRAY_BUFFER: number;
            DEPTH_RANGE: number;
            NICEST: number;
            ACTIVE_ATTRIBUTES: number;
            NEVER: number;
            FLOAT_VEC4: number;
            CURRENT_VERTEX_ATTRIB: number;
            STENCIL_PASS_DEPTH_PASS: number;
            INVERT: number;
            LINK_STATUS: number;
            RGB: number;
            INT_VEC4: number;
            TEXTURE2: number;
            UNPACK_COLORSPACE_CONVERSION_WEBGL: number;
            MEDIUM_FLOAT: number;
            SRC_ALPHA_SATURATE: number;
            BUFFER_USAGE: number;
            SHORT: number;
            NONE: number;
            UNSIGNED_BYTE: number;
            INT: number;
            SUBPIXEL_BITS: number;
            KEEP: number;
            SAMPLES: number;
            FRAGMENT_SHADER: number;
            LINE_WIDTH: number;
            BLEND_SRC_RGB: number;
            LOW_FLOAT: number;
            VERSION: number;
        }
        declare var WebGLRenderingContext: {
            prototype: WebGLRenderingContext;
            new(): WebGLRenderingContext;
            DEPTH_FUNC: number;
            DEPTH_COMPONENT16: number;
            REPLACE: number;
            REPEAT: number;
            VERTEX_ATTRIB_ARRAY_ENABLED: number;
            FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;
            STENCIL_BUFFER_BIT: number;
            RENDERER: number;
            STENCIL_BACK_REF: number;
            TEXTURE26: number;
            RGB565: number;
            DITHER: number;
            CONSTANT_COLOR: number;
            GENERATE_MIPMAP_HINT: number;
            POINTS: number;
            DECR: number;
            INT_VEC3: number;
            TEXTURE28: number;
            ONE_MINUS_CONSTANT_ALPHA: number;
            BACK: number;
            RENDERBUFFER_STENCIL_SIZE: number;
            UNPACK_FLIP_Y_WEBGL: number;
            BLEND: number;
            TEXTURE9: number;
            ARRAY_BUFFER_BINDING: number;
            MAX_VIEWPORT_DIMS: number;
            INVALID_FRAMEBUFFER_OPERATION: number;
            TEXTURE: number;
            TEXTURE0: number;
            TEXTURE31: number;
            TEXTURE24: number;
            HIGH_INT: number;
            RENDERBUFFER_BINDING: number;
            BLEND_COLOR: number;
            FASTEST: number;
            STENCIL_WRITEMASK: number;
            ALIASED_POINT_SIZE_RANGE: number;
            TEXTURE12: number;
            DST_ALPHA: number;
            BLEND_EQUATION_RGB: number;
            FRAMEBUFFER_COMPLETE: number;
            NEAREST_MIPMAP_NEAREST: number;
            VERTEX_ATTRIB_ARRAY_SIZE: number;
            TEXTURE3: number;
            DEPTH_WRITEMASK: number;
            CONTEXT_LOST_WEBGL: number;
            INVALID_VALUE: number;
            TEXTURE_MAG_FILTER: number;
            ONE_MINUS_CONSTANT_COLOR: number;
            ONE_MINUS_SRC_ALPHA: number;
            TEXTURE_CUBE_MAP_POSITIVE_Z: number;
            NOTEQUAL: number;
            ALPHA: number;
            DEPTH_STENCIL: number;
            MAX_VERTEX_UNIFORM_VECTORS: number;
            DEPTH_COMPONENT: number;
            RENDERBUFFER_RED_SIZE: number;
            TEXTURE20: number;
            RED_BITS: number;
            RENDERBUFFER_BLUE_SIZE: number;
            SCISSOR_BOX: number;
            VENDOR: number;
            FRONT_AND_BACK: number;
            CONSTANT_ALPHA: number;
            VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;
            NEAREST: number;
            CULL_FACE: number;
            ALIASED_LINE_WIDTH_RANGE: number;
            TEXTURE19: number;
            FRONT: number;
            DEPTH_CLEAR_VALUE: number;
            GREEN_BITS: number;
            TEXTURE29: number;
            TEXTURE23: number;
            MAX_RENDERBUFFER_SIZE: number;
            STENCIL_ATTACHMENT: number;
            TEXTURE27: number;
            BOOL_VEC2: number;
            OUT_OF_MEMORY: number;
            MIRRORED_REPEAT: number;
            POLYGON_OFFSET_UNITS: number;
            TEXTURE_MIN_FILTER: number;
            STENCIL_BACK_PASS_DEPTH_PASS: number;
            LINE_LOOP: number;
            FLOAT_MAT3: number;
            TEXTURE14: number;
            LINEAR: number;
            RGB5_A1: number;
            ONE_MINUS_SRC_COLOR: number;
            SAMPLE_COVERAGE_INVERT: number;
            DONT_CARE: number;
            FRAMEBUFFER_BINDING: number;
            RENDERBUFFER_ALPHA_SIZE: number;
            STENCIL_REF: number;
            ZERO: number;
            DECR_WRAP: number;
            SAMPLE_COVERAGE: number;
            STENCIL_BACK_FUNC: number;
            TEXTURE30: number;
            VIEWPORT: number;
            STENCIL_BITS: number;
            FLOAT: number;
            COLOR_WRITEMASK: number;
            SAMPLE_COVERAGE_VALUE: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Y: number;
            STENCIL_BACK_FAIL: number;
            FLOAT_MAT4: number;
            UNSIGNED_SHORT_4_4_4_4: number;
            TEXTURE6: number;
            RENDERBUFFER_WIDTH: number;
            RGBA4: number;
            ALWAYS: number;
            BLEND_EQUATION_ALPHA: number;
            COLOR_BUFFER_BIT: number;
            TEXTURE_CUBE_MAP: number;
            DEPTH_BUFFER_BIT: number;
            STENCIL_CLEAR_VALUE: number;
            BLEND_EQUATION: number;
            RENDERBUFFER_GREEN_SIZE: number;
            NEAREST_MIPMAP_LINEAR: number;
            VERTEX_ATTRIB_ARRAY_TYPE: number;
            INCR_WRAP: number;
            ONE_MINUS_DST_COLOR: number;
            HIGH_FLOAT: number;
            BYTE: number;
            FRONT_FACE: number;
            SAMPLE_ALPHA_TO_COVERAGE: number;
            CCW: number;
            TEXTURE13: number;
            MAX_VERTEX_ATTRIBS: number;
            MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;
            TEXTURE_WRAP_T: number;
            UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;
            FLOAT_VEC2: number;
            LUMINANCE: number;
            GREATER: number;
            INT_VEC2: number;
            VALIDATE_STATUS: number;
            FRAMEBUFFER: number;
            FRAMEBUFFER_UNSUPPORTED: number;
            TEXTURE5: number;
            FUNC_SUBTRACT: number;
            BLEND_DST_ALPHA: number;
            SAMPLER_CUBE: number;
            ONE_MINUS_DST_ALPHA: number;
            LESS: number;
            TEXTURE_CUBE_MAP_POSITIVE_X: number;
            BLUE_BITS: number;
            DEPTH_TEST: number;
            VERTEX_ATTRIB_ARRAY_STRIDE: number;
            DELETE_STATUS: number;
            TEXTURE18: number;
            POLYGON_OFFSET_FACTOR: number;
            UNSIGNED_INT: number;
            TEXTURE_2D: number;
            DST_COLOR: number;
            FLOAT_MAT2: number;
            COMPRESSED_TEXTURE_FORMATS: number;
            MAX_FRAGMENT_UNIFORM_VECTORS: number;
            DEPTH_STENCIL_ATTACHMENT: number;
            LUMINANCE_ALPHA: number;
            CW: number;
            VERTEX_ATTRIB_ARRAY_NORMALIZED: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Z: number;
            LINEAR_MIPMAP_LINEAR: number;
            BUFFER_SIZE: number;
            SAMPLE_BUFFERS: number;
            TEXTURE15: number;
            ACTIVE_TEXTURE: number;
            VERTEX_SHADER: number;
            TEXTURE22: number;
            VERTEX_ATTRIB_ARRAY_POINTER: number;
            INCR: number;
            COMPILE_STATUS: number;
            MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;
            TEXTURE7: number;
            UNSIGNED_SHORT_5_5_5_1: number;
            DEPTH_BITS: number;
            RGBA: number;
            TRIANGLE_STRIP: number;
            COLOR_CLEAR_VALUE: number;
            BROWSER_DEFAULT_WEBGL: number;
            INVALID_ENUM: number;
            SCISSOR_TEST: number;
            LINE_STRIP: number;
            FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;
            STENCIL_FUNC: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;
            RENDERBUFFER_HEIGHT: number;
            TEXTURE8: number;
            TRIANGLES: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;
            STENCIL_BACK_VALUE_MASK: number;
            TEXTURE25: number;
            RENDERBUFFER: number;
            LEQUAL: number;
            TEXTURE1: number;
            STENCIL_INDEX8: number;
            FUNC_ADD: number;
            STENCIL_FAIL: number;
            BLEND_SRC_ALPHA: number;
            BOOL: number;
            ALPHA_BITS: number;
            LOW_INT: number;
            TEXTURE10: number;
            SRC_COLOR: number;
            MAX_VARYING_VECTORS: number;
            BLEND_DST_RGB: number;
            TEXTURE_BINDING_CUBE_MAP: number;
            STENCIL_INDEX: number;
            TEXTURE_BINDING_2D: number;
            MEDIUM_INT: number;
            SHADER_TYPE: number;
            POLYGON_OFFSET_FILL: number;
            DYNAMIC_DRAW: number;
            TEXTURE4: number;
            STENCIL_BACK_PASS_DEPTH_FAIL: number;
            STREAM_DRAW: number;
            MAX_CUBE_MAP_TEXTURE_SIZE: number;
            TEXTURE17: number;
            TRIANGLE_FAN: number;
            UNPACK_ALIGNMENT: number;
            CURRENT_PROGRAM: number;
            LINES: number;
            INVALID_OPERATION: number;
            FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;
            LINEAR_MIPMAP_NEAREST: number;
            CLAMP_TO_EDGE: number;
            RENDERBUFFER_DEPTH_SIZE: number;
            TEXTURE_WRAP_S: number;
            ELEMENT_ARRAY_BUFFER: number;
            UNSIGNED_SHORT_5_6_5: number;
            ACTIVE_UNIFORMS: number;
            FLOAT_VEC3: number;
            NO_ERROR: number;
            ATTACHED_SHADERS: number;
            DEPTH_ATTACHMENT: number;
            TEXTURE11: number;
            STENCIL_TEST: number;
            ONE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;
            STATIC_DRAW: number;
            GEQUAL: number;
            BOOL_VEC4: number;
            COLOR_ATTACHMENT0: number;
            PACK_ALIGNMENT: number;
            MAX_TEXTURE_SIZE: number;
            STENCIL_PASS_DEPTH_FAIL: number;
            CULL_FACE_MODE: number;
            TEXTURE16: number;
            STENCIL_BACK_WRITEMASK: number;
            SRC_ALPHA: number;
            UNSIGNED_SHORT: number;
            TEXTURE21: number;
            FUNC_REVERSE_SUBTRACT: number;
            SHADING_LANGUAGE_VERSION: number;
            EQUAL: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;
            BOOL_VEC3: number;
            SAMPLER_2D: number;
            TEXTURE_CUBE_MAP_NEGATIVE_X: number;
            MAX_TEXTURE_IMAGE_UNITS: number;
            TEXTURE_CUBE_MAP_POSITIVE_Y: number;
            RENDERBUFFER_INTERNAL_FORMAT: number;
            STENCIL_VALUE_MASK: number;
            ELEMENT_ARRAY_BUFFER_BINDING: number;
            ARRAY_BUFFER: number;
            DEPTH_RANGE: number;
            NICEST: number;
            ACTIVE_ATTRIBUTES: number;
            NEVER: number;
            FLOAT_VEC4: number;
            CURRENT_VERTEX_ATTRIB: number;
            STENCIL_PASS_DEPTH_PASS: number;
            INVERT: number;
            LINK_STATUS: number;
            RGB: number;
            INT_VEC4: number;
            TEXTURE2: number;
            UNPACK_COLORSPACE_CONVERSION_WEBGL: number;
            MEDIUM_FLOAT: number;
            SRC_ALPHA_SATURATE: number;
            BUFFER_USAGE: number;
            SHORT: number;
            NONE: number;
            UNSIGNED_BYTE: number;
            INT: number;
            SUBPIXEL_BITS: number;
            KEEP: number;
            SAMPLES: number;
            FRAGMENT_SHADER: number;
            LINE_WIDTH: number;
            BLEND_SRC_RGB: number;
            LOW_FLOAT: number;
            VERSION: number;
        }
        
        interface WebGLProgram extends WebGLObject {
        }
        declare var WebGLProgram: {
            prototype: WebGLProgram;
            new(): WebGLProgram;
        }
        
        interface OES_standard_derivatives {
            FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;
        }
        declare var OES_standard_derivatives: {
            prototype: OES_standard_derivatives;
            new(): OES_standard_derivatives;
            FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;
        }
        
        interface WebGLFramebuffer extends WebGLObject {
        }
        declare var WebGLFramebuffer: {
            prototype: WebGLFramebuffer;
            new(): WebGLFramebuffer;
        }
        
        interface WebGLShader extends WebGLObject {
        }
        declare var WebGLShader: {
            prototype: WebGLShader;
            new(): WebGLShader;
        }
        
        interface OES_texture_float_linear {
        }
        declare var OES_texture_float_linear: {
            prototype: OES_texture_float_linear;
            new(): OES_texture_float_linear;
        }
        
        interface WebGLObject {
        }
        declare var WebGLObject: {
            prototype: WebGLObject;
            new(): WebGLObject;
        }
        
        interface WebGLBuffer extends WebGLObject {
        }
        declare var WebGLBuffer: {
            prototype: WebGLBuffer;
            new(): WebGLBuffer;
        }
        
        interface WebGLShaderPrecisionFormat {
            rangeMin: number;
            rangeMax: number;
            precision: number;
        }
        declare var WebGLShaderPrecisionFormat: {
            prototype: WebGLShaderPrecisionFormat;
            new(): WebGLShaderPrecisionFormat;
        }
        
        interface EXT_texture_filter_anisotropic {
            TEXTURE_MAX_ANISOTROPY_EXT: number;
            MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;
        }
        declare var EXT_texture_filter_anisotropic: {
            prototype: EXT_texture_filter_anisotropic;
            new(): EXT_texture_filter_anisotropic;
            TEXTURE_MAX_ANISOTROPY_EXT: number;
            MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;
        }
        
        declare var Option: { new(text?: string, value?: string, defaultSelected?: boolean, selected?:boolean): HTMLOptionElement; };
        declare var Image: { new(width?: number, height?: number): HTMLImageElement; };
        declare var Audio: { new(src?: string): HTMLAudioElement; };
        
        declare var ondragend: (ev: DragEvent) => any;
        declare var onkeydown: (ev: KeyboardEvent) => any;
        declare var ondragover: (ev: DragEvent) => any;
        declare var onkeyup: (ev: KeyboardEvent) => any;
        declare var onreset: (ev: Event) => any;
        declare var onmouseup: (ev: MouseEvent) => any;
        declare var ondragstart: (ev: DragEvent) => any;
        declare var ondrag: (ev: DragEvent) => any;
        declare var screenX: number;
        declare var onmouseover: (ev: MouseEvent) => any;
        declare var ondragleave: (ev: DragEvent) => any;
        declare var history: History;
        declare var pageXOffset: number;
        declare var name: string;
        declare var onafterprint: (ev: Event) => any;
        declare var onpause: (ev: Event) => any;
        declare var onbeforeprint: (ev: Event) => any;
        declare var top: Window;
        declare var onmousedown: (ev: MouseEvent) => any;
        declare var onseeked: (ev: Event) => any;
        declare var opener: Window;
        declare var onclick: (ev: MouseEvent) => any;
        declare var innerHeight: number;
        declare var onwaiting: (ev: Event) => any;
        declare var ononline: (ev: Event) => any;
        declare var ondurationchange: (ev: Event) => any;
        declare var frames: Window;
        declare var onblur: (ev: FocusEvent) => any;
        declare var onemptied: (ev: Event) => any;
        declare var onseeking: (ev: Event) => any;
        declare var oncanplay: (ev: Event) => any;
        declare var outerWidth: number;
        declare var onstalled: (ev: Event) => any;
        declare var onmousemove: (ev: MouseEvent) => any;
        declare var innerWidth: number;
        declare var onoffline: (ev: Event) => any;
        declare var length: number;
        declare var screen: Screen;
        declare var onbeforeunload: (ev: BeforeUnloadEvent) => any;
        declare var onratechange: (ev: Event) => any;
        declare var onstorage: (ev: StorageEvent) => any;
        declare var onloadstart: (ev: Event) => any;
        declare var ondragenter: (ev: DragEvent) => any;
        declare var onsubmit: (ev: Event) => any;
        declare var self: Window;
        declare var document: Document;
        declare var onprogress: (ev: ProgressEvent) => any;
        declare var ondblclick: (ev: MouseEvent) => any;
        declare var pageYOffset: number;
        declare var oncontextmenu: (ev: MouseEvent) => any;
        declare var onchange: (ev: Event) => any;
        declare var onloadedmetadata: (ev: Event) => any;
        declare var onplay: (ev: Event) => any;
        declare var onerror: ErrorEventHandler;
        declare var onplaying: (ev: Event) => any;
        declare var parent: Window;
        declare var location: Location;
        declare var oncanplaythrough: (ev: Event) => any;
        declare var onabort: (ev: UIEvent) => any;
        declare var onreadystatechange: (ev: Event) => any;
        declare var outerHeight: number;
        declare var onkeypress: (ev: KeyboardEvent) => any;
        declare var frameElement: Element;
        declare var onloadeddata: (ev: Event) => any;
        declare var onsuspend: (ev: Event) => any;
        declare var window: Window;
        declare var onfocus: (ev: FocusEvent) => any;
        declare var onmessage: (ev: MessageEvent) => any;
        declare var ontimeupdate: (ev: Event) => any;
        declare var onresize: (ev: UIEvent) => any;
        declare var onselect: (ev: UIEvent) => any;
        declare var navigator: Navigator;
        declare var styleMedia: StyleMedia;
        declare var ondrop: (ev: DragEvent) => any;
        declare var onmouseout: (ev: MouseEvent) => any;
        declare var onended: (ev: Event) => any;
        declare var onhashchange: (ev: Event) => any;
        declare var onunload: (ev: Event) => any;
        declare var onscroll: (ev: UIEvent) => any;
        declare var screenY: number;
        declare var onmousewheel: (ev: MouseWheelEvent) => any;
        declare var onload: (ev: Event) => any;
        declare var onvolumechange: (ev: Event) => any;
        declare var oninput: (ev: Event) => any;
        declare var performance: Performance;
        declare var onmspointerdown: (ev: any) => any;
        declare var animationStartTime: number;
        declare var onmsgesturedoubletap: (ev: any) => any;
        declare var onmspointerhover: (ev: any) => any;
        declare var onmsgesturehold: (ev: any) => any;
        declare var onmspointermove: (ev: any) => any;
        declare var onmsgesturechange: (ev: any) => any;
        declare var onmsgesturestart: (ev: any) => any;
        declare var onmspointercancel: (ev: any) => any;
        declare var onmsgestureend: (ev: any) => any;
        declare var onmsgesturetap: (ev: any) => any;
        declare var onmspointerout: (ev: any) => any;
        declare var msAnimationStartTime: number;
        declare var applicationCache: ApplicationCache;
        declare var onmsinertiastart: (ev: any) => any;
        declare var onmspointerover: (ev: any) => any;
        declare var onpopstate: (ev: PopStateEvent) => any;
        declare var onmspointerup: (ev: any) => any;
        declare var onpageshow: (ev: PageTransitionEvent) => any;
        declare var ondevicemotion: (ev: DeviceMotionEvent) => any;
        declare var devicePixelRatio: number;
        declare var msCrypto: Crypto;
        declare var ondeviceorientation: (ev: DeviceOrientationEvent) => any;
        declare var doNotTrack: string;
        declare var onmspointerenter: (ev: any) => any;
        declare var onpagehide: (ev: PageTransitionEvent) => any;
        declare var onmspointerleave: (ev: any) => any;
        declare function alert(message?: any): void;
        declare function scroll(x?: number, y?: number): void;
        declare function focus(): void;
        declare function scrollTo(x?: number, y?: number): void;
        declare function print(): void;
        declare function prompt(message?: string, _default?: string): string;
        declare function toString(): string;
        declare function open(url?: string, target?: string, features?: string, replace?: boolean): Window;
        declare function scrollBy(x?: number, y?: number): void;
        declare function confirm(message?: string): boolean;
        declare function close(): void;
        declare function postMessage(message: any, targetOrigin: string, ports?: any): void;
        declare function showModalDialog(url?: string, argument?: any, options?: any): any;
        declare function blur(): void;
        declare function getSelection(): Selection;
        declare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
        declare function msCancelRequestAnimationFrame(handle: number): void;
        declare function matchMedia(mediaQuery: string): MediaQueryList;
        declare function cancelAnimationFrame(handle: number): void;
        declare function msIsStaticHTML(html: string): boolean;
        declare function msMatchMedia(mediaQuery: string): MediaQueryList;
        declare function requestAnimationFrame(callback: FrameRequestCallback): number;
        declare function msRequestAnimationFrame(callback: FrameRequestCallback): number;
        declare function removeEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        declare function dispatchEvent(evt: Event): boolean;
        declare function attachEvent(event: string, listener: EventListener): boolean;
        declare function detachEvent(event: string, listener: EventListener): void;
        declare var localStorage: Storage;
        declare var status: string;
        declare var onmouseleave: (ev: MouseEvent) => any;
        declare var screenLeft: number;
        declare var offscreenBuffering: any;
        declare var maxConnectionsPerServer: number;
        declare var onmouseenter: (ev: MouseEvent) => any;
        declare var clipboardData: DataTransfer;
        declare var defaultStatus: string;
        declare var clientInformation: Navigator;
        declare var closed: boolean;
        declare var onhelp: (ev: Event) => any;
        declare var external: External;
        declare var event: MSEventObj;
        declare var onfocusout: (ev: FocusEvent) => any;
        declare var screenTop: number;
        declare var onfocusin: (ev: FocusEvent) => any;
        declare function showModelessDialog(url?: string, argument?: any, options?: any): Window;
        declare function navigate(url: string): void;
        declare function resizeBy(x?: number, y?: number): void;
        declare function item(index: any): any;
        declare function resizeTo(x?: number, y?: number): void;
        declare function createPopup(arguments?: any): MSPopupWindow;
        declare function toStaticHTML(html: string): string;
        declare function execScript(code: string, language?: string): any;
        declare function msWriteProfilerMark(profilerMarkName: string): void;
        declare function moveTo(x?: number, y?: number): void;
        declare function moveBy(x?: number, y?: number): void;
        declare function showHelp(url: string, helpArg?: any, features?: string): void;
        declare function captureEvents(): void;
        declare function releaseEvents(): void;
        declare var sessionStorage: Storage;
        declare function clearTimeout(handle: number): void;
        declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;
        declare function clearInterval(handle: number): void;
        declare function setInterval(handler: any, timeout?: any, ...args: any[]): number;
        declare function msSetImmediate(expression: any, ...args: any[]): number;
        declare function clearImmediate(handle: number): void;
        declare function msClearImmediate(handle: number): void;
        declare function setImmediate(expression: any, ...args: any[]): number;
        declare function btoa(rawString: string): string;
        declare function atob(encodedString: string): string;
        declare var msIndexedDB: IDBFactory;
        declare var indexedDB: IDBFactory;
        declare var console: Console;
        declare var onpointerenter: (ev: PointerEvent) => any;
        declare var onpointerout: (ev: PointerEvent) => any;
        declare var onpointerdown: (ev: PointerEvent) => any;
        declare var onpointerup: (ev: PointerEvent) => any;
        declare var onpointercancel: (ev: PointerEvent) => any;
        declare var onpointerover: (ev: PointerEvent) => any;
        declare var onpointermove: (ev: PointerEvent) => any;
        declare var onpointerleave: (ev: PointerEvent) => any;
        declare function addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "help", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "contextmenu", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "readystatechange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "hashchange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerdown", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgesturedoubletap", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerhover", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgesturehold", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointermove", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgesturechange", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgesturestart", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointercancel", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgestureend", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msgesturetap", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerout", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "msinertiastart", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerover", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerup", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerenter", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mspointerleave", listener: (ev: any) => any, useCapture?: boolean): void;
        declare function addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
        
      • extensions.d.ts.text
        /////////////////////////////
        /// IE10 ECMAScript Extensions
        /////////////////////////////
        
        /**
          * Represents a raw buffer of binary data, which is used to store data for the 
          * different typed arrays. ArrayBuffers cannot be read from or written to directly, 
          * but can be passed to a typed array or DataView Object to interpret the raw 
          * buffer as needed. 
          */
        interface ArrayBuffer {
            /**
              * Read-only. The length of the ArrayBuffer (in bytes).
              */
            byteLength: number;
        
            /**
              * Returns a section of an ArrayBuffer.
              */
            slice(begin:number, end?:number): ArrayBuffer;
        }
        
        declare var ArrayBuffer: {
            prototype: ArrayBuffer;
            new (byteLength: number): ArrayBuffer;
        }
        
        interface ArrayBufferView {
            buffer: ArrayBuffer;
            byteOffset: number;
            byteLength: number;
        }
        
        /**
          * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Int8Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int8Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int8Array;
        }
        declare var Int8Array: {
            prototype: Int8Array;
            new (length: number): Int8Array;
            new (array: Int8Array): Int8Array;
            new (array: number[]): Int8Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int8Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint8Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint8Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Uint8Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint8Array;
        }
        declare var Uint8Array: {
            prototype: Uint8Array;
            new (length: number): Uint8Array;
            new (array: Uint8Array): Uint8Array;
            new (array: number[]): Uint8Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 16-bit integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Int16Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int16Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Int16Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int16Array;
        }
        declare var Int16Array: {
            prototype: Int16Array;
            new (length: number): Int16Array;
            new (array: Int16Array): Int16Array;
            new (array: number[]): Int16Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int16Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint16Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint16Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Uint16Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray.
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint16Array;
        }
        declare var Uint16Array: {
            prototype: Uint16Array;
            new (length: number): Uint16Array;
            new (array: Uint16Array): Uint16Array;
            new (array: number[]): Uint16Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint16Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 32-bit integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Int32Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int32Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Int32Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int32Array;
        }
        declare var Int32Array: {
            prototype: Int32Array;
            new (length: number): Int32Array;
            new (array: Int32Array): Int32Array;
            new (array: number[]): Int32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int32Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint32Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint32Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Int8Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint32Array;
        }
        declare var Uint32Array: {
            prototype: Uint32Array;
            new (length: number): Uint32Array;
            new (array: Uint32Array): Uint32Array;
            new (array: number[]): Uint32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint32Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Float32Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Float32Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Float32Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Float32Array;
        }
        declare var Float32Array: {
            prototype: Float32Array;
            new (length: number): Float32Array;
            new (array: Float32Array): Float32Array;
            new (array: number[]): Float32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float32Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * A typed array of 64-bit float values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
          */
        interface Float64Array extends ArrayBufferView {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The length of the array.
              */
            length: number;
            [index: number]: number;
        
            /**
              * Gets the element at the specified index.
              * @param index The index at which to get the element of the array.
              */
            get(index: number): number;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Float64Array, offset?: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: number[], offset?: number): void;
        
            /**
              * Gets a new Float64Array view of the ArrayBuffer Object store for this array, specifying the first and last members of the subarray. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Float64Array;
        }
        declare var Float64Array: {
            prototype: Float64Array;
            new (length: number): Float64Array;
            new (array: Float64Array): Float64Array;
            new (array: number[]): Float64Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float64Array;
            BYTES_PER_ELEMENT: number;
        }
        
        /**
          * You can use a DataView object to read and write the different kinds of binary data to any location in the ArrayBuffer. 
          */
        interface DataView extends ArrayBufferView {
            /**
              * Gets the Int8 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getInt8(byteOffset: number): number;
        
            /**
              * Gets the Uint8 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getUint8(byteOffset: number): number;
        
            /**
              * Gets the Int16 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getInt16(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Gets the Uint16 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getUint16(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Gets the Int32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getInt32(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Gets the Uint32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getUint32(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Gets the Float32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getFloat32(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Gets the Float64 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. 
              * @param byteOffset The place in the buffer at which the value should be retrieved.
              */
            getFloat64(byteOffset: number, littleEndian?: boolean): number;
        
            /**
              * Stores an Int8 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              */
            setInt8(byteOffset: number, value: number): void;
        
            /**
              * Stores an Uint8 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              */
            setUint8(byteOffset: number, value: number): void;
        
            /**
              * Stores an Int16 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setInt16(byteOffset: number, value: number, littleEndian?: boolean): void;
        
            /**
              * Stores an Uint16 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setUint16(byteOffset: number, value: number, littleEndian?: boolean): void;
        
            /**
              * Stores an Int32 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setInt32(byteOffset: number, value: number, littleEndian?: boolean): void;
        
            /**
              * Stores an Uint32 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setUint32(byteOffset: number, value: number, littleEndian?: boolean): void;
        
            /**
              * Stores an Float32 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void;
        
            /**
              * Stores an Float64 value at the specified byte offset from the start of the view. 
              * @param byteOffset The place in the buffer at which the value should be set.
              * @param value The value to set.
              * @param littleEndian If false or undefined, a big-endian value should be written, otherwise a little-endian value should be written.
              */
            setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void;
        }
        declare var DataView: {
            prototype: DataView;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): DataView;
        }
        
        /////////////////////////////
        /// IE11 ECMAScript Extensions
        /////////////////////////////
        
        interface Map<K, V> {
            clear(): void;
            delete(key: K): boolean;
            forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
            get(key: K): V;
            has(key: K): boolean;
            set(key: K, value: V): Map<K, V>;
            size: number;
        }
        declare var Map: {
            new <K, V>(): Map<K, V>;
            prototype: Map<any, any>;
        }
        
        interface WeakMap<K, V> {
            clear(): void;
            delete(key: K): boolean;
            get(key: K): V;
            has(key: K): boolean;
            set(key: K, value: V): WeakMap<K, V>;
        }
        declare var WeakMap: {
            new <K, V>(): WeakMap<K, V>;
            prototype: WeakMap<any, any>;
        }
        
        interface Set<T> {
            add(value: T): Set<T>;
            clear(): void;
            delete(value: T): boolean;
            forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
            has(value: T): boolean;
            size: number;
        }
        declare var Set: {
            new <T>(): Set<T>;
            prototype: Set<any>;
        }
        
      • typescriptServices.js
        /*! *****************************************************************************
        Copyright (c) Microsoft Corporation. All rights reserved. 
        Licensed under the Apache License, Version 2.0 (the "License"); you may not use
        this file except in compliance with the License. You may obtain a copy of the
        License at http://www.apache.org/licenses/LICENSE-2.0  
         
        THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
        KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
        WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
        MERCHANTABLITY OR NON-INFRINGEMENT. 
         
        See the Apache Version 2.0 License for specific language governing permissions
        and limitations under the License.
        ***************************************************************************** */
        
        var ts;
        (function (ts) {
            (function (SyntaxKind) {
                SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown";
                SyntaxKind[SyntaxKind["EndOfFileToken"] = 1] = "EndOfFileToken";
                SyntaxKind[SyntaxKind["SingleLineCommentTrivia"] = 2] = "SingleLineCommentTrivia";
                SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia";
                SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia";
                SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia";
                SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 6] = "ConflictMarkerTrivia";
                SyntaxKind[SyntaxKind["NumericLiteral"] = 7] = "NumericLiteral";
                SyntaxKind[SyntaxKind["StringLiteral"] = 8] = "StringLiteral";
                SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 9] = "RegularExpressionLiteral";
                SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 10] = "NoSubstitutionTemplateLiteral";
                SyntaxKind[SyntaxKind["TemplateHead"] = 11] = "TemplateHead";
                SyntaxKind[SyntaxKind["TemplateMiddle"] = 12] = "TemplateMiddle";
                SyntaxKind[SyntaxKind["TemplateTail"] = 13] = "TemplateTail";
                SyntaxKind[SyntaxKind["OpenBraceToken"] = 14] = "OpenBraceToken";
                SyntaxKind[SyntaxKind["CloseBraceToken"] = 15] = "CloseBraceToken";
                SyntaxKind[SyntaxKind["OpenParenToken"] = 16] = "OpenParenToken";
                SyntaxKind[SyntaxKind["CloseParenToken"] = 17] = "CloseParenToken";
                SyntaxKind[SyntaxKind["OpenBracketToken"] = 18] = "OpenBracketToken";
                SyntaxKind[SyntaxKind["CloseBracketToken"] = 19] = "CloseBracketToken";
                SyntaxKind[SyntaxKind["DotToken"] = 20] = "DotToken";
                SyntaxKind[SyntaxKind["DotDotDotToken"] = 21] = "DotDotDotToken";
                SyntaxKind[SyntaxKind["SemicolonToken"] = 22] = "SemicolonToken";
                SyntaxKind[SyntaxKind["CommaToken"] = 23] = "CommaToken";
                SyntaxKind[SyntaxKind["LessThanToken"] = 24] = "LessThanToken";
                SyntaxKind[SyntaxKind["GreaterThanToken"] = 25] = "GreaterThanToken";
                SyntaxKind[SyntaxKind["LessThanEqualsToken"] = 26] = "LessThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanEqualsToken"] = 27] = "GreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["EqualsEqualsToken"] = 28] = "EqualsEqualsToken";
                SyntaxKind[SyntaxKind["ExclamationEqualsToken"] = 29] = "ExclamationEqualsToken";
                SyntaxKind[SyntaxKind["EqualsEqualsEqualsToken"] = 30] = "EqualsEqualsEqualsToken";
                SyntaxKind[SyntaxKind["ExclamationEqualsEqualsToken"] = 31] = "ExclamationEqualsEqualsToken";
                SyntaxKind[SyntaxKind["EqualsGreaterThanToken"] = 32] = "EqualsGreaterThanToken";
                SyntaxKind[SyntaxKind["PlusToken"] = 33] = "PlusToken";
                SyntaxKind[SyntaxKind["MinusToken"] = 34] = "MinusToken";
                SyntaxKind[SyntaxKind["AsteriskToken"] = 35] = "AsteriskToken";
                SyntaxKind[SyntaxKind["SlashToken"] = 36] = "SlashToken";
                SyntaxKind[SyntaxKind["PercentToken"] = 37] = "PercentToken";
                SyntaxKind[SyntaxKind["PlusPlusToken"] = 38] = "PlusPlusToken";
                SyntaxKind[SyntaxKind["MinusMinusToken"] = 39] = "MinusMinusToken";
                SyntaxKind[SyntaxKind["LessThanLessThanToken"] = 40] = "LessThanLessThanToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanToken"] = 41] = "GreaterThanGreaterThanToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanToken"] = 42] = "GreaterThanGreaterThanGreaterThanToken";
                SyntaxKind[SyntaxKind["AmpersandToken"] = 43] = "AmpersandToken";
                SyntaxKind[SyntaxKind["BarToken"] = 44] = "BarToken";
                SyntaxKind[SyntaxKind["CaretToken"] = 45] = "CaretToken";
                SyntaxKind[SyntaxKind["ExclamationToken"] = 46] = "ExclamationToken";
                SyntaxKind[SyntaxKind["TildeToken"] = 47] = "TildeToken";
                SyntaxKind[SyntaxKind["AmpersandAmpersandToken"] = 48] = "AmpersandAmpersandToken";
                SyntaxKind[SyntaxKind["BarBarToken"] = 49] = "BarBarToken";
                SyntaxKind[SyntaxKind["QuestionToken"] = 50] = "QuestionToken";
                SyntaxKind[SyntaxKind["ColonToken"] = 51] = "ColonToken";
                SyntaxKind[SyntaxKind["EqualsToken"] = 52] = "EqualsToken";
                SyntaxKind[SyntaxKind["PlusEqualsToken"] = 53] = "PlusEqualsToken";
                SyntaxKind[SyntaxKind["MinusEqualsToken"] = 54] = "MinusEqualsToken";
                SyntaxKind[SyntaxKind["AsteriskEqualsToken"] = 55] = "AsteriskEqualsToken";
                SyntaxKind[SyntaxKind["SlashEqualsToken"] = 56] = "SlashEqualsToken";
                SyntaxKind[SyntaxKind["PercentEqualsToken"] = 57] = "PercentEqualsToken";
                SyntaxKind[SyntaxKind["LessThanLessThanEqualsToken"] = 58] = "LessThanLessThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanEqualsToken"] = 59] = "GreaterThanGreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanEqualsToken"] = 60] = "GreaterThanGreaterThanGreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 61] = "AmpersandEqualsToken";
                SyntaxKind[SyntaxKind["BarEqualsToken"] = 62] = "BarEqualsToken";
                SyntaxKind[SyntaxKind["CaretEqualsToken"] = 63] = "CaretEqualsToken";
                SyntaxKind[SyntaxKind["Identifier"] = 64] = "Identifier";
                SyntaxKind[SyntaxKind["BreakKeyword"] = 65] = "BreakKeyword";
                SyntaxKind[SyntaxKind["CaseKeyword"] = 66] = "CaseKeyword";
                SyntaxKind[SyntaxKind["CatchKeyword"] = 67] = "CatchKeyword";
                SyntaxKind[SyntaxKind["ClassKeyword"] = 68] = "ClassKeyword";
                SyntaxKind[SyntaxKind["ConstKeyword"] = 69] = "ConstKeyword";
                SyntaxKind[SyntaxKind["ContinueKeyword"] = 70] = "ContinueKeyword";
                SyntaxKind[SyntaxKind["DebuggerKeyword"] = 71] = "DebuggerKeyword";
                SyntaxKind[SyntaxKind["DefaultKeyword"] = 72] = "DefaultKeyword";
                SyntaxKind[SyntaxKind["DeleteKeyword"] = 73] = "DeleteKeyword";
                SyntaxKind[SyntaxKind["DoKeyword"] = 74] = "DoKeyword";
                SyntaxKind[SyntaxKind["ElseKeyword"] = 75] = "ElseKeyword";
                SyntaxKind[SyntaxKind["EnumKeyword"] = 76] = "EnumKeyword";
                SyntaxKind[SyntaxKind["ExportKeyword"] = 77] = "ExportKeyword";
                SyntaxKind[SyntaxKind["ExtendsKeyword"] = 78] = "ExtendsKeyword";
                SyntaxKind[SyntaxKind["FalseKeyword"] = 79] = "FalseKeyword";
                SyntaxKind[SyntaxKind["FinallyKeyword"] = 80] = "FinallyKeyword";
                SyntaxKind[SyntaxKind["ForKeyword"] = 81] = "ForKeyword";
                SyntaxKind[SyntaxKind["FunctionKeyword"] = 82] = "FunctionKeyword";
                SyntaxKind[SyntaxKind["IfKeyword"] = 83] = "IfKeyword";
                SyntaxKind[SyntaxKind["ImportKeyword"] = 84] = "ImportKeyword";
                SyntaxKind[SyntaxKind["InKeyword"] = 85] = "InKeyword";
                SyntaxKind[SyntaxKind["InstanceOfKeyword"] = 86] = "InstanceOfKeyword";
                SyntaxKind[SyntaxKind["NewKeyword"] = 87] = "NewKeyword";
                SyntaxKind[SyntaxKind["NullKeyword"] = 88] = "NullKeyword";
                SyntaxKind[SyntaxKind["ReturnKeyword"] = 89] = "ReturnKeyword";
                SyntaxKind[SyntaxKind["SuperKeyword"] = 90] = "SuperKeyword";
                SyntaxKind[SyntaxKind["SwitchKeyword"] = 91] = "SwitchKeyword";
                SyntaxKind[SyntaxKind["ThisKeyword"] = 92] = "ThisKeyword";
                SyntaxKind[SyntaxKind["ThrowKeyword"] = 93] = "ThrowKeyword";
                SyntaxKind[SyntaxKind["TrueKeyword"] = 94] = "TrueKeyword";
                SyntaxKind[SyntaxKind["TryKeyword"] = 95] = "TryKeyword";
                SyntaxKind[SyntaxKind["TypeOfKeyword"] = 96] = "TypeOfKeyword";
                SyntaxKind[SyntaxKind["VarKeyword"] = 97] = "VarKeyword";
                SyntaxKind[SyntaxKind["VoidKeyword"] = 98] = "VoidKeyword";
                SyntaxKind[SyntaxKind["WhileKeyword"] = 99] = "WhileKeyword";
                SyntaxKind[SyntaxKind["WithKeyword"] = 100] = "WithKeyword";
                SyntaxKind[SyntaxKind["AsKeyword"] = 101] = "AsKeyword";
                SyntaxKind[SyntaxKind["ImplementsKeyword"] = 102] = "ImplementsKeyword";
                SyntaxKind[SyntaxKind["InterfaceKeyword"] = 103] = "InterfaceKeyword";
                SyntaxKind[SyntaxKind["LetKeyword"] = 104] = "LetKeyword";
                SyntaxKind[SyntaxKind["PackageKeyword"] = 105] = "PackageKeyword";
                SyntaxKind[SyntaxKind["PrivateKeyword"] = 106] = "PrivateKeyword";
                SyntaxKind[SyntaxKind["ProtectedKeyword"] = 107] = "ProtectedKeyword";
                SyntaxKind[SyntaxKind["PublicKeyword"] = 108] = "PublicKeyword";
                SyntaxKind[SyntaxKind["StaticKeyword"] = 109] = "StaticKeyword";
                SyntaxKind[SyntaxKind["YieldKeyword"] = 110] = "YieldKeyword";
                SyntaxKind[SyntaxKind["AnyKeyword"] = 111] = "AnyKeyword";
                SyntaxKind[SyntaxKind["BooleanKeyword"] = 112] = "BooleanKeyword";
                SyntaxKind[SyntaxKind["ConstructorKeyword"] = 113] = "ConstructorKeyword";
                SyntaxKind[SyntaxKind["DeclareKeyword"] = 114] = "DeclareKeyword";
                SyntaxKind[SyntaxKind["GetKeyword"] = 115] = "GetKeyword";
                SyntaxKind[SyntaxKind["ModuleKeyword"] = 116] = "ModuleKeyword";
                SyntaxKind[SyntaxKind["RequireKeyword"] = 117] = "RequireKeyword";
                SyntaxKind[SyntaxKind["NumberKeyword"] = 118] = "NumberKeyword";
                SyntaxKind[SyntaxKind["SetKeyword"] = 119] = "SetKeyword";
                SyntaxKind[SyntaxKind["StringKeyword"] = 120] = "StringKeyword";
                SyntaxKind[SyntaxKind["SymbolKeyword"] = 121] = "SymbolKeyword";
                SyntaxKind[SyntaxKind["TypeKeyword"] = 122] = "TypeKeyword";
                SyntaxKind[SyntaxKind["FromKeyword"] = 123] = "FromKeyword";
                SyntaxKind[SyntaxKind["OfKeyword"] = 124] = "OfKeyword";
                SyntaxKind[SyntaxKind["QualifiedName"] = 125] = "QualifiedName";
                SyntaxKind[SyntaxKind["ComputedPropertyName"] = 126] = "ComputedPropertyName";
                SyntaxKind[SyntaxKind["TypeParameter"] = 127] = "TypeParameter";
                SyntaxKind[SyntaxKind["Parameter"] = 128] = "Parameter";
                SyntaxKind[SyntaxKind["PropertySignature"] = 129] = "PropertySignature";
                SyntaxKind[SyntaxKind["PropertyDeclaration"] = 130] = "PropertyDeclaration";
                SyntaxKind[SyntaxKind["MethodSignature"] = 131] = "MethodSignature";
                SyntaxKind[SyntaxKind["MethodDeclaration"] = 132] = "MethodDeclaration";
                SyntaxKind[SyntaxKind["Constructor"] = 133] = "Constructor";
                SyntaxKind[SyntaxKind["GetAccessor"] = 134] = "GetAccessor";
                SyntaxKind[SyntaxKind["SetAccessor"] = 135] = "SetAccessor";
                SyntaxKind[SyntaxKind["CallSignature"] = 136] = "CallSignature";
                SyntaxKind[SyntaxKind["ConstructSignature"] = 137] = "ConstructSignature";
                SyntaxKind[SyntaxKind["IndexSignature"] = 138] = "IndexSignature";
                SyntaxKind[SyntaxKind["TypeReference"] = 139] = "TypeReference";
                SyntaxKind[SyntaxKind["FunctionType"] = 140] = "FunctionType";
                SyntaxKind[SyntaxKind["ConstructorType"] = 141] = "ConstructorType";
                SyntaxKind[SyntaxKind["TypeQuery"] = 142] = "TypeQuery";
                SyntaxKind[SyntaxKind["TypeLiteral"] = 143] = "TypeLiteral";
                SyntaxKind[SyntaxKind["ArrayType"] = 144] = "ArrayType";
                SyntaxKind[SyntaxKind["TupleType"] = 145] = "TupleType";
                SyntaxKind[SyntaxKind["UnionType"] = 146] = "UnionType";
                SyntaxKind[SyntaxKind["ParenthesizedType"] = 147] = "ParenthesizedType";
                SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 148] = "ObjectBindingPattern";
                SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 149] = "ArrayBindingPattern";
                SyntaxKind[SyntaxKind["BindingElement"] = 150] = "BindingElement";
                SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 151] = "ArrayLiteralExpression";
                SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 152] = "ObjectLiteralExpression";
                SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 153] = "PropertyAccessExpression";
                SyntaxKind[SyntaxKind["ElementAccessExpression"] = 154] = "ElementAccessExpression";
                SyntaxKind[SyntaxKind["CallExpression"] = 155] = "CallExpression";
                SyntaxKind[SyntaxKind["NewExpression"] = 156] = "NewExpression";
                SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 157] = "TaggedTemplateExpression";
                SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 158] = "TypeAssertionExpression";
                SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 159] = "ParenthesizedExpression";
                SyntaxKind[SyntaxKind["FunctionExpression"] = 160] = "FunctionExpression";
                SyntaxKind[SyntaxKind["ArrowFunction"] = 161] = "ArrowFunction";
                SyntaxKind[SyntaxKind["DeleteExpression"] = 162] = "DeleteExpression";
                SyntaxKind[SyntaxKind["TypeOfExpression"] = 163] = "TypeOfExpression";
                SyntaxKind[SyntaxKind["VoidExpression"] = 164] = "VoidExpression";
                SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 165] = "PrefixUnaryExpression";
                SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 166] = "PostfixUnaryExpression";
                SyntaxKind[SyntaxKind["BinaryExpression"] = 167] = "BinaryExpression";
                SyntaxKind[SyntaxKind["ConditionalExpression"] = 168] = "ConditionalExpression";
                SyntaxKind[SyntaxKind["TemplateExpression"] = 169] = "TemplateExpression";
                SyntaxKind[SyntaxKind["YieldExpression"] = 170] = "YieldExpression";
                SyntaxKind[SyntaxKind["SpreadElementExpression"] = 171] = "SpreadElementExpression";
                SyntaxKind[SyntaxKind["OmittedExpression"] = 172] = "OmittedExpression";
                SyntaxKind[SyntaxKind["TemplateSpan"] = 173] = "TemplateSpan";
                SyntaxKind[SyntaxKind["Block"] = 174] = "Block";
                SyntaxKind[SyntaxKind["VariableStatement"] = 175] = "VariableStatement";
                SyntaxKind[SyntaxKind["EmptyStatement"] = 176] = "EmptyStatement";
                SyntaxKind[SyntaxKind["ExpressionStatement"] = 177] = "ExpressionStatement";
                SyntaxKind[SyntaxKind["IfStatement"] = 178] = "IfStatement";
                SyntaxKind[SyntaxKind["DoStatement"] = 179] = "DoStatement";
                SyntaxKind[SyntaxKind["WhileStatement"] = 180] = "WhileStatement";
                SyntaxKind[SyntaxKind["ForStatement"] = 181] = "ForStatement";
                SyntaxKind[SyntaxKind["ForInStatement"] = 182] = "ForInStatement";
                SyntaxKind[SyntaxKind["ForOfStatement"] = 183] = "ForOfStatement";
                SyntaxKind[SyntaxKind["ContinueStatement"] = 184] = "ContinueStatement";
                SyntaxKind[SyntaxKind["BreakStatement"] = 185] = "BreakStatement";
                SyntaxKind[SyntaxKind["ReturnStatement"] = 186] = "ReturnStatement";
                SyntaxKind[SyntaxKind["WithStatement"] = 187] = "WithStatement";
                SyntaxKind[SyntaxKind["SwitchStatement"] = 188] = "SwitchStatement";
                SyntaxKind[SyntaxKind["LabeledStatement"] = 189] = "LabeledStatement";
                SyntaxKind[SyntaxKind["ThrowStatement"] = 190] = "ThrowStatement";
                SyntaxKind[SyntaxKind["TryStatement"] = 191] = "TryStatement";
                SyntaxKind[SyntaxKind["DebuggerStatement"] = 192] = "DebuggerStatement";
                SyntaxKind[SyntaxKind["VariableDeclaration"] = 193] = "VariableDeclaration";
                SyntaxKind[SyntaxKind["VariableDeclarationList"] = 194] = "VariableDeclarationList";
                SyntaxKind[SyntaxKind["FunctionDeclaration"] = 195] = "FunctionDeclaration";
                SyntaxKind[SyntaxKind["ClassDeclaration"] = 196] = "ClassDeclaration";
                SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 197] = "InterfaceDeclaration";
                SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 198] = "TypeAliasDeclaration";
                SyntaxKind[SyntaxKind["EnumDeclaration"] = 199] = "EnumDeclaration";
                SyntaxKind[SyntaxKind["ModuleDeclaration"] = 200] = "ModuleDeclaration";
                SyntaxKind[SyntaxKind["ModuleBlock"] = 201] = "ModuleBlock";
                SyntaxKind[SyntaxKind["CaseBlock"] = 202] = "CaseBlock";
                SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 203] = "ImportEqualsDeclaration";
                SyntaxKind[SyntaxKind["ImportDeclaration"] = 204] = "ImportDeclaration";
                SyntaxKind[SyntaxKind["ImportClause"] = 205] = "ImportClause";
                SyntaxKind[SyntaxKind["NamespaceImport"] = 206] = "NamespaceImport";
                SyntaxKind[SyntaxKind["NamedImports"] = 207] = "NamedImports";
                SyntaxKind[SyntaxKind["ImportSpecifier"] = 208] = "ImportSpecifier";
                SyntaxKind[SyntaxKind["ExportAssignment"] = 209] = "ExportAssignment";
                SyntaxKind[SyntaxKind["ExportDeclaration"] = 210] = "ExportDeclaration";
                SyntaxKind[SyntaxKind["NamedExports"] = 211] = "NamedExports";
                SyntaxKind[SyntaxKind["ExportSpecifier"] = 212] = "ExportSpecifier";
                SyntaxKind[SyntaxKind["ExternalModuleReference"] = 213] = "ExternalModuleReference";
                SyntaxKind[SyntaxKind["CaseClause"] = 214] = "CaseClause";
                SyntaxKind[SyntaxKind["DefaultClause"] = 215] = "DefaultClause";
                SyntaxKind[SyntaxKind["HeritageClause"] = 216] = "HeritageClause";
                SyntaxKind[SyntaxKind["CatchClause"] = 217] = "CatchClause";
                SyntaxKind[SyntaxKind["PropertyAssignment"] = 218] = "PropertyAssignment";
                SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 219] = "ShorthandPropertyAssignment";
                SyntaxKind[SyntaxKind["EnumMember"] = 220] = "EnumMember";
                SyntaxKind[SyntaxKind["SourceFile"] = 221] = "SourceFile";
                SyntaxKind[SyntaxKind["SyntaxList"] = 222] = "SyntaxList";
                SyntaxKind[SyntaxKind["Count"] = 223] = "Count";
                SyntaxKind[SyntaxKind["FirstAssignment"] = 52] = "FirstAssignment";
                SyntaxKind[SyntaxKind["LastAssignment"] = 63] = "LastAssignment";
                SyntaxKind[SyntaxKind["FirstReservedWord"] = 65] = "FirstReservedWord";
                SyntaxKind[SyntaxKind["LastReservedWord"] = 100] = "LastReservedWord";
                SyntaxKind[SyntaxKind["FirstKeyword"] = 65] = "FirstKeyword";
                SyntaxKind[SyntaxKind["LastKeyword"] = 124] = "LastKeyword";
                SyntaxKind[SyntaxKind["FirstFutureReservedWord"] = 102] = "FirstFutureReservedWord";
                SyntaxKind[SyntaxKind["LastFutureReservedWord"] = 110] = "LastFutureReservedWord";
                SyntaxKind[SyntaxKind["FirstTypeNode"] = 139] = "FirstTypeNode";
                SyntaxKind[SyntaxKind["LastTypeNode"] = 147] = "LastTypeNode";
                SyntaxKind[SyntaxKind["FirstPunctuation"] = 14] = "FirstPunctuation";
                SyntaxKind[SyntaxKind["LastPunctuation"] = 63] = "LastPunctuation";
                SyntaxKind[SyntaxKind["FirstToken"] = 0] = "FirstToken";
                SyntaxKind[SyntaxKind["LastToken"] = 124] = "LastToken";
                SyntaxKind[SyntaxKind["FirstTriviaToken"] = 2] = "FirstTriviaToken";
                SyntaxKind[SyntaxKind["LastTriviaToken"] = 6] = "LastTriviaToken";
                SyntaxKind[SyntaxKind["FirstLiteralToken"] = 7] = "FirstLiteralToken";
                SyntaxKind[SyntaxKind["LastLiteralToken"] = 10] = "LastLiteralToken";
                SyntaxKind[SyntaxKind["FirstTemplateToken"] = 10] = "FirstTemplateToken";
                SyntaxKind[SyntaxKind["LastTemplateToken"] = 13] = "LastTemplateToken";
                SyntaxKind[SyntaxKind["FirstBinaryOperator"] = 24] = "FirstBinaryOperator";
                SyntaxKind[SyntaxKind["LastBinaryOperator"] = 63] = "LastBinaryOperator";
                SyntaxKind[SyntaxKind["FirstNode"] = 125] = "FirstNode";
            })(ts.SyntaxKind || (ts.SyntaxKind = {}));
            var SyntaxKind = ts.SyntaxKind;
            (function (NodeFlags) {
                NodeFlags[NodeFlags["Export"] = 1] = "Export";
                NodeFlags[NodeFlags["Ambient"] = 2] = "Ambient";
                NodeFlags[NodeFlags["Public"] = 16] = "Public";
                NodeFlags[NodeFlags["Private"] = 32] = "Private";
                NodeFlags[NodeFlags["Protected"] = 64] = "Protected";
                NodeFlags[NodeFlags["Static"] = 128] = "Static";
                NodeFlags[NodeFlags["Default"] = 256] = "Default";
                NodeFlags[NodeFlags["MultiLine"] = 512] = "MultiLine";
                NodeFlags[NodeFlags["Synthetic"] = 1024] = "Synthetic";
                NodeFlags[NodeFlags["DeclarationFile"] = 2048] = "DeclarationFile";
                NodeFlags[NodeFlags["Let"] = 4096] = "Let";
                NodeFlags[NodeFlags["Const"] = 8192] = "Const";
                NodeFlags[NodeFlags["OctalLiteral"] = 16384] = "OctalLiteral";
                NodeFlags[NodeFlags["Modifier"] = 499] = "Modifier";
                NodeFlags[NodeFlags["AccessibilityModifier"] = 112] = "AccessibilityModifier";
                NodeFlags[NodeFlags["BlockScoped"] = 12288] = "BlockScoped";
            })(ts.NodeFlags || (ts.NodeFlags = {}));
            var NodeFlags = ts.NodeFlags;
            (function (ParserContextFlags) {
                ParserContextFlags[ParserContextFlags["StrictMode"] = 1] = "StrictMode";
                ParserContextFlags[ParserContextFlags["DisallowIn"] = 2] = "DisallowIn";
                ParserContextFlags[ParserContextFlags["Yield"] = 4] = "Yield";
                ParserContextFlags[ParserContextFlags["GeneratorParameter"] = 8] = "GeneratorParameter";
                ParserContextFlags[ParserContextFlags["ThisNodeHasError"] = 16] = "ThisNodeHasError";
                ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 31] = "ParserGeneratedFlags";
                ParserContextFlags[ParserContextFlags["ThisNodeOrAnySubNodesHasError"] = 32] = "ThisNodeOrAnySubNodesHasError";
                ParserContextFlags[ParserContextFlags["HasAggregatedChildData"] = 64] = "HasAggregatedChildData";
            })(ts.ParserContextFlags || (ts.ParserContextFlags = {}));
            var ParserContextFlags = ts.ParserContextFlags;
            (function (RelationComparisonResult) {
                RelationComparisonResult[RelationComparisonResult["Succeeded"] = 1] = "Succeeded";
                RelationComparisonResult[RelationComparisonResult["Failed"] = 2] = "Failed";
                RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported";
            })(ts.RelationComparisonResult || (ts.RelationComparisonResult = {}));
            var RelationComparisonResult = ts.RelationComparisonResult;
            (function (ExitStatus) {
                ExitStatus[ExitStatus["Success"] = 0] = "Success";
                ExitStatus[ExitStatus["DiagnosticsPresent_OutputsSkipped"] = 1] = "DiagnosticsPresent_OutputsSkipped";
                ExitStatus[ExitStatus["DiagnosticsPresent_OutputsGenerated"] = 2] = "DiagnosticsPresent_OutputsGenerated";
            })(ts.ExitStatus || (ts.ExitStatus = {}));
            var ExitStatus = ts.ExitStatus;
            (function (TypeFormatFlags) {
                TypeFormatFlags[TypeFormatFlags["None"] = 0] = "None";
                TypeFormatFlags[TypeFormatFlags["WriteArrayAsGenericType"] = 1] = "WriteArrayAsGenericType";
                TypeFormatFlags[TypeFormatFlags["UseTypeOfFunction"] = 2] = "UseTypeOfFunction";
                TypeFormatFlags[TypeFormatFlags["NoTruncation"] = 4] = "NoTruncation";
                TypeFormatFlags[TypeFormatFlags["WriteArrowStyleSignature"] = 8] = "WriteArrowStyleSignature";
                TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 16] = "WriteOwnNameForAnyLike";
                TypeFormatFlags[TypeFormatFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature";
                TypeFormatFlags[TypeFormatFlags["InElementType"] = 64] = "InElementType";
                TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 128] = "UseFullyQualifiedType";
            })(ts.TypeFormatFlags || (ts.TypeFormatFlags = {}));
            var TypeFormatFlags = ts.TypeFormatFlags;
            (function (SymbolFormatFlags) {
                SymbolFormatFlags[SymbolFormatFlags["None"] = 0] = "None";
                SymbolFormatFlags[SymbolFormatFlags["WriteTypeParametersOrArguments"] = 1] = "WriteTypeParametersOrArguments";
                SymbolFormatFlags[SymbolFormatFlags["UseOnlyExternalAliasing"] = 2] = "UseOnlyExternalAliasing";
            })(ts.SymbolFormatFlags || (ts.SymbolFormatFlags = {}));
            var SymbolFormatFlags = ts.SymbolFormatFlags;
            (function (SymbolAccessibility) {
                SymbolAccessibility[SymbolAccessibility["Accessible"] = 0] = "Accessible";
                SymbolAccessibility[SymbolAccessibility["NotAccessible"] = 1] = "NotAccessible";
                SymbolAccessibility[SymbolAccessibility["CannotBeNamed"] = 2] = "CannotBeNamed";
            })(ts.SymbolAccessibility || (ts.SymbolAccessibility = {}));
            var SymbolAccessibility = ts.SymbolAccessibility;
            (function (SymbolFlags) {
                SymbolFlags[SymbolFlags["FunctionScopedVariable"] = 1] = "FunctionScopedVariable";
                SymbolFlags[SymbolFlags["BlockScopedVariable"] = 2] = "BlockScopedVariable";
                SymbolFlags[SymbolFlags["Property"] = 4] = "Property";
                SymbolFlags[SymbolFlags["EnumMember"] = 8] = "EnumMember";
                SymbolFlags[SymbolFlags["Function"] = 16] = "Function";
                SymbolFlags[SymbolFlags["Class"] = 32] = "Class";
                SymbolFlags[SymbolFlags["Interface"] = 64] = "Interface";
                SymbolFlags[SymbolFlags["ConstEnum"] = 128] = "ConstEnum";
                SymbolFlags[SymbolFlags["RegularEnum"] = 256] = "RegularEnum";
                SymbolFlags[SymbolFlags["ValueModule"] = 512] = "ValueModule";
                SymbolFlags[SymbolFlags["NamespaceModule"] = 1024] = "NamespaceModule";
                SymbolFlags[SymbolFlags["TypeLiteral"] = 2048] = "TypeLiteral";
                SymbolFlags[SymbolFlags["ObjectLiteral"] = 4096] = "ObjectLiteral";
                SymbolFlags[SymbolFlags["Method"] = 8192] = "Method";
                SymbolFlags[SymbolFlags["Constructor"] = 16384] = "Constructor";
                SymbolFlags[SymbolFlags["GetAccessor"] = 32768] = "GetAccessor";
                SymbolFlags[SymbolFlags["SetAccessor"] = 65536] = "SetAccessor";
                SymbolFlags[SymbolFlags["Signature"] = 131072] = "Signature";
                SymbolFlags[SymbolFlags["TypeParameter"] = 262144] = "TypeParameter";
                SymbolFlags[SymbolFlags["TypeAlias"] = 524288] = "TypeAlias";
                SymbolFlags[SymbolFlags["ExportValue"] = 1048576] = "ExportValue";
                SymbolFlags[SymbolFlags["ExportType"] = 2097152] = "ExportType";
                SymbolFlags[SymbolFlags["ExportNamespace"] = 4194304] = "ExportNamespace";
                SymbolFlags[SymbolFlags["Alias"] = 8388608] = "Alias";
                SymbolFlags[SymbolFlags["Instantiated"] = 16777216] = "Instantiated";
                SymbolFlags[SymbolFlags["Merged"] = 33554432] = "Merged";
                SymbolFlags[SymbolFlags["Transient"] = 67108864] = "Transient";
                SymbolFlags[SymbolFlags["Prototype"] = 134217728] = "Prototype";
                SymbolFlags[SymbolFlags["UnionProperty"] = 268435456] = "UnionProperty";
                SymbolFlags[SymbolFlags["Optional"] = 536870912] = "Optional";
                SymbolFlags[SymbolFlags["ExportStar"] = 1073741824] = "ExportStar";
                SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum";
                SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable";
                SymbolFlags[SymbolFlags["Value"] = 107455] = "Value";
                SymbolFlags[SymbolFlags["Type"] = 793056] = "Type";
                SymbolFlags[SymbolFlags["Namespace"] = 1536] = "Namespace";
                SymbolFlags[SymbolFlags["Module"] = 1536] = "Module";
                SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor";
                SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 107454] = "FunctionScopedVariableExcludes";
                SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 107455] = "BlockScopedVariableExcludes";
                SymbolFlags[SymbolFlags["ParameterExcludes"] = 107455] = "ParameterExcludes";
                SymbolFlags[SymbolFlags["PropertyExcludes"] = 107455] = "PropertyExcludes";
                SymbolFlags[SymbolFlags["EnumMemberExcludes"] = 107455] = "EnumMemberExcludes";
                SymbolFlags[SymbolFlags["FunctionExcludes"] = 106927] = "FunctionExcludes";
                SymbolFlags[SymbolFlags["ClassExcludes"] = 899583] = "ClassExcludes";
                SymbolFlags[SymbolFlags["InterfaceExcludes"] = 792992] = "InterfaceExcludes";
                SymbolFlags[SymbolFlags["RegularEnumExcludes"] = 899327] = "RegularEnumExcludes";
                SymbolFlags[SymbolFlags["ConstEnumExcludes"] = 899967] = "ConstEnumExcludes";
                SymbolFlags[SymbolFlags["ValueModuleExcludes"] = 106639] = "ValueModuleExcludes";
                SymbolFlags[SymbolFlags["NamespaceModuleExcludes"] = 0] = "NamespaceModuleExcludes";
                SymbolFlags[SymbolFlags["MethodExcludes"] = 99263] = "MethodExcludes";
                SymbolFlags[SymbolFlags["GetAccessorExcludes"] = 41919] = "GetAccessorExcludes";
                SymbolFlags[SymbolFlags["SetAccessorExcludes"] = 74687] = "SetAccessorExcludes";
                SymbolFlags[SymbolFlags["TypeParameterExcludes"] = 530912] = "TypeParameterExcludes";
                SymbolFlags[SymbolFlags["TypeAliasExcludes"] = 793056] = "TypeAliasExcludes";
                SymbolFlags[SymbolFlags["AliasExcludes"] = 8388608] = "AliasExcludes";
                SymbolFlags[SymbolFlags["ModuleMember"] = 8914931] = "ModuleMember";
                SymbolFlags[SymbolFlags["ExportHasLocal"] = 944] = "ExportHasLocal";
                SymbolFlags[SymbolFlags["HasLocals"] = 255504] = "HasLocals";
                SymbolFlags[SymbolFlags["HasExports"] = 1952] = "HasExports";
                SymbolFlags[SymbolFlags["HasMembers"] = 6240] = "HasMembers";
                SymbolFlags[SymbolFlags["IsContainer"] = 262128] = "IsContainer";
                SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor";
                SymbolFlags[SymbolFlags["Export"] = 7340032] = "Export";
            })(ts.SymbolFlags || (ts.SymbolFlags = {}));
            var SymbolFlags = ts.SymbolFlags;
            (function (NodeCheckFlags) {
                NodeCheckFlags[NodeCheckFlags["TypeChecked"] = 1] = "TypeChecked";
                NodeCheckFlags[NodeCheckFlags["LexicalThis"] = 2] = "LexicalThis";
                NodeCheckFlags[NodeCheckFlags["CaptureThis"] = 4] = "CaptureThis";
                NodeCheckFlags[NodeCheckFlags["EmitExtends"] = 8] = "EmitExtends";
                NodeCheckFlags[NodeCheckFlags["SuperInstance"] = 16] = "SuperInstance";
                NodeCheckFlags[NodeCheckFlags["SuperStatic"] = 32] = "SuperStatic";
                NodeCheckFlags[NodeCheckFlags["ContextChecked"] = 64] = "ContextChecked";
                NodeCheckFlags[NodeCheckFlags["EnumValuesComputed"] = 128] = "EnumValuesComputed";
                NodeCheckFlags[NodeCheckFlags["BlockScopedBindingInLoop"] = 256] = "BlockScopedBindingInLoop";
            })(ts.NodeCheckFlags || (ts.NodeCheckFlags = {}));
            var NodeCheckFlags = ts.NodeCheckFlags;
            (function (TypeFlags) {
                TypeFlags[TypeFlags["Any"] = 1] = "Any";
                TypeFlags[TypeFlags["String"] = 2] = "String";
                TypeFlags[TypeFlags["Number"] = 4] = "Number";
                TypeFlags[TypeFlags["Boolean"] = 8] = "Boolean";
                TypeFlags[TypeFlags["Void"] = 16] = "Void";
                TypeFlags[TypeFlags["Undefined"] = 32] = "Undefined";
                TypeFlags[TypeFlags["Null"] = 64] = "Null";
                TypeFlags[TypeFlags["Enum"] = 128] = "Enum";
                TypeFlags[TypeFlags["StringLiteral"] = 256] = "StringLiteral";
                TypeFlags[TypeFlags["TypeParameter"] = 512] = "TypeParameter";
                TypeFlags[TypeFlags["Class"] = 1024] = "Class";
                TypeFlags[TypeFlags["Interface"] = 2048] = "Interface";
                TypeFlags[TypeFlags["Reference"] = 4096] = "Reference";
                TypeFlags[TypeFlags["Tuple"] = 8192] = "Tuple";
                TypeFlags[TypeFlags["Union"] = 16384] = "Union";
                TypeFlags[TypeFlags["Anonymous"] = 32768] = "Anonymous";
                TypeFlags[TypeFlags["FromSignature"] = 65536] = "FromSignature";
                TypeFlags[TypeFlags["ObjectLiteral"] = 131072] = "ObjectLiteral";
                TypeFlags[TypeFlags["ContainsUndefinedOrNull"] = 262144] = "ContainsUndefinedOrNull";
                TypeFlags[TypeFlags["ContainsObjectLiteral"] = 524288] = "ContainsObjectLiteral";
                TypeFlags[TypeFlags["ESSymbol"] = 1048576] = "ESSymbol";
                TypeFlags[TypeFlags["Intrinsic"] = 1048703] = "Intrinsic";
                TypeFlags[TypeFlags["Primitive"] = 1049086] = "Primitive";
                TypeFlags[TypeFlags["StringLike"] = 258] = "StringLike";
                TypeFlags[TypeFlags["NumberLike"] = 132] = "NumberLike";
                TypeFlags[TypeFlags["ObjectType"] = 48128] = "ObjectType";
                TypeFlags[TypeFlags["RequiresWidening"] = 786432] = "RequiresWidening";
            })(ts.TypeFlags || (ts.TypeFlags = {}));
            var TypeFlags = ts.TypeFlags;
            (function (SignatureKind) {
                SignatureKind[SignatureKind["Call"] = 0] = "Call";
                SignatureKind[SignatureKind["Construct"] = 1] = "Construct";
            })(ts.SignatureKind || (ts.SignatureKind = {}));
            var SignatureKind = ts.SignatureKind;
            (function (IndexKind) {
                IndexKind[IndexKind["String"] = 0] = "String";
                IndexKind[IndexKind["Number"] = 1] = "Number";
            })(ts.IndexKind || (ts.IndexKind = {}));
            var IndexKind = ts.IndexKind;
            (function (DiagnosticCategory) {
                DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
                DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
                DiagnosticCategory[DiagnosticCategory["Message"] = 2] = "Message";
            })(ts.DiagnosticCategory || (ts.DiagnosticCategory = {}));
            var DiagnosticCategory = ts.DiagnosticCategory;
            (function (ModuleKind) {
                ModuleKind[ModuleKind["None"] = 0] = "None";
                ModuleKind[ModuleKind["CommonJS"] = 1] = "CommonJS";
                ModuleKind[ModuleKind["AMD"] = 2] = "AMD";
            })(ts.ModuleKind || (ts.ModuleKind = {}));
            var ModuleKind = ts.ModuleKind;
            (function (ScriptTarget) {
                ScriptTarget[ScriptTarget["ES3"] = 0] = "ES3";
                ScriptTarget[ScriptTarget["ES5"] = 1] = "ES5";
                ScriptTarget[ScriptTarget["ES6"] = 2] = "ES6";
                ScriptTarget[ScriptTarget["Latest"] = 2] = "Latest";
            })(ts.ScriptTarget || (ts.ScriptTarget = {}));
            var ScriptTarget = ts.ScriptTarget;
            (function (CharacterCodes) {
                CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter";
                CharacterCodes[CharacterCodes["maxAsciiCharacter"] = 127] = "maxAsciiCharacter";
                CharacterCodes[CharacterCodes["lineFeed"] = 10] = "lineFeed";
                CharacterCodes[CharacterCodes["carriageReturn"] = 13] = "carriageReturn";
                CharacterCodes[CharacterCodes["lineSeparator"] = 8232] = "lineSeparator";
                CharacterCodes[CharacterCodes["paragraphSeparator"] = 8233] = "paragraphSeparator";
                CharacterCodes[CharacterCodes["nextLine"] = 133] = "nextLine";
                CharacterCodes[CharacterCodes["space"] = 32] = "space";
                CharacterCodes[CharacterCodes["nonBreakingSpace"] = 160] = "nonBreakingSpace";
                CharacterCodes[CharacterCodes["enQuad"] = 8192] = "enQuad";
                CharacterCodes[CharacterCodes["emQuad"] = 8193] = "emQuad";
                CharacterCodes[CharacterCodes["enSpace"] = 8194] = "enSpace";
                CharacterCodes[CharacterCodes["emSpace"] = 8195] = "emSpace";
                CharacterCodes[CharacterCodes["threePerEmSpace"] = 8196] = "threePerEmSpace";
                CharacterCodes[CharacterCodes["fourPerEmSpace"] = 8197] = "fourPerEmSpace";
                CharacterCodes[CharacterCodes["sixPerEmSpace"] = 8198] = "sixPerEmSpace";
                CharacterCodes[CharacterCodes["figureSpace"] = 8199] = "figureSpace";
                CharacterCodes[CharacterCodes["punctuationSpace"] = 8200] = "punctuationSpace";
                CharacterCodes[CharacterCodes["thinSpace"] = 8201] = "thinSpace";
                CharacterCodes[CharacterCodes["hairSpace"] = 8202] = "hairSpace";
                CharacterCodes[CharacterCodes["zeroWidthSpace"] = 8203] = "zeroWidthSpace";
                CharacterCodes[CharacterCodes["narrowNoBreakSpace"] = 8239] = "narrowNoBreakSpace";
                CharacterCodes[CharacterCodes["ideographicSpace"] = 12288] = "ideographicSpace";
                CharacterCodes[CharacterCodes["mathematicalSpace"] = 8287] = "mathematicalSpace";
                CharacterCodes[CharacterCodes["ogham"] = 5760] = "ogham";
                CharacterCodes[CharacterCodes["_"] = 95] = "_";
                CharacterCodes[CharacterCodes["$"] = 36] = "$";
                CharacterCodes[CharacterCodes["_0"] = 48] = "_0";
                CharacterCodes[CharacterCodes["_1"] = 49] = "_1";
                CharacterCodes[CharacterCodes["_2"] = 50] = "_2";
                CharacterCodes[CharacterCodes["_3"] = 51] = "_3";
                CharacterCodes[CharacterCodes["_4"] = 52] = "_4";
                CharacterCodes[CharacterCodes["_5"] = 53] = "_5";
                CharacterCodes[CharacterCodes["_6"] = 54] = "_6";
                CharacterCodes[CharacterCodes["_7"] = 55] = "_7";
                CharacterCodes[CharacterCodes["_8"] = 56] = "_8";
                CharacterCodes[CharacterCodes["_9"] = 57] = "_9";
                CharacterCodes[CharacterCodes["a"] = 97] = "a";
                CharacterCodes[CharacterCodes["b"] = 98] = "b";
                CharacterCodes[CharacterCodes["c"] = 99] = "c";
                CharacterCodes[CharacterCodes["d"] = 100] = "d";
                CharacterCodes[CharacterCodes["e"] = 101] = "e";
                CharacterCodes[CharacterCodes["f"] = 102] = "f";
                CharacterCodes[CharacterCodes["g"] = 103] = "g";
                CharacterCodes[CharacterCodes["h"] = 104] = "h";
                CharacterCodes[CharacterCodes["i"] = 105] = "i";
                CharacterCodes[CharacterCodes["j"] = 106] = "j";
                CharacterCodes[CharacterCodes["k"] = 107] = "k";
                CharacterCodes[CharacterCodes["l"] = 108] = "l";
                CharacterCodes[CharacterCodes["m"] = 109] = "m";
                CharacterCodes[CharacterCodes["n"] = 110] = "n";
                CharacterCodes[CharacterCodes["o"] = 111] = "o";
                CharacterCodes[CharacterCodes["p"] = 112] = "p";
                CharacterCodes[CharacterCodes["q"] = 113] = "q";
                CharacterCodes[CharacterCodes["r"] = 114] = "r";
                CharacterCodes[CharacterCodes["s"] = 115] = "s";
                CharacterCodes[CharacterCodes["t"] = 116] = "t";
                CharacterCodes[CharacterCodes["u"] = 117] = "u";
                CharacterCodes[CharacterCodes["v"] = 118] = "v";
                CharacterCodes[CharacterCodes["w"] = 119] = "w";
                CharacterCodes[CharacterCodes["x"] = 120] = "x";
                CharacterCodes[CharacterCodes["y"] = 121] = "y";
                CharacterCodes[CharacterCodes["z"] = 122] = "z";
                CharacterCodes[CharacterCodes["A"] = 65] = "A";
                CharacterCodes[CharacterCodes["B"] = 66] = "B";
                CharacterCodes[CharacterCodes["C"] = 67] = "C";
                CharacterCodes[CharacterCodes["D"] = 68] = "D";
                CharacterCodes[CharacterCodes["E"] = 69] = "E";
                CharacterCodes[CharacterCodes["F"] = 70] = "F";
                CharacterCodes[CharacterCodes["G"] = 71] = "G";
                CharacterCodes[CharacterCodes["H"] = 72] = "H";
                CharacterCodes[CharacterCodes["I"] = 73] = "I";
                CharacterCodes[CharacterCodes["J"] = 74] = "J";
                CharacterCodes[CharacterCodes["K"] = 75] = "K";
                CharacterCodes[CharacterCodes["L"] = 76] = "L";
                CharacterCodes[CharacterCodes["M"] = 77] = "M";
                CharacterCodes[CharacterCodes["N"] = 78] = "N";
                CharacterCodes[CharacterCodes["O"] = 79] = "O";
                CharacterCodes[CharacterCodes["P"] = 80] = "P";
                CharacterCodes[CharacterCodes["Q"] = 81] = "Q";
                CharacterCodes[CharacterCodes["R"] = 82] = "R";
                CharacterCodes[CharacterCodes["S"] = 83] = "S";
                CharacterCodes[CharacterCodes["T"] = 84] = "T";
                CharacterCodes[CharacterCodes["U"] = 85] = "U";
                CharacterCodes[CharacterCodes["V"] = 86] = "V";
                CharacterCodes[CharacterCodes["W"] = 87] = "W";
                CharacterCodes[CharacterCodes["X"] = 88] = "X";
                CharacterCodes[CharacterCodes["Y"] = 89] = "Y";
                CharacterCodes[CharacterCodes["Z"] = 90] = "Z";
                CharacterCodes[CharacterCodes["ampersand"] = 38] = "ampersand";
                CharacterCodes[CharacterCodes["asterisk"] = 42] = "asterisk";
                CharacterCodes[CharacterCodes["at"] = 64] = "at";
                CharacterCodes[CharacterCodes["backslash"] = 92] = "backslash";
                CharacterCodes[CharacterCodes["backtick"] = 96] = "backtick";
                CharacterCodes[CharacterCodes["bar"] = 124] = "bar";
                CharacterCodes[CharacterCodes["caret"] = 94] = "caret";
                CharacterCodes[CharacterCodes["closeBrace"] = 125] = "closeBrace";
                CharacterCodes[CharacterCodes["closeBracket"] = 93] = "closeBracket";
                CharacterCodes[CharacterCodes["closeParen"] = 41] = "closeParen";
                CharacterCodes[CharacterCodes["colon"] = 58] = "colon";
                CharacterCodes[CharacterCodes["comma"] = 44] = "comma";
                CharacterCodes[CharacterCodes["dot"] = 46] = "dot";
                CharacterCodes[CharacterCodes["doubleQuote"] = 34] = "doubleQuote";
                CharacterCodes[CharacterCodes["equals"] = 61] = "equals";
                CharacterCodes[CharacterCodes["exclamation"] = 33] = "exclamation";
                CharacterCodes[CharacterCodes["greaterThan"] = 62] = "greaterThan";
                CharacterCodes[CharacterCodes["hash"] = 35] = "hash";
                CharacterCodes[CharacterCodes["lessThan"] = 60] = "lessThan";
                CharacterCodes[CharacterCodes["minus"] = 45] = "minus";
                CharacterCodes[CharacterCodes["openBrace"] = 123] = "openBrace";
                CharacterCodes[CharacterCodes["openBracket"] = 91] = "openBracket";
                CharacterCodes[CharacterCodes["openParen"] = 40] = "openParen";
                CharacterCodes[CharacterCodes["percent"] = 37] = "percent";
                CharacterCodes[CharacterCodes["plus"] = 43] = "plus";
                CharacterCodes[CharacterCodes["question"] = 63] = "question";
                CharacterCodes[CharacterCodes["semicolon"] = 59] = "semicolon";
                CharacterCodes[CharacterCodes["singleQuote"] = 39] = "singleQuote";
                CharacterCodes[CharacterCodes["slash"] = 47] = "slash";
                CharacterCodes[CharacterCodes["tilde"] = 126] = "tilde";
                CharacterCodes[CharacterCodes["backspace"] = 8] = "backspace";
                CharacterCodes[CharacterCodes["formFeed"] = 12] = "formFeed";
                CharacterCodes[CharacterCodes["byteOrderMark"] = 65279] = "byteOrderMark";
                CharacterCodes[CharacterCodes["tab"] = 9] = "tab";
                CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab";
            })(ts.CharacterCodes || (ts.CharacterCodes = {}));
            var CharacterCodes = ts.CharacterCodes;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            (function (Ternary) {
                Ternary[Ternary["False"] = 0] = "False";
                Ternary[Ternary["Maybe"] = 1] = "Maybe";
                Ternary[Ternary["True"] = -1] = "True";
            })(ts.Ternary || (ts.Ternary = {}));
            var Ternary = ts.Ternary;
            (function (Comparison) {
                Comparison[Comparison["LessThan"] = -1] = "LessThan";
                Comparison[Comparison["EqualTo"] = 0] = "EqualTo";
                Comparison[Comparison["GreaterThan"] = 1] = "GreaterThan";
            })(ts.Comparison || (ts.Comparison = {}));
            var Comparison = ts.Comparison;
            function forEach(array, callback) {
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        var result = callback(array[i], i);
                        if (result) {
                            return result;
                        }
                    }
                }
                return undefined;
            }
            ts.forEach = forEach;
            function contains(array, value) {
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        if (array[i] === value) {
                            return true;
                        }
                    }
                }
                return false;
            }
            ts.contains = contains;
            function indexOf(array, value) {
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        if (array[i] === value) {
                            return i;
                        }
                    }
                }
                return -1;
            }
            ts.indexOf = indexOf;
            function countWhere(array, predicate) {
                var count = 0;
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        if (predicate(array[i])) {
                            count++;
                        }
                    }
                }
                return count;
            }
            ts.countWhere = countWhere;
            function filter(array, f) {
                if (array) {
                    var result = [];
                    for (var i = 0, len = array.length; i < len; i++) {
                        var item = array[i];
                        if (f(item)) {
                            result.push(item);
                        }
                    }
                }
                return result;
            }
            ts.filter = filter;
            function map(array, f) {
                if (array) {
                    var result = [];
                    for (var i = 0, len = array.length; i < len; i++) {
                        result.push(f(array[i]));
                    }
                }
                return result;
            }
            ts.map = map;
            function concatenate(array1, array2) {
                if (!array2 || !array2.length)
                    return array1;
                if (!array1 || !array1.length)
                    return array2;
                return array1.concat(array2);
            }
            ts.concatenate = concatenate;
            function deduplicate(array) {
                if (array) {
                    var result = [];
                    for (var i = 0, len = array.length; i < len; i++) {
                        var item = array[i];
                        if (!contains(result, item))
                            result.push(item);
                    }
                }
                return result;
            }
            ts.deduplicate = deduplicate;
            function sum(array, prop) {
                var result = 0;
                for (var i = 0; i < array.length; i++) {
                    result += array[i][prop];
                }
                return result;
            }
            ts.sum = sum;
            function addRange(to, from) {
                for (var i = 0, n = from.length; i < n; i++) {
                    to.push(from[i]);
                }
            }
            ts.addRange = addRange;
            function lastOrUndefined(array) {
                if (array.length === 0) {
                    return undefined;
                }
                return array[array.length - 1];
            }
            ts.lastOrUndefined = lastOrUndefined;
            function binarySearch(array, value) {
                var low = 0;
                var high = array.length - 1;
                while (low <= high) {
                    var middle = low + ((high - low) >> 1);
                    var midValue = array[middle];
                    if (midValue === value) {
                        return middle;
                    }
                    else if (midValue > value) {
                        high = middle - 1;
                    }
                    else {
                        low = middle + 1;
                    }
                }
                return ~low;
            }
            ts.binarySearch = binarySearch;
            var hasOwnProperty = Object.prototype.hasOwnProperty;
            function hasProperty(map, key) {
                return hasOwnProperty.call(map, key);
            }
            ts.hasProperty = hasProperty;
            function getProperty(map, key) {
                return hasOwnProperty.call(map, key) ? map[key] : undefined;
            }
            ts.getProperty = getProperty;
            function isEmpty(map) {
                for (var id in map) {
                    if (hasProperty(map, id)) {
                        return false;
                    }
                }
                return true;
            }
            ts.isEmpty = isEmpty;
            function clone(object) {
                var result = {};
                for (var id in object) {
                    result[id] = object[id];
                }
                return result;
            }
            ts.clone = clone;
            function extend(first, second) {
                var result = {};
                for (var id in first) {
                    result[id] = first[id];
                }
                for (var id in second) {
                    if (!hasProperty(result, id)) {
                        result[id] = second[id];
                    }
                }
                return result;
            }
            ts.extend = extend;
            function forEachValue(map, callback) {
                var result;
                for (var id in map) {
                    if (result = callback(map[id]))
                        break;
                }
                return result;
            }
            ts.forEachValue = forEachValue;
            function forEachKey(map, callback) {
                var result;
                for (var id in map) {
                    if (result = callback(id))
                        break;
                }
                return result;
            }
            ts.forEachKey = forEachKey;
            function lookUp(map, key) {
                return hasProperty(map, key) ? map[key] : undefined;
            }
            ts.lookUp = lookUp;
            function mapToArray(map) {
                var result = [];
                for (var id in map) {
                    result.push(map[id]);
                }
                return result;
            }
            ts.mapToArray = mapToArray;
            function copyMap(source, target) {
                for (var p in source) {
                    target[p] = source[p];
                }
            }
            ts.copyMap = copyMap;
            function arrayToMap(array, makeKey) {
                var result = {};
                forEach(array, function (value) {
                    result[makeKey(value)] = value;
                });
                return result;
            }
            ts.arrayToMap = arrayToMap;
            function formatStringFromArgs(text, args, baseIndex) {
                baseIndex = baseIndex || 0;
                return text.replace(/{(\d+)}/g, function (match, index) {
                    return args[+index + baseIndex];
                });
            }
            ts.localizedDiagnosticMessages = undefined;
            function getLocaleSpecificMessage(message) {
                return ts.localizedDiagnosticMessages && ts.localizedDiagnosticMessages[message] ? ts.localizedDiagnosticMessages[message] : message;
            }
            ts.getLocaleSpecificMessage = getLocaleSpecificMessage;
            function createFileDiagnostic(file, start, length, message) {
                var end = start + length;
                Debug.assert(start >= 0, "start must be non-negative, is " + start);
                Debug.assert(length >= 0, "length must be non-negative, is " + length);
                Debug.assert(start <= file.text.length, "start must be within the bounds of the file. " + start + " > " + file.text.length);
                Debug.assert(end <= file.text.length, "end must be the bounds of the file. " + end + " > " + file.text.length);
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 4) {
                    text = formatStringFromArgs(text, arguments, 4);
                }
                return {
                    file: file,
                    start: start,
                    length: length,
                    messageText: text,
                    category: message.category,
                    code: message.code
                };
            }
            ts.createFileDiagnostic = createFileDiagnostic;
            function createCompilerDiagnostic(message) {
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 1) {
                    text = formatStringFromArgs(text, arguments, 1);
                }
                return {
                    file: undefined,
                    start: undefined,
                    length: undefined,
                    messageText: text,
                    category: message.category,
                    code: message.code
                };
            }
            ts.createCompilerDiagnostic = createCompilerDiagnostic;
            function chainDiagnosticMessages(details, message) {
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 2) {
                    text = formatStringFromArgs(text, arguments, 2);
                }
                return {
                    messageText: text,
                    category: message.category,
                    code: message.code,
                    next: details
                };
            }
            ts.chainDiagnosticMessages = chainDiagnosticMessages;
            function concatenateDiagnosticMessageChains(headChain, tailChain) {
                Debug.assert(!headChain.next);
                headChain.next = tailChain;
                return headChain;
            }
            ts.concatenateDiagnosticMessageChains = concatenateDiagnosticMessageChains;
            function compareValues(a, b) {
                if (a === b)
                    return 0;
                if (a === undefined)
                    return -1;
                if (b === undefined)
                    return 1;
                return a < b ? -1 : 1;
            }
            ts.compareValues = compareValues;
            function getDiagnosticFileName(diagnostic) {
                return diagnostic.file ? diagnostic.file.fileName : undefined;
            }
            function compareDiagnostics(d1, d2) {
                return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) || compareValues(d1.start, d2.start) || compareValues(d1.length, d2.length) || compareValues(d1.code, d2.code) || compareMessageText(d1.messageText, d2.messageText) || 0;
            }
            ts.compareDiagnostics = compareDiagnostics;
            function compareMessageText(text1, text2) {
                while (text1 && text2) {
                    var string1 = typeof text1 === "string" ? text1 : text1.messageText;
                    var string2 = typeof text2 === "string" ? text2 : text2.messageText;
                    var res = compareValues(string1, string2);
                    if (res) {
                        return res;
                    }
                    text1 = typeof text1 === "string" ? undefined : text1.next;
                    text2 = typeof text2 === "string" ? undefined : text2.next;
                }
                if (!text1 && !text2) {
                    return 0;
                }
                return text1 ? 1 : -1;
            }
            function sortAndDeduplicateDiagnostics(diagnostics) {
                return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics));
            }
            ts.sortAndDeduplicateDiagnostics = sortAndDeduplicateDiagnostics;
            function deduplicateSortedDiagnostics(diagnostics) {
                if (diagnostics.length < 2) {
                    return diagnostics;
                }
                var newDiagnostics = [
                    diagnostics[0]
                ];
                var previousDiagnostic = diagnostics[0];
                for (var i = 1; i < diagnostics.length; i++) {
                    var currentDiagnostic = diagnostics[i];
                    var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === 0;
                    if (!isDupe) {
                        newDiagnostics.push(currentDiagnostic);
                        previousDiagnostic = currentDiagnostic;
                    }
                }
                return newDiagnostics;
            }
            ts.deduplicateSortedDiagnostics = deduplicateSortedDiagnostics;
            function normalizeSlashes(path) {
                return path.replace(/\\/g, "/");
            }
            ts.normalizeSlashes = normalizeSlashes;
            function getRootLength(path) {
                if (path.charCodeAt(0) === 47) {
                    if (path.charCodeAt(1) !== 47)
                        return 1;
                    var p1 = path.indexOf("/", 2);
                    if (p1 < 0)
                        return 2;
                    var p2 = path.indexOf("/", p1 + 1);
                    if (p2 < 0)
                        return p1 + 1;
                    return p2 + 1;
                }
                if (path.charCodeAt(1) === 58) {
                    if (path.charCodeAt(2) === 47)
                        return 3;
                    return 2;
                }
                return 0;
            }
            ts.getRootLength = getRootLength;
            ts.directorySeparator = "/";
            function getNormalizedParts(normalizedSlashedPath, rootLength) {
                var parts = normalizedSlashedPath.substr(rootLength).split(ts.directorySeparator);
                var normalized = [];
                for (var i = 0; i < parts.length; i++) {
                    var part = parts[i];
                    if (part !== ".") {
                        if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
                            normalized.pop();
                        }
                        else {
                            if (part) {
                                normalized.push(part);
                            }
                        }
                    }
                }
                return normalized;
            }
            function normalizePath(path) {
                var path = normalizeSlashes(path);
                var rootLength = getRootLength(path);
                var normalized = getNormalizedParts(path, rootLength);
                return path.substr(0, rootLength) + normalized.join(ts.directorySeparator);
            }
            ts.normalizePath = normalizePath;
            function getDirectoryPath(path) {
                return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(ts.directorySeparator)));
            }
            ts.getDirectoryPath = getDirectoryPath;
            function isUrl(path) {
                return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1;
            }
            ts.isUrl = isUrl;
            function isRootedDiskPath(path) {
                return getRootLength(path) !== 0;
            }
            ts.isRootedDiskPath = isRootedDiskPath;
            function normalizedPathComponents(path, rootLength) {
                var normalizedParts = getNormalizedParts(path, rootLength);
                return [
                    path.substr(0, rootLength)
                ].concat(normalizedParts);
            }
            function getNormalizedPathComponents(path, currentDirectory) {
                var path = normalizeSlashes(path);
                var rootLength = getRootLength(path);
                if (rootLength == 0) {
                    path = combinePaths(normalizeSlashes(currentDirectory), path);
                    rootLength = getRootLength(path);
                }
                return normalizedPathComponents(path, rootLength);
            }
            ts.getNormalizedPathComponents = getNormalizedPathComponents;
            function getNormalizedAbsolutePath(fileName, currentDirectory) {
                return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory));
            }
            ts.getNormalizedAbsolutePath = getNormalizedAbsolutePath;
            function getNormalizedPathFromPathComponents(pathComponents) {
                if (pathComponents && pathComponents.length) {
                    return pathComponents[0] + pathComponents.slice(1).join(ts.directorySeparator);
                }
            }
            ts.getNormalizedPathFromPathComponents = getNormalizedPathFromPathComponents;
            function getNormalizedPathComponentsOfUrl(url) {
                var urlLength = url.length;
                var rootLength = url.indexOf("://") + "://".length;
                while (rootLength < urlLength) {
                    if (url.charCodeAt(rootLength) === 47) {
                        rootLength++;
                    }
                    else {
                        break;
                    }
                }
                if (rootLength === urlLength) {
                    return [
                        url
                    ];
                }
                var indexOfNextSlash = url.indexOf(ts.directorySeparator, rootLength);
                if (indexOfNextSlash !== -1) {
                    rootLength = indexOfNextSlash + 1;
                    return normalizedPathComponents(url, rootLength);
                }
                else {
                    return [
                        url + ts.directorySeparator
                    ];
                }
            }
            function getNormalizedPathOrUrlComponents(pathOrUrl, currentDirectory) {
                if (isUrl(pathOrUrl)) {
                    return getNormalizedPathComponentsOfUrl(pathOrUrl);
                }
                else {
                    return getNormalizedPathComponents(pathOrUrl, currentDirectory);
                }
            }
            function getRelativePathToDirectoryOrUrl(directoryPathOrUrl, relativeOrAbsolutePath, currentDirectory, getCanonicalFileName, isAbsolutePathAnUrl) {
                var pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
                var directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
                if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
                    directoryComponents.length--;
                }
                for (var joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
                    if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
                        break;
                    }
                }
                if (joinStartIndex) {
                    var relativePath = "";
                    var relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
                    for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
                        if (directoryComponents[joinStartIndex] !== "") {
                            relativePath = relativePath + ".." + ts.directorySeparator;
                        }
                    }
                    return relativePath + relativePathComponents.join(ts.directorySeparator);
                }
                var absolutePath = getNormalizedPathFromPathComponents(pathComponents);
                if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
                    absolutePath = "file:///" + absolutePath;
                }
                return absolutePath;
            }
            ts.getRelativePathToDirectoryOrUrl = getRelativePathToDirectoryOrUrl;
            function getBaseFileName(path) {
                var i = path.lastIndexOf(ts.directorySeparator);
                return i < 0 ? path : path.substring(i + 1);
            }
            ts.getBaseFileName = getBaseFileName;
            function combinePaths(path1, path2) {
                if (!(path1 && path1.length))
                    return path2;
                if (!(path2 && path2.length))
                    return path1;
                if (getRootLength(path2) !== 0)
                    return path2;
                if (path1.charAt(path1.length - 1) === ts.directorySeparator)
                    return path1 + path2;
                return path1 + ts.directorySeparator + path2;
            }
            ts.combinePaths = combinePaths;
            function fileExtensionIs(path, extension) {
                var pathLen = path.length;
                var extLen = extension.length;
                return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
            }
            ts.fileExtensionIs = fileExtensionIs;
            var supportedExtensions = [
                ".d.ts",
                ".ts",
                ".js"
            ];
            function removeFileExtension(path) {
                for (var i = 0; i < supportedExtensions.length; i++) {
                    var ext = supportedExtensions[i];
                    if (fileExtensionIs(path, ext)) {
                        return path.substr(0, path.length - ext.length);
                    }
                }
                return path;
            }
            ts.removeFileExtension = removeFileExtension;
            var backslashOrDoubleQuote = /[\"\\]/g;
            var escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
            var escapedCharsMap = {
                "\0": "\\0",
                "\t": "\\t",
                "\v": "\\v",
                "\f": "\\f",
                "\b": "\\b",
                "\r": "\\r",
                "\n": "\\n",
                "\\": "\\\\",
                "\"": "\\\"",
                "\u2028": "\\u2028",
                "\u2029": "\\u2029",
                "\u0085": "\\u0085"
            };
            function getDefaultLibFileName(options) {
                return options.target === 2 ? "lib.es6.d.ts" : "lib.d.ts";
            }
            ts.getDefaultLibFileName = getDefaultLibFileName;
            function Symbol(flags, name) {
                this.flags = flags;
                this.name = name;
                this.declarations = undefined;
            }
            function Type(checker, flags) {
                this.flags = flags;
            }
            function Signature(checker) {
            }
            ts.objectAllocator = {
                getNodeConstructor: function (kind) {
                    function Node() {
                    }
                    Node.prototype = {
                        kind: kind,
                        pos: 0,
                        end: 0,
                        flags: 0,
                        parent: undefined
                    };
                    return Node;
                },
                getSymbolConstructor: function () {
                    return Symbol;
                },
                getTypeConstructor: function () {
                    return Type;
                },
                getSignatureConstructor: function () {
                    return Signature;
                }
            };
            (function (AssertionLevel) {
                AssertionLevel[AssertionLevel["None"] = 0] = "None";
                AssertionLevel[AssertionLevel["Normal"] = 1] = "Normal";
                AssertionLevel[AssertionLevel["Aggressive"] = 2] = "Aggressive";
                AssertionLevel[AssertionLevel["VeryAggressive"] = 3] = "VeryAggressive";
            })(ts.AssertionLevel || (ts.AssertionLevel = {}));
            var AssertionLevel = ts.AssertionLevel;
            var Debug;
            (function (Debug) {
                var currentAssertionLevel = 0;
                function shouldAssert(level) {
                    return currentAssertionLevel >= level;
                }
                Debug.shouldAssert = shouldAssert;
                function assert(expression, message, verboseDebugInfo) {
                    if (!expression) {
                        var verboseDebugString = "";
                        if (verboseDebugInfo) {
                            verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
                        }
                        throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
                    }
                }
                Debug.assert = assert;
                function fail(message) {
                    Debug.assert(false, message);
                }
                Debug.fail = fail;
            })(Debug = ts.Debug || (ts.Debug = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            ts.sys = (function () {
                function getWScriptSystem() {
                    var fso = new ActiveXObject("Scripting.FileSystemObject");
                    var fileStream = new ActiveXObject("ADODB.Stream");
                    fileStream.Type = 2;
                    var binaryStream = new ActiveXObject("ADODB.Stream");
                    binaryStream.Type = 1;
                    var args = [];
                    for (var i = 0; i < WScript.Arguments.length; i++) {
                        args[i] = WScript.Arguments.Item(i);
                    }
                    function readFile(fileName, encoding) {
                        if (!fso.FileExists(fileName)) {
                            return undefined;
                        }
                        fileStream.Open();
                        try {
                            if (encoding) {
                                fileStream.Charset = encoding;
                                fileStream.LoadFromFile(fileName);
                            }
                            else {
                                fileStream.Charset = "x-ansi";
                                fileStream.LoadFromFile(fileName);
                                var bom = fileStream.ReadText(2) || "";
                                fileStream.Position = 0;
                                fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
                            }
                            return fileStream.ReadText();
                        }
                        catch (e) {
                            throw e;
                        }
                        finally {
                            fileStream.Close();
                        }
                    }
                    function writeFile(fileName, data, writeByteOrderMark) {
                        fileStream.Open();
                        binaryStream.Open();
                        try {
                            fileStream.Charset = "utf-8";
                            fileStream.WriteText(data);
                            if (writeByteOrderMark) {
                                fileStream.Position = 0;
                            }
                            else {
                                fileStream.Position = 3;
                            }
                            fileStream.CopyTo(binaryStream);
                            binaryStream.SaveToFile(fileName, 2);
                        }
                        finally {
                            binaryStream.Close();
                            fileStream.Close();
                        }
                    }
                    function getNames(collection) {
                        var result = [];
                        for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
                            result.push(e.item().Name);
                        }
                        return result.sort();
                    }
                    function readDirectory(path, extension) {
                        var result = [];
                        visitDirectory(path);
                        return result;
                        function visitDirectory(path) {
                            var folder = fso.GetFolder(path || ".");
                            var files = getNames(folder.files);
                            for (var i = 0; i < files.length; i++) {
                                var name = files[i];
                                if (!extension || ts.fileExtensionIs(name, extension)) {
                                    result.push(ts.combinePaths(path, name));
                                }
                            }
                            var subfolders = getNames(folder.subfolders);
                            for (var i = 0; i < subfolders.length; i++) {
                                visitDirectory(ts.combinePaths(path, subfolders[i]));
                            }
                        }
                    }
                    return {
                        args: args,
                        newLine: "\r\n",
                        useCaseSensitiveFileNames: false,
                        write: function (s) {
                            WScript.StdOut.Write(s);
                        },
                        readFile: readFile,
                        writeFile: writeFile,
                        resolvePath: function (path) {
                            return fso.GetAbsolutePathName(path);
                        },
                        fileExists: function (path) {
                            return fso.FileExists(path);
                        },
                        directoryExists: function (path) {
                            return fso.FolderExists(path);
                        },
                        createDirectory: function (directoryName) {
                            if (!this.directoryExists(directoryName)) {
                                fso.CreateFolder(directoryName);
                            }
                        },
                        getExecutingFilePath: function () {
                            return WScript.ScriptFullName;
                        },
                        getCurrentDirectory: function () {
                            return new ActiveXObject("WScript.Shell").CurrentDirectory;
                        },
                        readDirectory: readDirectory,
                        exit: function (exitCode) {
                            try {
                                WScript.Quit(exitCode);
                            }
                            catch (e) {
                            }
                        }
                    };
                }
                function getNodeSystem() {
                    var _fs = require("fs");
                    var _path = require("path");
                    var _os = require('os');
                    var platform = _os.platform();
                    var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
                    function readFile(fileName, encoding) {
                        if (!_fs.existsSync(fileName)) {
                            return undefined;
                        }
                        var buffer = _fs.readFileSync(fileName);
                        var len = buffer.length;
                        if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
                            len &= ~1;
                            for (var i = 0; i < len; i += 2) {
                                var temp = buffer[i];
                                buffer[i] = buffer[i + 1];
                                buffer[i + 1] = temp;
                            }
                            return buffer.toString("utf16le", 2);
                        }
                        if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
                            return buffer.toString("utf16le", 2);
                        }
                        if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
                            return buffer.toString("utf8", 3);
                        }
                        return buffer.toString("utf8");
                    }
                    function writeFile(fileName, data, writeByteOrderMark) {
                        if (writeByteOrderMark) {
                            data = '\uFEFF' + data;
                        }
                        _fs.writeFileSync(fileName, data, "utf8");
                    }
                    function readDirectory(path, extension) {
                        var result = [];
                        visitDirectory(path);
                        return result;
                        function visitDirectory(path) {
                            var files = _fs.readdirSync(path || ".").sort();
                            var directories = [];
                            for (var i = 0; i < files.length; i++) {
                                var name = ts.combinePaths(path, files[i]);
                                var stat = _fs.lstatSync(name);
                                if (stat.isFile()) {
                                    if (!extension || ts.fileExtensionIs(name, extension)) {
                                        result.push(name);
                                    }
                                }
                                else if (stat.isDirectory()) {
                                    directories.push(name);
                                }
                            }
                            for (var i = 0; i < directories.length; i++) {
                                visitDirectory(directories[i]);
                            }
                        }
                    }
                    return {
                        args: process.argv.slice(2),
                        newLine: _os.EOL,
                        useCaseSensitiveFileNames: useCaseSensitiveFileNames,
                        write: function (s) {
                            _fs.writeSync(1, s);
                        },
                        readFile: readFile,
                        writeFile: writeFile,
                        watchFile: function (fileName, callback) {
                            _fs.watchFile(fileName, {
                                persistent: true,
                                interval: 250
                            }, fileChanged);
                            return {
                                close: function () {
                                    _fs.unwatchFile(fileName, fileChanged);
                                }
                            };
                            function fileChanged(curr, prev) {
                                if (+curr.mtime <= +prev.mtime) {
                                    return;
                                }
                                callback(fileName);
                            }
                            ;
                        },
                        resolvePath: function (path) {
                            return _path.resolve(path);
                        },
                        fileExists: function (path) {
                            return _fs.existsSync(path);
                        },
                        directoryExists: function (path) {
                            return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
                        },
                        createDirectory: function (directoryName) {
                            if (!this.directoryExists(directoryName)) {
                                _fs.mkdirSync(directoryName);
                            }
                        },
                        getExecutingFilePath: function () {
                            return __filename;
                        },
                        getCurrentDirectory: function () {
                            return process.cwd();
                        },
                        readDirectory: readDirectory,
                        getMemoryUsage: function () {
                            if (global.gc) {
                                global.gc();
                            }
                            return process.memoryUsage().heapUsed;
                        },
                        exit: function (exitCode) {
                            process.exit(exitCode);
                        }
                    };
                }
                if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
                    return getWScriptSystem();
                }
                else if (typeof module !== "undefined" && module.exports) {
                    return getNodeSystem();
                }
                else {
                    return undefined;
                }
            })();
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            ts.Diagnostics = {
                Unterminated_string_literal: {
                    code: 1002,
                    category: 1,
                    key: "Unterminated string literal."
                },
                Identifier_expected: {
                    code: 1003,
                    category: 1,
                    key: "Identifier expected."
                },
                _0_expected: {
                    code: 1005,
                    category: 1,
                    key: "'{0}' expected."
                },
                A_file_cannot_have_a_reference_to_itself: {
                    code: 1006,
                    category: 1,
                    key: "A file cannot have a reference to itself."
                },
                Trailing_comma_not_allowed: {
                    code: 1009,
                    category: 1,
                    key: "Trailing comma not allowed."
                },
                Asterisk_Slash_expected: {
                    code: 1010,
                    category: 1,
                    key: "'*/' expected."
                },
                Unexpected_token: {
                    code: 1012,
                    category: 1,
                    key: "Unexpected token."
                },
                A_rest_parameter_must_be_last_in_a_parameter_list: {
                    code: 1014,
                    category: 1,
                    key: "A rest parameter must be last in a parameter list."
                },
                Parameter_cannot_have_question_mark_and_initializer: {
                    code: 1015,
                    category: 1,
                    key: "Parameter cannot have question mark and initializer."
                },
                A_required_parameter_cannot_follow_an_optional_parameter: {
                    code: 1016,
                    category: 1,
                    key: "A required parameter cannot follow an optional parameter."
                },
                An_index_signature_cannot_have_a_rest_parameter: {
                    code: 1017,
                    category: 1,
                    key: "An index signature cannot have a rest parameter."
                },
                An_index_signature_parameter_cannot_have_an_accessibility_modifier: {
                    code: 1018,
                    category: 1,
                    key: "An index signature parameter cannot have an accessibility modifier."
                },
                An_index_signature_parameter_cannot_have_a_question_mark: {
                    code: 1019,
                    category: 1,
                    key: "An index signature parameter cannot have a question mark."
                },
                An_index_signature_parameter_cannot_have_an_initializer: {
                    code: 1020,
                    category: 1,
                    key: "An index signature parameter cannot have an initializer."
                },
                An_index_signature_must_have_a_type_annotation: {
                    code: 1021,
                    category: 1,
                    key: "An index signature must have a type annotation."
                },
                An_index_signature_parameter_must_have_a_type_annotation: {
                    code: 1022,
                    category: 1,
                    key: "An index signature parameter must have a type annotation."
                },
                An_index_signature_parameter_type_must_be_string_or_number: {
                    code: 1023,
                    category: 1,
                    key: "An index signature parameter type must be 'string' or 'number'."
                },
                A_class_or_interface_declaration_can_only_have_one_extends_clause: {
                    code: 1024,
                    category: 1,
                    key: "A class or interface declaration can only have one 'extends' clause."
                },
                An_extends_clause_must_precede_an_implements_clause: {
                    code: 1025,
                    category: 1,
                    key: "An 'extends' clause must precede an 'implements' clause."
                },
                A_class_can_only_extend_a_single_class: {
                    code: 1026,
                    category: 1,
                    key: "A class can only extend a single class."
                },
                A_class_declaration_can_only_have_one_implements_clause: {
                    code: 1027,
                    category: 1,
                    key: "A class declaration can only have one 'implements' clause."
                },
                Accessibility_modifier_already_seen: {
                    code: 1028,
                    category: 1,
                    key: "Accessibility modifier already seen."
                },
                _0_modifier_must_precede_1_modifier: {
                    code: 1029,
                    category: 1,
                    key: "'{0}' modifier must precede '{1}' modifier."
                },
                _0_modifier_already_seen: {
                    code: 1030,
                    category: 1,
                    key: "'{0}' modifier already seen."
                },
                _0_modifier_cannot_appear_on_a_class_element: {
                    code: 1031,
                    category: 1,
                    key: "'{0}' modifier cannot appear on a class element."
                },
                An_interface_declaration_cannot_have_an_implements_clause: {
                    code: 1032,
                    category: 1,
                    key: "An interface declaration cannot have an 'implements' clause."
                },
                super_must_be_followed_by_an_argument_list_or_member_access: {
                    code: 1034,
                    category: 1,
                    key: "'super' must be followed by an argument list or member access."
                },
                Only_ambient_modules_can_use_quoted_names: {
                    code: 1035,
                    category: 1,
                    key: "Only ambient modules can use quoted names."
                },
                Statements_are_not_allowed_in_ambient_contexts: {
                    code: 1036,
                    category: 1,
                    key: "Statements are not allowed in ambient contexts."
                },
                A_declare_modifier_cannot_be_used_in_an_already_ambient_context: {
                    code: 1038,
                    category: 1,
                    key: "A 'declare' modifier cannot be used in an already ambient context."
                },
                Initializers_are_not_allowed_in_ambient_contexts: {
                    code: 1039,
                    category: 1,
                    key: "Initializers are not allowed in ambient contexts."
                },
                _0_modifier_cannot_appear_on_a_module_element: {
                    code: 1044,
                    category: 1,
                    key: "'{0}' modifier cannot appear on a module element."
                },
                A_declare_modifier_cannot_be_used_with_an_interface_declaration: {
                    code: 1045,
                    category: 1,
                    key: "A 'declare' modifier cannot be used with an interface declaration."
                },
                A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: {
                    code: 1046,
                    category: 1,
                    key: "A 'declare' modifier is required for a top level declaration in a .d.ts file."
                },
                A_rest_parameter_cannot_be_optional: {
                    code: 1047,
                    category: 1,
                    key: "A rest parameter cannot be optional."
                },
                A_rest_parameter_cannot_have_an_initializer: {
                    code: 1048,
                    category: 1,
                    key: "A rest parameter cannot have an initializer."
                },
                A_set_accessor_must_have_exactly_one_parameter: {
                    code: 1049,
                    category: 1,
                    key: "A 'set' accessor must have exactly one parameter."
                },
                A_set_accessor_cannot_have_an_optional_parameter: {
                    code: 1051,
                    category: 1,
                    key: "A 'set' accessor cannot have an optional parameter."
                },
                A_set_accessor_parameter_cannot_have_an_initializer: {
                    code: 1052,
                    category: 1,
                    key: "A 'set' accessor parameter cannot have an initializer."
                },
                A_set_accessor_cannot_have_rest_parameter: {
                    code: 1053,
                    category: 1,
                    key: "A 'set' accessor cannot have rest parameter."
                },
                A_get_accessor_cannot_have_parameters: {
                    code: 1054,
                    category: 1,
                    key: "A 'get' accessor cannot have parameters."
                },
                Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: {
                    code: 1056,
                    category: 1,
                    key: "Accessors are only available when targeting ECMAScript 5 and higher."
                },
                Enum_member_must_have_initializer: {
                    code: 1061,
                    category: 1,
                    key: "Enum member must have initializer."
                },
                An_export_assignment_cannot_be_used_in_an_internal_module: {
                    code: 1063,
                    category: 1,
                    key: "An export assignment cannot be used in an internal module."
                },
                Ambient_enum_elements_can_only_have_integer_literal_initializers: {
                    code: 1066,
                    category: 1,
                    key: "Ambient enum elements can only have integer literal initializers."
                },
                Unexpected_token_A_constructor_method_accessor_or_property_was_expected: {
                    code: 1068,
                    category: 1,
                    key: "Unexpected token. A constructor, method, accessor, or property was expected."
                },
                A_declare_modifier_cannot_be_used_with_an_import_declaration: {
                    code: 1079,
                    category: 1,
                    key: "A 'declare' modifier cannot be used with an import declaration."
                },
                Invalid_reference_directive_syntax: {
                    code: 1084,
                    category: 1,
                    key: "Invalid 'reference' directive syntax."
                },
                Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: {
                    code: 1085,
                    category: 1,
                    key: "Octal literals are not available when targeting ECMAScript 5 and higher."
                },
                An_accessor_cannot_be_declared_in_an_ambient_context: {
                    code: 1086,
                    category: 1,
                    key: "An accessor cannot be declared in an ambient context."
                },
                _0_modifier_cannot_appear_on_a_constructor_declaration: {
                    code: 1089,
                    category: 1,
                    key: "'{0}' modifier cannot appear on a constructor declaration."
                },
                _0_modifier_cannot_appear_on_a_parameter: {
                    code: 1090,
                    category: 1,
                    key: "'{0}' modifier cannot appear on a parameter."
                },
                Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: {
                    code: 1091,
                    category: 1,
                    key: "Only a single variable declaration is allowed in a 'for...in' statement."
                },
                Type_parameters_cannot_appear_on_a_constructor_declaration: {
                    code: 1092,
                    category: 1,
                    key: "Type parameters cannot appear on a constructor declaration."
                },
                Type_annotation_cannot_appear_on_a_constructor_declaration: {
                    code: 1093,
                    category: 1,
                    key: "Type annotation cannot appear on a constructor declaration."
                },
                An_accessor_cannot_have_type_parameters: {
                    code: 1094,
                    category: 1,
                    key: "An accessor cannot have type parameters."
                },
                A_set_accessor_cannot_have_a_return_type_annotation: {
                    code: 1095,
                    category: 1,
                    key: "A 'set' accessor cannot have a return type annotation."
                },
                An_index_signature_must_have_exactly_one_parameter: {
                    code: 1096,
                    category: 1,
                    key: "An index signature must have exactly one parameter."
                },
                _0_list_cannot_be_empty: {
                    code: 1097,
                    category: 1,
                    key: "'{0}' list cannot be empty."
                },
                Type_parameter_list_cannot_be_empty: {
                    code: 1098,
                    category: 1,
                    key: "Type parameter list cannot be empty."
                },
                Type_argument_list_cannot_be_empty: {
                    code: 1099,
                    category: 1,
                    key: "Type argument list cannot be empty."
                },
                Invalid_use_of_0_in_strict_mode: {
                    code: 1100,
                    category: 1,
                    key: "Invalid use of '{0}' in strict mode."
                },
                with_statements_are_not_allowed_in_strict_mode: {
                    code: 1101,
                    category: 1,
                    key: "'with' statements are not allowed in strict mode."
                },
                delete_cannot_be_called_on_an_identifier_in_strict_mode: {
                    code: 1102,
                    category: 1,
                    key: "'delete' cannot be called on an identifier in strict mode."
                },
                A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: {
                    code: 1104,
                    category: 1,
                    key: "A 'continue' statement can only be used within an enclosing iteration statement."
                },
                A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: {
                    code: 1105,
                    category: 1,
                    key: "A 'break' statement can only be used within an enclosing iteration or switch statement."
                },
                Jump_target_cannot_cross_function_boundary: {
                    code: 1107,
                    category: 1,
                    key: "Jump target cannot cross function boundary."
                },
                A_return_statement_can_only_be_used_within_a_function_body: {
                    code: 1108,
                    category: 1,
                    key: "A 'return' statement can only be used within a function body."
                },
                Expression_expected: {
                    code: 1109,
                    category: 1,
                    key: "Expression expected."
                },
                Type_expected: {
                    code: 1110,
                    category: 1,
                    key: "Type expected."
                },
                A_class_member_cannot_be_declared_optional: {
                    code: 1112,
                    category: 1,
                    key: "A class member cannot be declared optional."
                },
                A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: {
                    code: 1113,
                    category: 1,
                    key: "A 'default' clause cannot appear more than once in a 'switch' statement."
                },
                Duplicate_label_0: {
                    code: 1114,
                    category: 1,
                    key: "Duplicate label '{0}'"
                },
                A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement: {
                    code: 1115,
                    category: 1,
                    key: "A 'continue' statement can only jump to a label of an enclosing iteration statement."
                },
                A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement: {
                    code: 1116,
                    category: 1,
                    key: "A 'break' statement can only jump to a label of an enclosing statement."
                },
                An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode: {
                    code: 1117,
                    category: 1,
                    key: "An object literal cannot have multiple properties with the same name in strict mode."
                },
                An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: {
                    code: 1118,
                    category: 1,
                    key: "An object literal cannot have multiple get/set accessors with the same name."
                },
                An_object_literal_cannot_have_property_and_accessor_with_the_same_name: {
                    code: 1119,
                    category: 1,
                    key: "An object literal cannot have property and accessor with the same name."
                },
                An_export_assignment_cannot_have_modifiers: {
                    code: 1120,
                    category: 1,
                    key: "An export assignment cannot have modifiers."
                },
                Octal_literals_are_not_allowed_in_strict_mode: {
                    code: 1121,
                    category: 1,
                    key: "Octal literals are not allowed in strict mode."
                },
                A_tuple_type_element_list_cannot_be_empty: {
                    code: 1122,
                    category: 1,
                    key: "A tuple type element list cannot be empty."
                },
                Variable_declaration_list_cannot_be_empty: {
                    code: 1123,
                    category: 1,
                    key: "Variable declaration list cannot be empty."
                },
                Digit_expected: {
                    code: 1124,
                    category: 1,
                    key: "Digit expected."
                },
                Hexadecimal_digit_expected: {
                    code: 1125,
                    category: 1,
                    key: "Hexadecimal digit expected."
                },
                Unexpected_end_of_text: {
                    code: 1126,
                    category: 1,
                    key: "Unexpected end of text."
                },
                Invalid_character: {
                    code: 1127,
                    category: 1,
                    key: "Invalid character."
                },
                Declaration_or_statement_expected: {
                    code: 1128,
                    category: 1,
                    key: "Declaration or statement expected."
                },
                Statement_expected: {
                    code: 1129,
                    category: 1,
                    key: "Statement expected."
                },
                case_or_default_expected: {
                    code: 1130,
                    category: 1,
                    key: "'case' or 'default' expected."
                },
                Property_or_signature_expected: {
                    code: 1131,
                    category: 1,
                    key: "Property or signature expected."
                },
                Enum_member_expected: {
                    code: 1132,
                    category: 1,
                    key: "Enum member expected."
                },
                Type_reference_expected: {
                    code: 1133,
                    category: 1,
                    key: "Type reference expected."
                },
                Variable_declaration_expected: {
                    code: 1134,
                    category: 1,
                    key: "Variable declaration expected."
                },
                Argument_expression_expected: {
                    code: 1135,
                    category: 1,
                    key: "Argument expression expected."
                },
                Property_assignment_expected: {
                    code: 1136,
                    category: 1,
                    key: "Property assignment expected."
                },
                Expression_or_comma_expected: {
                    code: 1137,
                    category: 1,
                    key: "Expression or comma expected."
                },
                Parameter_declaration_expected: {
                    code: 1138,
                    category: 1,
                    key: "Parameter declaration expected."
                },
                Type_parameter_declaration_expected: {
                    code: 1139,
                    category: 1,
                    key: "Type parameter declaration expected."
                },
                Type_argument_expected: {
                    code: 1140,
                    category: 1,
                    key: "Type argument expected."
                },
                String_literal_expected: {
                    code: 1141,
                    category: 1,
                    key: "String literal expected."
                },
                Line_break_not_permitted_here: {
                    code: 1142,
                    category: 1,
                    key: "Line break not permitted here."
                },
                or_expected: {
                    code: 1144,
                    category: 1,
                    key: "'{' or ';' expected."
                },
                Modifiers_not_permitted_on_index_signature_members: {
                    code: 1145,
                    category: 1,
                    key: "Modifiers not permitted on index signature members."
                },
                Declaration_expected: {
                    code: 1146,
                    category: 1,
                    key: "Declaration expected."
                },
                Import_declarations_in_an_internal_module_cannot_reference_an_external_module: {
                    code: 1147,
                    category: 1,
                    key: "Import declarations in an internal module cannot reference an external module."
                },
                Cannot_compile_external_modules_unless_the_module_flag_is_provided: {
                    code: 1148,
                    category: 1,
                    key: "Cannot compile external modules unless the '--module' flag is provided."
                },
                File_name_0_differs_from_already_included_file_name_1_only_in_casing: {
                    code: 1149,
                    category: 1,
                    key: "File name '{0}' differs from already included file name '{1}' only in casing"
                },
                new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: {
                    code: 1150,
                    category: 1,
                    key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead."
                },
                var_let_or_const_expected: {
                    code: 1152,
                    category: 1,
                    key: "'var', 'let' or 'const' expected."
                },
                let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: {
                    code: 1153,
                    category: 1,
                    key: "'let' declarations are only available when targeting ECMAScript 6 and higher."
                },
                const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: {
                    code: 1154,
                    category: 1,
                    key: "'const' declarations are only available when targeting ECMAScript 6 and higher."
                },
                const_declarations_must_be_initialized: {
                    code: 1155,
                    category: 1,
                    key: "'const' declarations must be initialized"
                },
                const_declarations_can_only_be_declared_inside_a_block: {
                    code: 1156,
                    category: 1,
                    key: "'const' declarations can only be declared inside a block."
                },
                let_declarations_can_only_be_declared_inside_a_block: {
                    code: 1157,
                    category: 1,
                    key: "'let' declarations can only be declared inside a block."
                },
                Unterminated_template_literal: {
                    code: 1160,
                    category: 1,
                    key: "Unterminated template literal."
                },
                Unterminated_regular_expression_literal: {
                    code: 1161,
                    category: 1,
                    key: "Unterminated regular expression literal."
                },
                An_object_member_cannot_be_declared_optional: {
                    code: 1162,
                    category: 1,
                    key: "An object member cannot be declared optional."
                },
                yield_expression_must_be_contained_within_a_generator_declaration: {
                    code: 1163,
                    category: 1,
                    key: "'yield' expression must be contained_within a generator declaration."
                },
                Computed_property_names_are_not_allowed_in_enums: {
                    code: 1164,
                    category: 1,
                    key: "Computed property names are not allowed in enums."
                },
                A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: {
                    code: 1165,
                    category: 1,
                    key: "A computed property name in an ambient context must directly refer to a built-in symbol."
                },
                A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: {
                    code: 1166,
                    category: 1,
                    key: "A computed property name in a class property declaration must directly refer to a built-in symbol."
                },
                Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: {
                    code: 1167,
                    category: 1,
                    key: "Computed property names are only available when targeting ECMAScript 6 and higher."
                },
                A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol: {
                    code: 1168,
                    category: 1,
                    key: "A computed property name in a method overload must directly refer to a built-in symbol."
                },
                A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol: {
                    code: 1169,
                    category: 1,
                    key: "A computed property name in an interface must directly refer to a built-in symbol."
                },
                A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol: {
                    code: 1170,
                    category: 1,
                    key: "A computed property name in a type literal must directly refer to a built-in symbol."
                },
                A_comma_expression_is_not_allowed_in_a_computed_property_name: {
                    code: 1171,
                    category: 1,
                    key: "A comma expression is not allowed in a computed property name."
                },
                extends_clause_already_seen: {
                    code: 1172,
                    category: 1,
                    key: "'extends' clause already seen."
                },
                extends_clause_must_precede_implements_clause: {
                    code: 1173,
                    category: 1,
                    key: "'extends' clause must precede 'implements' clause."
                },
                Classes_can_only_extend_a_single_class: {
                    code: 1174,
                    category: 1,
                    key: "Classes can only extend a single class."
                },
                implements_clause_already_seen: {
                    code: 1175,
                    category: 1,
                    key: "'implements' clause already seen."
                },
                Interface_declaration_cannot_have_implements_clause: {
                    code: 1176,
                    category: 1,
                    key: "Interface declaration cannot have 'implements' clause."
                },
                Binary_digit_expected: {
                    code: 1177,
                    category: 1,
                    key: "Binary digit expected."
                },
                Octal_digit_expected: {
                    code: 1178,
                    category: 1,
                    key: "Octal digit expected."
                },
                Unexpected_token_expected: {
                    code: 1179,
                    category: 1,
                    key: "Unexpected token. '{' expected."
                },
                Property_destructuring_pattern_expected: {
                    code: 1180,
                    category: 1,
                    key: "Property destructuring pattern expected."
                },
                Array_element_destructuring_pattern_expected: {
                    code: 1181,
                    category: 1,
                    key: "Array element destructuring pattern expected."
                },
                A_destructuring_declaration_must_have_an_initializer: {
                    code: 1182,
                    category: 1,
                    key: "A destructuring declaration must have an initializer."
                },
                Destructuring_declarations_are_not_allowed_in_ambient_contexts: {
                    code: 1183,
                    category: 1,
                    key: "Destructuring declarations are not allowed in ambient contexts."
                },
                An_implementation_cannot_be_declared_in_ambient_contexts: {
                    code: 1184,
                    category: 1,
                    key: "An implementation cannot be declared in ambient contexts."
                },
                Modifiers_cannot_appear_here: {
                    code: 1184,
                    category: 1,
                    key: "Modifiers cannot appear here."
                },
                Merge_conflict_marker_encountered: {
                    code: 1185,
                    category: 1,
                    key: "Merge conflict marker encountered."
                },
                A_rest_element_cannot_have_an_initializer: {
                    code: 1186,
                    category: 1,
                    key: "A rest element cannot have an initializer."
                },
                A_parameter_property_may_not_be_a_binding_pattern: {
                    code: 1187,
                    category: 1,
                    key: "A parameter property may not be a binding pattern."
                },
                Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement: {
                    code: 1188,
                    category: 1,
                    key: "Only a single variable declaration is allowed in a 'for...of' statement."
                },
                The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer: {
                    code: 1189,
                    category: 1,
                    key: "The variable declaration of a 'for...in' statement cannot have an initializer."
                },
                The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer: {
                    code: 1190,
                    category: 1,
                    key: "The variable declaration of a 'for...of' statement cannot have an initializer."
                },
                An_import_declaration_cannot_have_modifiers: {
                    code: 1191,
                    category: 1,
                    key: "An import declaration cannot have modifiers."
                },
                External_module_0_has_no_default_export_or_export_assignment: {
                    code: 1192,
                    category: 1,
                    key: "External module '{0}' has no default export or export assignment."
                },
                An_export_declaration_cannot_have_modifiers: {
                    code: 1193,
                    category: 1,
                    key: "An export declaration cannot have modifiers."
                },
                Export_declarations_are_not_permitted_in_an_internal_module: {
                    code: 1194,
                    category: 1,
                    key: "Export declarations are not permitted in an internal module."
                },
                Catch_clause_variable_name_must_be_an_identifier: {
                    code: 1195,
                    category: 1,
                    key: "Catch clause variable name must be an identifier."
                },
                Catch_clause_variable_cannot_have_a_type_annotation: {
                    code: 1196,
                    category: 1,
                    key: "Catch clause variable cannot have a type annotation."
                },
                Catch_clause_variable_cannot_have_an_initializer: {
                    code: 1197,
                    category: 1,
                    key: "Catch clause variable cannot have an initializer."
                },
                An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: {
                    code: 1198,
                    category: 1,
                    key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive."
                },
                Unterminated_Unicode_escape_sequence: {
                    code: 1199,
                    category: 1,
                    key: "Unterminated Unicode escape sequence."
                },
                Duplicate_identifier_0: {
                    code: 2300,
                    category: 1,
                    key: "Duplicate identifier '{0}'."
                },
                Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: {
                    code: 2301,
                    category: 1,
                    key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor."
                },
                Static_members_cannot_reference_class_type_parameters: {
                    code: 2302,
                    category: 1,
                    key: "Static members cannot reference class type parameters."
                },
                Circular_definition_of_import_alias_0: {
                    code: 2303,
                    category: 1,
                    key: "Circular definition of import alias '{0}'."
                },
                Cannot_find_name_0: {
                    code: 2304,
                    category: 1,
                    key: "Cannot find name '{0}'."
                },
                Module_0_has_no_exported_member_1: {
                    code: 2305,
                    category: 1,
                    key: "Module '{0}' has no exported member '{1}'."
                },
                File_0_is_not_an_external_module: {
                    code: 2306,
                    category: 1,
                    key: "File '{0}' is not an external module."
                },
                Cannot_find_external_module_0: {
                    code: 2307,
                    category: 1,
                    key: "Cannot find external module '{0}'."
                },
                A_module_cannot_have_more_than_one_export_assignment: {
                    code: 2308,
                    category: 1,
                    key: "A module cannot have more than one export assignment."
                },
                An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements: {
                    code: 2309,
                    category: 1,
                    key: "An export assignment cannot be used in a module with other exported elements."
                },
                Type_0_recursively_references_itself_as_a_base_type: {
                    code: 2310,
                    category: 1,
                    key: "Type '{0}' recursively references itself as a base type."
                },
                A_class_may_only_extend_another_class: {
                    code: 2311,
                    category: 1,
                    key: "A class may only extend another class."
                },
                An_interface_may_only_extend_a_class_or_another_interface: {
                    code: 2312,
                    category: 1,
                    key: "An interface may only extend a class or another interface."
                },
                Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: {
                    code: 2313,
                    category: 1,
                    key: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list."
                },
                Generic_type_0_requires_1_type_argument_s: {
                    code: 2314,
                    category: 1,
                    key: "Generic type '{0}' requires {1} type argument(s)."
                },
                Type_0_is_not_generic: {
                    code: 2315,
                    category: 1,
                    key: "Type '{0}' is not generic."
                },
                Global_type_0_must_be_a_class_or_interface_type: {
                    code: 2316,
                    category: 1,
                    key: "Global type '{0}' must be a class or interface type."
                },
                Global_type_0_must_have_1_type_parameter_s: {
                    code: 2317,
                    category: 1,
                    key: "Global type '{0}' must have {1} type parameter(s)."
                },
                Cannot_find_global_type_0: {
                    code: 2318,
                    category: 1,
                    key: "Cannot find global type '{0}'."
                },
                Named_property_0_of_types_1_and_2_are_not_identical: {
                    code: 2319,
                    category: 1,
                    key: "Named property '{0}' of types '{1}' and '{2}' are not identical."
                },
                Interface_0_cannot_simultaneously_extend_types_1_and_2: {
                    code: 2320,
                    category: 1,
                    key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'."
                },
                Excessive_stack_depth_comparing_types_0_and_1: {
                    code: 2321,
                    category: 1,
                    key: "Excessive stack depth comparing types '{0}' and '{1}'."
                },
                Type_0_is_not_assignable_to_type_1: {
                    code: 2322,
                    category: 1,
                    key: "Type '{0}' is not assignable to type '{1}'."
                },
                Property_0_is_missing_in_type_1: {
                    code: 2324,
                    category: 1,
                    key: "Property '{0}' is missing in type '{1}'."
                },
                Property_0_is_private_in_type_1_but_not_in_type_2: {
                    code: 2325,
                    category: 1,
                    key: "Property '{0}' is private in type '{1}' but not in type '{2}'."
                },
                Types_of_property_0_are_incompatible: {
                    code: 2326,
                    category: 1,
                    key: "Types of property '{0}' are incompatible."
                },
                Property_0_is_optional_in_type_1_but_required_in_type_2: {
                    code: 2327,
                    category: 1,
                    key: "Property '{0}' is optional in type '{1}' but required in type '{2}'."
                },
                Types_of_parameters_0_and_1_are_incompatible: {
                    code: 2328,
                    category: 1,
                    key: "Types of parameters '{0}' and '{1}' are incompatible."
                },
                Index_signature_is_missing_in_type_0: {
                    code: 2329,
                    category: 1,
                    key: "Index signature is missing in type '{0}'."
                },
                Index_signatures_are_incompatible: {
                    code: 2330,
                    category: 1,
                    key: "Index signatures are incompatible."
                },
                this_cannot_be_referenced_in_a_module_body: {
                    code: 2331,
                    category: 1,
                    key: "'this' cannot be referenced in a module body."
                },
                this_cannot_be_referenced_in_current_location: {
                    code: 2332,
                    category: 1,
                    key: "'this' cannot be referenced in current location."
                },
                this_cannot_be_referenced_in_constructor_arguments: {
                    code: 2333,
                    category: 1,
                    key: "'this' cannot be referenced in constructor arguments."
                },
                this_cannot_be_referenced_in_a_static_property_initializer: {
                    code: 2334,
                    category: 1,
                    key: "'this' cannot be referenced in a static property initializer."
                },
                super_can_only_be_referenced_in_a_derived_class: {
                    code: 2335,
                    category: 1,
                    key: "'super' can only be referenced in a derived class."
                },
                super_cannot_be_referenced_in_constructor_arguments: {
                    code: 2336,
                    category: 1,
                    key: "'super' cannot be referenced in constructor arguments."
                },
                Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: {
                    code: 2337,
                    category: 1,
                    key: "Super calls are not permitted outside constructors or in nested functions inside constructors"
                },
                super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: {
                    code: 2338,
                    category: 1,
                    key: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class"
                },
                Property_0_does_not_exist_on_type_1: {
                    code: 2339,
                    category: 1,
                    key: "Property '{0}' does not exist on type '{1}'."
                },
                Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: {
                    code: 2340,
                    category: 1,
                    key: "Only public and protected methods of the base class are accessible via the 'super' keyword"
                },
                Property_0_is_private_and_only_accessible_within_class_1: {
                    code: 2341,
                    category: 1,
                    key: "Property '{0}' is private and only accessible within class '{1}'."
                },
                An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: {
                    code: 2342,
                    category: 1,
                    key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'."
                },
                Type_0_does_not_satisfy_the_constraint_1: {
                    code: 2344,
                    category: 1,
                    key: "Type '{0}' does not satisfy the constraint '{1}'."
                },
                Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: {
                    code: 2345,
                    category: 1,
                    key: "Argument of type '{0}' is not assignable to parameter of type '{1}'."
                },
                Supplied_parameters_do_not_match_any_signature_of_call_target: {
                    code: 2346,
                    category: 1,
                    key: "Supplied parameters do not match any signature of call target."
                },
                Untyped_function_calls_may_not_accept_type_arguments: {
                    code: 2347,
                    category: 1,
                    key: "Untyped function calls may not accept type arguments."
                },
                Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: {
                    code: 2348,
                    category: 1,
                    key: "Value of type '{0}' is not callable. Did you mean to include 'new'?"
                },
                Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: {
                    code: 2349,
                    category: 1,
                    key: "Cannot invoke an expression whose type lacks a call signature."
                },
                Only_a_void_function_can_be_called_with_the_new_keyword: {
                    code: 2350,
                    category: 1,
                    key: "Only a void function can be called with the 'new' keyword."
                },
                Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: {
                    code: 2351,
                    category: 1,
                    key: "Cannot use 'new' with an expression whose type lacks a call or construct signature."
                },
                Neither_type_0_nor_type_1_is_assignable_to_the_other: {
                    code: 2352,
                    category: 1,
                    key: "Neither type '{0}' nor type '{1}' is assignable to the other."
                },
                No_best_common_type_exists_among_return_expressions: {
                    code: 2354,
                    category: 1,
                    key: "No best common type exists among return expressions."
                },
                A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: {
                    code: 2355,
                    category: 1,
                    key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement."
                },
                An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: {
                    code: 2356,
                    category: 1,
                    key: "An arithmetic operand must be of type 'any', 'number' or an enum type."
                },
                The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: {
                    code: 2357,
                    category: 1,
                    key: "The operand of an increment or decrement operator must be a variable, property or indexer."
                },
                The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: {
                    code: 2358,
                    category: 1,
                    key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter."
                },
                The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: {
                    code: 2359,
                    category: 1,
                    key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type."
                },
                The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol: {
                    code: 2360,
                    category: 1,
                    key: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'."
                },
                The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: {
                    code: 2361,
                    category: 1,
                    key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter"
                },
                The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: {
                    code: 2362,
                    category: 1,
                    key: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type."
                },
                The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: {
                    code: 2363,
                    category: 1,
                    key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type."
                },
                Invalid_left_hand_side_of_assignment_expression: {
                    code: 2364,
                    category: 1,
                    key: "Invalid left-hand side of assignment expression."
                },
                Operator_0_cannot_be_applied_to_types_1_and_2: {
                    code: 2365,
                    category: 1,
                    key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'."
                },
                Type_parameter_name_cannot_be_0: {
                    code: 2368,
                    category: 1,
                    key: "Type parameter name cannot be '{0}'"
                },
                A_parameter_property_is_only_allowed_in_a_constructor_implementation: {
                    code: 2369,
                    category: 1,
                    key: "A parameter property is only allowed in a constructor implementation."
                },
                A_rest_parameter_must_be_of_an_array_type: {
                    code: 2370,
                    category: 1,
                    key: "A rest parameter must be of an array type."
                },
                A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: {
                    code: 2371,
                    category: 1,
                    key: "A parameter initializer is only allowed in a function or constructor implementation."
                },
                Parameter_0_cannot_be_referenced_in_its_initializer: {
                    code: 2372,
                    category: 1,
                    key: "Parameter '{0}' cannot be referenced in its initializer."
                },
                Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: {
                    code: 2373,
                    category: 1,
                    key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it."
                },
                Duplicate_string_index_signature: {
                    code: 2374,
                    category: 1,
                    key: "Duplicate string index signature."
                },
                Duplicate_number_index_signature: {
                    code: 2375,
                    category: 1,
                    key: "Duplicate number index signature."
                },
                A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: {
                    code: 2376,
                    category: 1,
                    key: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties."
                },
                Constructors_for_derived_classes_must_contain_a_super_call: {
                    code: 2377,
                    category: 1,
                    key: "Constructors for derived classes must contain a 'super' call."
                },
                A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: {
                    code: 2378,
                    category: 1,
                    key: "A 'get' accessor must return a value or consist of a single 'throw' statement."
                },
                Getter_and_setter_accessors_do_not_agree_in_visibility: {
                    code: 2379,
                    category: 1,
                    key: "Getter and setter accessors do not agree in visibility."
                },
                get_and_set_accessor_must_have_the_same_type: {
                    code: 2380,
                    category: 1,
                    key: "'get' and 'set' accessor must have the same type."
                },
                A_signature_with_an_implementation_cannot_use_a_string_literal_type: {
                    code: 2381,
                    category: 1,
                    key: "A signature with an implementation cannot use a string literal type."
                },
                Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: {
                    code: 2382,
                    category: 1,
                    key: "Specialized overload signature is not assignable to any non-specialized signature."
                },
                Overload_signatures_must_all_be_exported_or_not_exported: {
                    code: 2383,
                    category: 1,
                    key: "Overload signatures must all be exported or not exported."
                },
                Overload_signatures_must_all_be_ambient_or_non_ambient: {
                    code: 2384,
                    category: 1,
                    key: "Overload signatures must all be ambient or non-ambient."
                },
                Overload_signatures_must_all_be_public_private_or_protected: {
                    code: 2385,
                    category: 1,
                    key: "Overload signatures must all be public, private or protected."
                },
                Overload_signatures_must_all_be_optional_or_required: {
                    code: 2386,
                    category: 1,
                    key: "Overload signatures must all be optional or required."
                },
                Function_overload_must_be_static: {
                    code: 2387,
                    category: 1,
                    key: "Function overload must be static."
                },
                Function_overload_must_not_be_static: {
                    code: 2388,
                    category: 1,
                    key: "Function overload must not be static."
                },
                Function_implementation_name_must_be_0: {
                    code: 2389,
                    category: 1,
                    key: "Function implementation name must be '{0}'."
                },
                Constructor_implementation_is_missing: {
                    code: 2390,
                    category: 1,
                    key: "Constructor implementation is missing."
                },
                Function_implementation_is_missing_or_not_immediately_following_the_declaration: {
                    code: 2391,
                    category: 1,
                    key: "Function implementation is missing or not immediately following the declaration."
                },
                Multiple_constructor_implementations_are_not_allowed: {
                    code: 2392,
                    category: 1,
                    key: "Multiple constructor implementations are not allowed."
                },
                Duplicate_function_implementation: {
                    code: 2393,
                    category: 1,
                    key: "Duplicate function implementation."
                },
                Overload_signature_is_not_compatible_with_function_implementation: {
                    code: 2394,
                    category: 1,
                    key: "Overload signature is not compatible with function implementation."
                },
                Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: {
                    code: 2395,
                    category: 1,
                    key: "Individual declarations in merged declaration {0} must be all exported or all local."
                },
                Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: {
                    code: 2396,
                    category: 1,
                    key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters."
                },
                Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: {
                    code: 2399,
                    category: 1,
                    key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference."
                },
                Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: {
                    code: 2400,
                    category: 1,
                    key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference."
                },
                Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: {
                    code: 2401,
                    category: 1,
                    key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference."
                },
                Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: {
                    code: 2402,
                    category: 1,
                    key: "Expression resolves to '_super' that compiler uses to capture base class reference."
                },
                Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: {
                    code: 2403,
                    category: 1,
                    key: "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'."
                },
                The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation: {
                    code: 2404,
                    category: 1,
                    key: "The left-hand side of a 'for...in' statement cannot use a type annotation."
                },
                The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any: {
                    code: 2405,
                    category: 1,
                    key: "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'."
                },
                Invalid_left_hand_side_in_for_in_statement: {
                    code: 2406,
                    category: 1,
                    key: "Invalid left-hand side in 'for...in' statement."
                },
                The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: {
                    code: 2407,
                    category: 1,
                    key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter."
                },
                Setters_cannot_return_a_value: {
                    code: 2408,
                    category: 1,
                    key: "Setters cannot return a value."
                },
                Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: {
                    code: 2409,
                    category: 1,
                    key: "Return type of constructor signature must be assignable to the instance type of the class"
                },
                All_symbols_within_a_with_block_will_be_resolved_to_any: {
                    code: 2410,
                    category: 1,
                    key: "All symbols within a 'with' block will be resolved to 'any'."
                },
                Property_0_of_type_1_is_not_assignable_to_string_index_type_2: {
                    code: 2411,
                    category: 1,
                    key: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'."
                },
                Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: {
                    code: 2412,
                    category: 1,
                    key: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'."
                },
                Numeric_index_type_0_is_not_assignable_to_string_index_type_1: {
                    code: 2413,
                    category: 1,
                    key: "Numeric index type '{0}' is not assignable to string index type '{1}'."
                },
                Class_name_cannot_be_0: {
                    code: 2414,
                    category: 1,
                    key: "Class name cannot be '{0}'"
                },
                Class_0_incorrectly_extends_base_class_1: {
                    code: 2415,
                    category: 1,
                    key: "Class '{0}' incorrectly extends base class '{1}'."
                },
                Class_static_side_0_incorrectly_extends_base_class_static_side_1: {
                    code: 2417,
                    category: 1,
                    key: "Class static side '{0}' incorrectly extends base class static side '{1}'."
                },
                Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: {
                    code: 2419,
                    category: 1,
                    key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'."
                },
                Class_0_incorrectly_implements_interface_1: {
                    code: 2420,
                    category: 1,
                    key: "Class '{0}' incorrectly implements interface '{1}'."
                },
                A_class_may_only_implement_another_class_or_interface: {
                    code: 2422,
                    category: 1,
                    key: "A class may only implement another class or interface."
                },
                Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: {
                    code: 2423,
                    category: 1,
                    key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor."
                },
                Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: {
                    code: 2424,
                    category: 1,
                    key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property."
                },
                Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: {
                    code: 2425,
                    category: 1,
                    key: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function."
                },
                Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: {
                    code: 2426,
                    category: 1,
                    key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function."
                },
                Interface_name_cannot_be_0: {
                    code: 2427,
                    category: 1,
                    key: "Interface name cannot be '{0}'"
                },
                All_declarations_of_an_interface_must_have_identical_type_parameters: {
                    code: 2428,
                    category: 1,
                    key: "All declarations of an interface must have identical type parameters."
                },
                Interface_0_incorrectly_extends_interface_1: {
                    code: 2430,
                    category: 1,
                    key: "Interface '{0}' incorrectly extends interface '{1}'."
                },
                Enum_name_cannot_be_0: {
                    code: 2431,
                    category: 1,
                    key: "Enum name cannot be '{0}'"
                },
                In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: {
                    code: 2432,
                    category: 1,
                    key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element."
                },
                A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged: {
                    code: 2433,
                    category: 1,
                    key: "A module declaration cannot be in a different file from a class or function with which it is merged"
                },
                A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: {
                    code: 2434,
                    category: 1,
                    key: "A module declaration cannot be located prior to a class or function with which it is merged"
                },
                Ambient_external_modules_cannot_be_nested_in_other_modules: {
                    code: 2435,
                    category: 1,
                    key: "Ambient external modules cannot be nested in other modules."
                },
                Ambient_external_module_declaration_cannot_specify_relative_module_name: {
                    code: 2436,
                    category: 1,
                    key: "Ambient external module declaration cannot specify relative module name."
                },
                Module_0_is_hidden_by_a_local_declaration_with_the_same_name: {
                    code: 2437,
                    category: 1,
                    key: "Module '{0}' is hidden by a local declaration with the same name"
                },
                Import_name_cannot_be_0: {
                    code: 2438,
                    category: 1,
                    key: "Import name cannot be '{0}'"
                },
                Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: {
                    code: 2439,
                    category: 1,
                    key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name."
                },
                Import_declaration_conflicts_with_local_declaration_of_0: {
                    code: 2440,
                    category: 1,
                    key: "Import declaration conflicts with local declaration of '{0}'"
                },
                Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: {
                    code: 2441,
                    category: 1,
                    key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module."
                },
                Types_have_separate_declarations_of_a_private_property_0: {
                    code: 2442,
                    category: 1,
                    key: "Types have separate declarations of a private property '{0}'."
                },
                Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2: {
                    code: 2443,
                    category: 1,
                    key: "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'."
                },
                Property_0_is_protected_in_type_1_but_public_in_type_2: {
                    code: 2444,
                    category: 1,
                    key: "Property '{0}' is protected in type '{1}' but public in type '{2}'."
                },
                Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: {
                    code: 2445,
                    category: 1,
                    key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses."
                },
                Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: {
                    code: 2446,
                    category: 1,
                    key: "Property '{0}' is protected and only accessible through an instance of class '{1}'."
                },
                The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: {
                    code: 2447,
                    category: 1,
                    key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead."
                },
                Block_scoped_variable_0_used_before_its_declaration: {
                    code: 2448,
                    category: 1,
                    key: "Block-scoped variable '{0}' used before its declaration."
                },
                The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: {
                    code: 2449,
                    category: 1,
                    key: "The operand of an increment or decrement operator cannot be a constant."
                },
                Left_hand_side_of_assignment_expression_cannot_be_a_constant: {
                    code: 2450,
                    category: 1,
                    key: "Left-hand side of assignment expression cannot be a constant."
                },
                Cannot_redeclare_block_scoped_variable_0: {
                    code: 2451,
                    category: 1,
                    key: "Cannot redeclare block-scoped variable '{0}'."
                },
                An_enum_member_cannot_have_a_numeric_name: {
                    code: 2452,
                    category: 1,
                    key: "An enum member cannot have a numeric name."
                },
                The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: {
                    code: 2453,
                    category: 1,
                    key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly."
                },
                Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: {
                    code: 2455,
                    category: 1,
                    key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'."
                },
                Type_alias_0_circularly_references_itself: {
                    code: 2456,
                    category: 1,
                    key: "Type alias '{0}' circularly references itself."
                },
                Type_alias_name_cannot_be_0: {
                    code: 2457,
                    category: 1,
                    key: "Type alias name cannot be '{0}'"
                },
                An_AMD_module_cannot_have_multiple_name_assignments: {
                    code: 2458,
                    category: 1,
                    key: "An AMD module cannot have multiple name assignments."
                },
                Type_0_has_no_property_1_and_no_string_index_signature: {
                    code: 2459,
                    category: 1,
                    key: "Type '{0}' has no property '{1}' and no string index signature."
                },
                Type_0_has_no_property_1: {
                    code: 2460,
                    category: 1,
                    key: "Type '{0}' has no property '{1}'."
                },
                Type_0_is_not_an_array_type: {
                    code: 2461,
                    category: 1,
                    key: "Type '{0}' is not an array type."
                },
                A_rest_element_must_be_last_in_an_array_destructuring_pattern: {
                    code: 2462,
                    category: 1,
                    key: "A rest element must be last in an array destructuring pattern"
                },
                A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: {
                    code: 2463,
                    category: 1,
                    key: "A binding pattern parameter cannot be optional in an implementation signature."
                },
                A_computed_property_name_must_be_of_type_string_number_symbol_or_any: {
                    code: 2464,
                    category: 1,
                    key: "A computed property name must be of type 'string', 'number', 'symbol', or 'any'."
                },
                this_cannot_be_referenced_in_a_computed_property_name: {
                    code: 2465,
                    category: 1,
                    key: "'this' cannot be referenced in a computed property name."
                },
                super_cannot_be_referenced_in_a_computed_property_name: {
                    code: 2466,
                    category: 1,
                    key: "'super' cannot be referenced in a computed property name."
                },
                A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: {
                    code: 2467,
                    category: 1,
                    key: "A computed property name cannot reference a type parameter from its containing type."
                },
                Cannot_find_global_value_0: {
                    code: 2468,
                    category: 1,
                    key: "Cannot find global value '{0}'."
                },
                The_0_operator_cannot_be_applied_to_type_symbol: {
                    code: 2469,
                    category: 1,
                    key: "The '{0}' operator cannot be applied to type 'symbol'."
                },
                Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object: {
                    code: 2470,
                    category: 1,
                    key: "'Symbol' reference does not refer to the global Symbol constructor object."
                },
                A_computed_property_name_of_the_form_0_must_be_of_type_symbol: {
                    code: 2471,
                    category: 1,
                    key: "A computed property name of the form '{0}' must be of type 'symbol'."
                },
                Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: {
                    code: 2472,
                    category: 1,
                    key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher."
                },
                Enum_declarations_must_all_be_const_or_non_const: {
                    code: 2473,
                    category: 1,
                    key: "Enum declarations must all be const or non-const."
                },
                In_const_enum_declarations_member_initializer_must_be_constant_expression: {
                    code: 2474,
                    category: 1,
                    key: "In 'const' enum declarations member initializer must be constant expression."
                },
                const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: {
                    code: 2475,
                    category: 1,
                    key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment."
                },
                A_const_enum_member_can_only_be_accessed_using_a_string_literal: {
                    code: 2476,
                    category: 1,
                    key: "A const enum member can only be accessed using a string literal."
                },
                const_enum_member_initializer_was_evaluated_to_a_non_finite_value: {
                    code: 2477,
                    category: 1,
                    key: "'const' enum member initializer was evaluated to a non-finite value."
                },
                const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: {
                    code: 2478,
                    category: 1,
                    key: "'const' enum member initializer was evaluated to disallowed value 'NaN'."
                },
                Property_0_does_not_exist_on_const_enum_1: {
                    code: 2479,
                    category: 1,
                    key: "Property '{0}' does not exist on 'const' enum '{1}'."
                },
                let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: {
                    code: 2480,
                    category: 1,
                    key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations."
                },
                Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: {
                    code: 2481,
                    category: 1,
                    key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'."
                },
                The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: {
                    code: 2483,
                    category: 1,
                    key: "The left-hand side of a 'for...of' statement cannot use a type annotation."
                },
                Export_declaration_conflicts_with_exported_declaration_of_0: {
                    code: 2484,
                    category: 1,
                    key: "Export declaration conflicts with exported declaration of '{0}'"
                },
                The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: {
                    code: 2485,
                    category: 1,
                    key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant."
                },
                The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: {
                    code: 2486,
                    category: 1,
                    key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant."
                },
                Invalid_left_hand_side_in_for_of_statement: {
                    code: 2487,
                    category: 1,
                    key: "Invalid left-hand side in 'for...of' statement."
                },
                The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator: {
                    code: 2488,
                    category: 1,
                    key: "The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator."
                },
                The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method: {
                    code: 2489,
                    category: 1,
                    key: "The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method."
                },
                The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: {
                    code: 2490,
                    category: 1,
                    key: "The type returned by the 'next()' method of an iterator must have a 'value' property."
                },
                The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: {
                    code: 2491,
                    category: 1,
                    key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern."
                },
                Cannot_redeclare_identifier_0_in_catch_clause: {
                    code: 2492,
                    category: 1,
                    key: "Cannot redeclare identifier '{0}' in catch clause"
                },
                Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: {
                    code: 2493,
                    category: 1,
                    key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'."
                },
                Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: {
                    code: 2494,
                    category: 1,
                    key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher."
                },
                Type_0_is_not_an_array_type_or_a_string_type: {
                    code: 2461,
                    category: 1,
                    key: "Type '{0}' is not an array type or a string type."
                },
                Import_declaration_0_is_using_private_name_1: {
                    code: 4000,
                    category: 1,
                    key: "Import declaration '{0}' is using private name '{1}'."
                },
                Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: {
                    code: 4002,
                    category: 1,
                    key: "Type parameter '{0}' of exported class has or is using private name '{1}'."
                },
                Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: {
                    code: 4004,
                    category: 1,
                    key: "Type parameter '{0}' of exported interface has or is using private name '{1}'."
                },
                Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4006,
                    category: 1,
                    key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'."
                },
                Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4008,
                    category: 1,
                    key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'."
                },
                Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4010,
                    category: 1,
                    key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'."
                },
                Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4012,
                    category: 1,
                    key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'."
                },
                Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4014,
                    category: 1,
                    key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'."
                },
                Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: {
                    code: 4016,
                    category: 1,
                    key: "Type parameter '{0}' of exported function has or is using private name '{1}'."
                },
                Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: {
                    code: 4019,
                    category: 1,
                    key: "Implements clause of exported class '{0}' has or is using private name '{1}'."
                },
                Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: {
                    code: 4020,
                    category: 1,
                    key: "Extends clause of exported class '{0}' has or is using private name '{1}'."
                },
                Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: {
                    code: 4022,
                    category: 1,
                    key: "Extends clause of exported interface '{0}' has or is using private name '{1}'."
                },
                Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4023,
                    category: 1,
                    key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named."
                },
                Exported_variable_0_has_or_is_using_name_1_from_private_module_2: {
                    code: 4024,
                    category: 1,
                    key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'."
                },
                Exported_variable_0_has_or_is_using_private_name_1: {
                    code: 4025,
                    category: 1,
                    key: "Exported variable '{0}' has or is using private name '{1}'."
                },
                Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4026,
                    category: 1,
                    key: "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named."
                },
                Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4027,
                    category: 1,
                    key: "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'."
                },
                Public_static_property_0_of_exported_class_has_or_is_using_private_name_1: {
                    code: 4028,
                    category: 1,
                    key: "Public static property '{0}' of exported class has or is using private name '{1}'."
                },
                Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4029,
                    category: 1,
                    key: "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named."
                },
                Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4030,
                    category: 1,
                    key: "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'."
                },
                Public_property_0_of_exported_class_has_or_is_using_private_name_1: {
                    code: 4031,
                    category: 1,
                    key: "Public property '{0}' of exported class has or is using private name '{1}'."
                },
                Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: {
                    code: 4032,
                    category: 1,
                    key: "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'."
                },
                Property_0_of_exported_interface_has_or_is_using_private_name_1: {
                    code: 4033,
                    category: 1,
                    key: "Property '{0}' of exported interface has or is using private name '{1}'."
                },
                Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4034,
                    category: 1,
                    key: "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4035,
                    category: 1,
                    key: "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'."
                },
                Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4036,
                    category: 1,
                    key: "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4037,
                    category: 1,
                    key: "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'."
                },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: {
                    code: 4038,
                    category: 1,
                    key: "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named."
                },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: {
                    code: 4039,
                    category: 1,
                    key: "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0: {
                    code: 4040,
                    category: 1,
                    key: "Return type of public static property getter from exported class has or is using private name '{0}'."
                },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: {
                    code: 4041,
                    category: 1,
                    key: "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named."
                },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: {
                    code: 4042,
                    category: 1,
                    key: "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0: {
                    code: 4043,
                    category: 1,
                    key: "Return type of public property getter from exported class has or is using private name '{0}'."
                },
                Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: {
                    code: 4044,
                    category: 1,
                    key: "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0: {
                    code: 4045,
                    category: 1,
                    key: "Return type of constructor signature from exported interface has or is using private name '{0}'."
                },
                Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: {
                    code: 4046,
                    category: 1,
                    key: "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0: {
                    code: 4047,
                    category: 1,
                    key: "Return type of call signature from exported interface has or is using private name '{0}'."
                },
                Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: {
                    code: 4048,
                    category: 1,
                    key: "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0: {
                    code: 4049,
                    category: 1,
                    key: "Return type of index signature from exported interface has or is using private name '{0}'."
                },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: {
                    code: 4050,
                    category: 1,
                    key: "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named."
                },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: {
                    code: 4051,
                    category: 1,
                    key: "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0: {
                    code: 4052,
                    category: 1,
                    key: "Return type of public static method from exported class has or is using private name '{0}'."
                },
                Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: {
                    code: 4053,
                    category: 1,
                    key: "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named."
                },
                Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: {
                    code: 4054,
                    category: 1,
                    key: "Return type of public method from exported class has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0: {
                    code: 4055,
                    category: 1,
                    key: "Return type of public method from exported class has or is using private name '{0}'."
                },
                Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1: {
                    code: 4056,
                    category: 1,
                    key: "Return type of method from exported interface has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0: {
                    code: 4057,
                    category: 1,
                    key: "Return type of method from exported interface has or is using private name '{0}'."
                },
                Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: {
                    code: 4058,
                    category: 1,
                    key: "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named."
                },
                Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1: {
                    code: 4059,
                    category: 1,
                    key: "Return type of exported function has or is using name '{0}' from private module '{1}'."
                },
                Return_type_of_exported_function_has_or_is_using_private_name_0: {
                    code: 4060,
                    category: 1,
                    key: "Return type of exported function has or is using private name '{0}'."
                },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4061,
                    category: 1,
                    key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named."
                },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4062,
                    category: 1,
                    key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4063,
                    category: 1,
                    key: "Parameter '{0}' of constructor from exported class has or is using private name '{1}'."
                },
                Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: {
                    code: 4064,
                    category: 1,
                    key: "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4065,
                    category: 1,
                    key: "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'."
                },
                Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: {
                    code: 4066,
                    category: 1,
                    key: "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4067,
                    category: 1,
                    key: "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'."
                },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4068,
                    category: 1,
                    key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named."
                },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4069,
                    category: 1,
                    key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4070,
                    category: 1,
                    key: "Parameter '{0}' of public static method from exported class has or is using private name '{1}'."
                },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4071,
                    category: 1,
                    key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named."
                },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: {
                    code: 4072,
                    category: 1,
                    key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: {
                    code: 4073,
                    category: 1,
                    key: "Parameter '{0}' of public method from exported class has or is using private name '{1}'."
                },
                Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: {
                    code: 4074,
                    category: 1,
                    key: "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: {
                    code: 4075,
                    category: 1,
                    key: "Parameter '{0}' of method from exported interface has or is using private name '{1}'."
                },
                Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: {
                    code: 4076,
                    category: 1,
                    key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named."
                },
                Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: {
                    code: 4077,
                    category: 1,
                    key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'."
                },
                Parameter_0_of_exported_function_has_or_is_using_private_name_1: {
                    code: 4078,
                    category: 1,
                    key: "Parameter '{0}' of exported function has or is using private name '{1}'."
                },
                Exported_type_alias_0_has_or_is_using_private_name_1: {
                    code: 4081,
                    category: 1,
                    key: "Exported type alias '{0}' has or is using private name '{1}'."
                },
                Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: {
                    code: 4091,
                    category: 1,
                    key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher."
                },
                The_current_host_does_not_support_the_0_option: {
                    code: 5001,
                    category: 1,
                    key: "The current host does not support the '{0}' option."
                },
                Cannot_find_the_common_subdirectory_path_for_the_input_files: {
                    code: 5009,
                    category: 1,
                    key: "Cannot find the common subdirectory path for the input files."
                },
                Cannot_read_file_0_Colon_1: {
                    code: 5012,
                    category: 1,
                    key: "Cannot read file '{0}': {1}"
                },
                Unsupported_file_encoding: {
                    code: 5013,
                    category: 1,
                    key: "Unsupported file encoding."
                },
                Unknown_compiler_option_0: {
                    code: 5023,
                    category: 1,
                    key: "Unknown compiler option '{0}'."
                },
                Compiler_option_0_requires_a_value_of_type_1: {
                    code: 5024,
                    category: 1,
                    key: "Compiler option '{0}' requires a value of type {1}."
                },
                Could_not_write_file_0_Colon_1: {
                    code: 5033,
                    category: 1,
                    key: "Could not write file '{0}': {1}"
                },
                Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: {
                    code: 5038,
                    category: 1,
                    key: "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option."
                },
                Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: {
                    code: 5039,
                    category: 1,
                    key: "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option."
                },
                Option_noEmit_cannot_be_specified_with_option_out_or_outDir: {
                    code: 5040,
                    category: 1,
                    key: "Option 'noEmit' cannot be specified with option 'out' or 'outDir'."
                },
                Option_noEmit_cannot_be_specified_with_option_declaration: {
                    code: 5041,
                    category: 1,
                    key: "Option 'noEmit' cannot be specified with option 'declaration'."
                },
                Option_project_cannot_be_mixed_with_source_files_on_a_command_line: {
                    code: 5042,
                    category: 1,
                    key: "Option 'project' cannot be mixed with source files on a command line."
                },
                Concatenate_and_emit_output_to_single_file: {
                    code: 6001,
                    category: 2,
                    key: "Concatenate and emit output to single file."
                },
                Generates_corresponding_d_ts_file: {
                    code: 6002,
                    category: 2,
                    key: "Generates corresponding '.d.ts' file."
                },
                Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: {
                    code: 6003,
                    category: 2,
                    key: "Specifies the location where debugger should locate map files instead of generated locations."
                },
                Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: {
                    code: 6004,
                    category: 2,
                    key: "Specifies the location where debugger should locate TypeScript files instead of source locations."
                },
                Watch_input_files: {
                    code: 6005,
                    category: 2,
                    key: "Watch input files."
                },
                Redirect_output_structure_to_the_directory: {
                    code: 6006,
                    category: 2,
                    key: "Redirect output structure to the directory."
                },
                Do_not_erase_const_enum_declarations_in_generated_code: {
                    code: 6007,
                    category: 2,
                    key: "Do not erase const enum declarations in generated code."
                },
                Do_not_emit_outputs_if_any_type_checking_errors_were_reported: {
                    code: 6008,
                    category: 2,
                    key: "Do not emit outputs if any type checking errors were reported."
                },
                Do_not_emit_comments_to_output: {
                    code: 6009,
                    category: 2,
                    key: "Do not emit comments to output."
                },
                Do_not_emit_outputs: {
                    code: 6010,
                    category: 2,
                    key: "Do not emit outputs."
                },
                Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: {
                    code: 6015,
                    category: 2,
                    key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)"
                },
                Specify_module_code_generation_Colon_commonjs_or_amd: {
                    code: 6016,
                    category: 2,
                    key: "Specify module code generation: 'commonjs' or 'amd'"
                },
                Print_this_message: {
                    code: 6017,
                    category: 2,
                    key: "Print this message."
                },
                Print_the_compiler_s_version: {
                    code: 6019,
                    category: 2,
                    key: "Print the compiler's version."
                },
                Compile_the_project_in_the_given_directory: {
                    code: 6020,
                    category: 2,
                    key: "Compile the project in the given directory."
                },
                Syntax_Colon_0: {
                    code: 6023,
                    category: 2,
                    key: "Syntax: {0}"
                },
                options: {
                    code: 6024,
                    category: 2,
                    key: "options"
                },
                file: {
                    code: 6025,
                    category: 2,
                    key: "file"
                },
                Examples_Colon_0: {
                    code: 6026,
                    category: 2,
                    key: "Examples: {0}"
                },
                Options_Colon: {
                    code: 6027,
                    category: 2,
                    key: "Options:"
                },
                Version_0: {
                    code: 6029,
                    category: 2,
                    key: "Version {0}"
                },
                Insert_command_line_options_and_files_from_a_file: {
                    code: 6030,
                    category: 2,
                    key: "Insert command line options and files from a file."
                },
                File_change_detected_Starting_incremental_compilation: {
                    code: 6032,
                    category: 2,
                    key: "File change detected. Starting incremental compilation..."
                },
                KIND: {
                    code: 6034,
                    category: 2,
                    key: "KIND"
                },
                FILE: {
                    code: 6035,
                    category: 2,
                    key: "FILE"
                },
                VERSION: {
                    code: 6036,
                    category: 2,
                    key: "VERSION"
                },
                LOCATION: {
                    code: 6037,
                    category: 2,
                    key: "LOCATION"
                },
                DIRECTORY: {
                    code: 6038,
                    category: 2,
                    key: "DIRECTORY"
                },
                Compilation_complete_Watching_for_file_changes: {
                    code: 6042,
                    category: 2,
                    key: "Compilation complete. Watching for file changes."
                },
                Generates_corresponding_map_file: {
                    code: 6043,
                    category: 2,
                    key: "Generates corresponding '.map' file."
                },
                Compiler_option_0_expects_an_argument: {
                    code: 6044,
                    category: 1,
                    key: "Compiler option '{0}' expects an argument."
                },
                Unterminated_quoted_string_in_response_file_0: {
                    code: 6045,
                    category: 1,
                    key: "Unterminated quoted string in response file '{0}'."
                },
                Argument_for_module_option_must_be_commonjs_or_amd: {
                    code: 6046,
                    category: 1,
                    key: "Argument for '--module' option must be 'commonjs' or 'amd'."
                },
                Argument_for_target_option_must_be_es3_es5_or_es6: {
                    code: 6047,
                    category: 1,
                    key: "Argument for '--target' option must be 'es3', 'es5', or 'es6'."
                },
                Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: {
                    code: 6048,
                    category: 1,
                    key: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'."
                },
                Unsupported_locale_0: {
                    code: 6049,
                    category: 1,
                    key: "Unsupported locale '{0}'."
                },
                Unable_to_open_file_0: {
                    code: 6050,
                    category: 1,
                    key: "Unable to open file '{0}'."
                },
                Corrupted_locale_file_0: {
                    code: 6051,
                    category: 1,
                    key: "Corrupted locale file {0}."
                },
                Raise_error_on_expressions_and_declarations_with_an_implied_any_type: {
                    code: 6052,
                    category: 2,
                    key: "Raise error on expressions and declarations with an implied 'any' type."
                },
                File_0_not_found: {
                    code: 6053,
                    category: 1,
                    key: "File '{0}' not found."
                },
                File_0_must_have_extension_ts_or_d_ts: {
                    code: 6054,
                    category: 1,
                    key: "File '{0}' must have extension '.ts' or '.d.ts'."
                },
                Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: {
                    code: 6055,
                    category: 2,
                    key: "Suppress noImplicitAny errors for indexing objects lacking index signatures."
                },
                Do_not_emit_declarations_for_code_that_has_an_internal_annotation: {
                    code: 6056,
                    category: 2,
                    key: "Do not emit declarations for code that has an '@internal' annotation."
                },
                Preserve_new_lines_when_emitting_code: {
                    code: 6057,
                    category: 2,
                    key: "Preserve new-lines when emitting code."
                },
                Variable_0_implicitly_has_an_1_type: {
                    code: 7005,
                    category: 1,
                    key: "Variable '{0}' implicitly has an '{1}' type."
                },
                Parameter_0_implicitly_has_an_1_type: {
                    code: 7006,
                    category: 1,
                    key: "Parameter '{0}' implicitly has an '{1}' type."
                },
                Member_0_implicitly_has_an_1_type: {
                    code: 7008,
                    category: 1,
                    key: "Member '{0}' implicitly has an '{1}' type."
                },
                new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type: {
                    code: 7009,
                    category: 1,
                    key: "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type."
                },
                _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type: {
                    code: 7010,
                    category: 1,
                    key: "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type."
                },
                Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type: {
                    code: 7011,
                    category: 1,
                    key: "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type."
                },
                Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: {
                    code: 7013,
                    category: 1,
                    key: "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type."
                },
                Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation: {
                    code: 7016,
                    category: 1,
                    key: "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation."
                },
                Index_signature_of_object_type_implicitly_has_an_any_type: {
                    code: 7017,
                    category: 1,
                    key: "Index signature of object type implicitly has an 'any' type."
                },
                Object_literal_s_property_0_implicitly_has_an_1_type: {
                    code: 7018,
                    category: 1,
                    key: "Object literal's property '{0}' implicitly has an '{1}' type."
                },
                Rest_parameter_0_implicitly_has_an_any_type: {
                    code: 7019,
                    category: 1,
                    key: "Rest parameter '{0}' implicitly has an 'any[]' type."
                },
                Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: {
                    code: 7020,
                    category: 1,
                    key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type."
                },
                _0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: {
                    code: 7021,
                    category: 1,
                    key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation."
                },
                _0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: {
                    code: 7022,
                    category: 1,
                    key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer."
                },
                _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: {
                    code: 7023,
                    category: 1,
                    key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions."
                },
                Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: {
                    code: 7024,
                    category: 1,
                    key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions."
                },
                You_cannot_rename_this_element: {
                    code: 8000,
                    category: 1,
                    key: "You cannot rename this element."
                },
                You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: {
                    code: 8001,
                    category: 1,
                    key: "You cannot rename elements that are defined in the standard TypeScript library."
                },
                yield_expressions_are_not_currently_supported: {
                    code: 9000,
                    category: 1,
                    key: "'yield' expressions are not currently supported."
                },
                Generators_are_not_currently_supported: {
                    code: 9001,
                    category: 1,
                    key: "Generators are not currently supported."
                },
                The_arguments_object_cannot_be_referenced_in_an_arrow_function_Consider_using_a_standard_function_expression: {
                    code: 9002,
                    category: 1,
                    key: "The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression."
                }
            };
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var textToToken = {
                "any": 111,
                "as": 101,
                "boolean": 112,
                "break": 65,
                "case": 66,
                "catch": 67,
                "class": 68,
                "continue": 70,
                "const": 69,
                "constructor": 113,
                "debugger": 71,
                "declare": 114,
                "default": 72,
                "delete": 73,
                "do": 74,
                "else": 75,
                "enum": 76,
                "export": 77,
                "extends": 78,
                "false": 79,
                "finally": 80,
                "for": 81,
                "from": 123,
                "function": 82,
                "get": 115,
                "if": 83,
                "implements": 102,
                "import": 84,
                "in": 85,
                "instanceof": 86,
                "interface": 103,
                "let": 104,
                "module": 116,
                "new": 87,
                "null": 88,
                "number": 118,
                "package": 105,
                "private": 106,
                "protected": 107,
                "public": 108,
                "require": 117,
                "return": 89,
                "set": 119,
                "static": 109,
                "string": 120,
                "super": 90,
                "switch": 91,
                "symbol": 121,
                "this": 92,
                "throw": 93,
                "true": 94,
                "try": 95,
                "type": 122,
                "typeof": 96,
                "var": 97,
                "void": 98,
                "while": 99,
                "with": 100,
                "yield": 110,
                "of": 124,
                "{": 14,
                "}": 15,
                "(": 16,
                ")": 17,
                "[": 18,
                "]": 19,
                ".": 20,
                "...": 21,
                ";": 22,
                ",": 23,
                "<": 24,
                ">": 25,
                "<=": 26,
                ">=": 27,
                "==": 28,
                "!=": 29,
                "===": 30,
                "!==": 31,
                "=>": 32,
                "+": 33,
                "-": 34,
                "*": 35,
                "/": 36,
                "%": 37,
                "++": 38,
                "--": 39,
                "<<": 40,
                ">>": 41,
                ">>>": 42,
                "&": 43,
                "|": 44,
                "^": 45,
                "!": 46,
                "~": 47,
                "&&": 48,
                "||": 49,
                "?": 50,
                ":": 51,
                "=": 52,
                "+=": 53,
                "-=": 54,
                "*=": 55,
                "/=": 56,
                "%=": 57,
                "<<=": 58,
                ">>=": 59,
                ">>>=": 60,
                "&=": 61,
                "|=": 62,
                "^=": 63
            };
            var unicodeES3IdentifierStart = [
                170,
                170,
                181,
                181,
                186,
                186,
                192,
                214,
                216,
                246,
                248,
                543,
                546,
                563,
                592,
                685,
                688,
                696,
                699,
                705,
                720,
                721,
                736,
                740,
                750,
                750,
                890,
                890,
                902,
                902,
                904,
                906,
                908,
                908,
                910,
                929,
                931,
                974,
                976,
                983,
                986,
                1011,
                1024,
                1153,
                1164,
                1220,
                1223,
                1224,
                1227,
                1228,
                1232,
                1269,
                1272,
                1273,
                1329,
                1366,
                1369,
                1369,
                1377,
                1415,
                1488,
                1514,
                1520,
                1522,
                1569,
                1594,
                1600,
                1610,
                1649,
                1747,
                1749,
                1749,
                1765,
                1766,
                1786,
                1788,
                1808,
                1808,
                1810,
                1836,
                1920,
                1957,
                2309,
                2361,
                2365,
                2365,
                2384,
                2384,
                2392,
                2401,
                2437,
                2444,
                2447,
                2448,
                2451,
                2472,
                2474,
                2480,
                2482,
                2482,
                2486,
                2489,
                2524,
                2525,
                2527,
                2529,
                2544,
                2545,
                2565,
                2570,
                2575,
                2576,
                2579,
                2600,
                2602,
                2608,
                2610,
                2611,
                2613,
                2614,
                2616,
                2617,
                2649,
                2652,
                2654,
                2654,
                2674,
                2676,
                2693,
                2699,
                2701,
                2701,
                2703,
                2705,
                2707,
                2728,
                2730,
                2736,
                2738,
                2739,
                2741,
                2745,
                2749,
                2749,
                2768,
                2768,
                2784,
                2784,
                2821,
                2828,
                2831,
                2832,
                2835,
                2856,
                2858,
                2864,
                2866,
                2867,
                2870,
                2873,
                2877,
                2877,
                2908,
                2909,
                2911,
                2913,
                2949,
                2954,
                2958,
                2960,
                2962,
                2965,
                2969,
                2970,
                2972,
                2972,
                2974,
                2975,
                2979,
                2980,
                2984,
                2986,
                2990,
                2997,
                2999,
                3001,
                3077,
                3084,
                3086,
                3088,
                3090,
                3112,
                3114,
                3123,
                3125,
                3129,
                3168,
                3169,
                3205,
                3212,
                3214,
                3216,
                3218,
                3240,
                3242,
                3251,
                3253,
                3257,
                3294,
                3294,
                3296,
                3297,
                3333,
                3340,
                3342,
                3344,
                3346,
                3368,
                3370,
                3385,
                3424,
                3425,
                3461,
                3478,
                3482,
                3505,
                3507,
                3515,
                3517,
                3517,
                3520,
                3526,
                3585,
                3632,
                3634,
                3635,
                3648,
                3654,
                3713,
                3714,
                3716,
                3716,
                3719,
                3720,
                3722,
                3722,
                3725,
                3725,
                3732,
                3735,
                3737,
                3743,
                3745,
                3747,
                3749,
                3749,
                3751,
                3751,
                3754,
                3755,
                3757,
                3760,
                3762,
                3763,
                3773,
                3773,
                3776,
                3780,
                3782,
                3782,
                3804,
                3805,
                3840,
                3840,
                3904,
                3911,
                3913,
                3946,
                3976,
                3979,
                4096,
                4129,
                4131,
                4135,
                4137,
                4138,
                4176,
                4181,
                4256,
                4293,
                4304,
                4342,
                4352,
                4441,
                4447,
                4514,
                4520,
                4601,
                4608,
                4614,
                4616,
                4678,
                4680,
                4680,
                4682,
                4685,
                4688,
                4694,
                4696,
                4696,
                4698,
                4701,
                4704,
                4742,
                4744,
                4744,
                4746,
                4749,
                4752,
                4782,
                4784,
                4784,
                4786,
                4789,
                4792,
                4798,
                4800,
                4800,
                4802,
                4805,
                4808,
                4814,
                4816,
                4822,
                4824,
                4846,
                4848,
                4878,
                4880,
                4880,
                4882,
                4885,
                4888,
                4894,
                4896,
                4934,
                4936,
                4954,
                5024,
                5108,
                5121,
                5740,
                5743,
                5750,
                5761,
                5786,
                5792,
                5866,
                6016,
                6067,
                6176,
                6263,
                6272,
                6312,
                7680,
                7835,
                7840,
                7929,
                7936,
                7957,
                7960,
                7965,
                7968,
                8005,
                8008,
                8013,
                8016,
                8023,
                8025,
                8025,
                8027,
                8027,
                8029,
                8029,
                8031,
                8061,
                8064,
                8116,
                8118,
                8124,
                8126,
                8126,
                8130,
                8132,
                8134,
                8140,
                8144,
                8147,
                8150,
                8155,
                8160,
                8172,
                8178,
                8180,
                8182,
                8188,
                8319,
                8319,
                8450,
                8450,
                8455,
                8455,
                8458,
                8467,
                8469,
                8469,
                8473,
                8477,
                8484,
                8484,
                8486,
                8486,
                8488,
                8488,
                8490,
                8493,
                8495,
                8497,
                8499,
                8505,
                8544,
                8579,
                12293,
                12295,
                12321,
                12329,
                12337,
                12341,
                12344,
                12346,
                12353,
                12436,
                12445,
                12446,
                12449,
                12538,
                12540,
                12542,
                12549,
                12588,
                12593,
                12686,
                12704,
                12727,
                13312,
                19893,
                19968,
                40869,
                40960,
                42124,
                44032,
                55203,
                63744,
                64045,
                64256,
                64262,
                64275,
                64279,
                64285,
                64285,
                64287,
                64296,
                64298,
                64310,
                64312,
                64316,
                64318,
                64318,
                64320,
                64321,
                64323,
                64324,
                64326,
                64433,
                64467,
                64829,
                64848,
                64911,
                64914,
                64967,
                65008,
                65019,
                65136,
                65138,
                65140,
                65140,
                65142,
                65276,
                65313,
                65338,
                65345,
                65370,
                65382,
                65470,
                65474,
                65479,
                65482,
                65487,
                65490,
                65495,
                65498,
                65500,
            ];
            var unicodeES3IdentifierPart = [
                170,
                170,
                181,
                181,
                186,
                186,
                192,
                214,
                216,
                246,
                248,
                543,
                546,
                563,
                592,
                685,
                688,
                696,
                699,
                705,
                720,
                721,
                736,
                740,
                750,
                750,
                768,
                846,
                864,
                866,
                890,
                890,
                902,
                902,
                904,
                906,
                908,
                908,
                910,
                929,
                931,
                974,
                976,
                983,
                986,
                1011,
                1024,
                1153,
                1155,
                1158,
                1164,
                1220,
                1223,
                1224,
                1227,
                1228,
                1232,
                1269,
                1272,
                1273,
                1329,
                1366,
                1369,
                1369,
                1377,
                1415,
                1425,
                1441,
                1443,
                1465,
                1467,
                1469,
                1471,
                1471,
                1473,
                1474,
                1476,
                1476,
                1488,
                1514,
                1520,
                1522,
                1569,
                1594,
                1600,
                1621,
                1632,
                1641,
                1648,
                1747,
                1749,
                1756,
                1759,
                1768,
                1770,
                1773,
                1776,
                1788,
                1808,
                1836,
                1840,
                1866,
                1920,
                1968,
                2305,
                2307,
                2309,
                2361,
                2364,
                2381,
                2384,
                2388,
                2392,
                2403,
                2406,
                2415,
                2433,
                2435,
                2437,
                2444,
                2447,
                2448,
                2451,
                2472,
                2474,
                2480,
                2482,
                2482,
                2486,
                2489,
                2492,
                2492,
                2494,
                2500,
                2503,
                2504,
                2507,
                2509,
                2519,
                2519,
                2524,
                2525,
                2527,
                2531,
                2534,
                2545,
                2562,
                2562,
                2565,
                2570,
                2575,
                2576,
                2579,
                2600,
                2602,
                2608,
                2610,
                2611,
                2613,
                2614,
                2616,
                2617,
                2620,
                2620,
                2622,
                2626,
                2631,
                2632,
                2635,
                2637,
                2649,
                2652,
                2654,
                2654,
                2662,
                2676,
                2689,
                2691,
                2693,
                2699,
                2701,
                2701,
                2703,
                2705,
                2707,
                2728,
                2730,
                2736,
                2738,
                2739,
                2741,
                2745,
                2748,
                2757,
                2759,
                2761,
                2763,
                2765,
                2768,
                2768,
                2784,
                2784,
                2790,
                2799,
                2817,
                2819,
                2821,
                2828,
                2831,
                2832,
                2835,
                2856,
                2858,
                2864,
                2866,
                2867,
                2870,
                2873,
                2876,
                2883,
                2887,
                2888,
                2891,
                2893,
                2902,
                2903,
                2908,
                2909,
                2911,
                2913,
                2918,
                2927,
                2946,
                2947,
                2949,
                2954,
                2958,
                2960,
                2962,
                2965,
                2969,
                2970,
                2972,
                2972,
                2974,
                2975,
                2979,
                2980,
                2984,
                2986,
                2990,
                2997,
                2999,
                3001,
                3006,
                3010,
                3014,
                3016,
                3018,
                3021,
                3031,
                3031,
                3047,
                3055,
                3073,
                3075,
                3077,
                3084,
                3086,
                3088,
                3090,
                3112,
                3114,
                3123,
                3125,
                3129,
                3134,
                3140,
                3142,
                3144,
                3146,
                3149,
                3157,
                3158,
                3168,
                3169,
                3174,
                3183,
                3202,
                3203,
                3205,
                3212,
                3214,
                3216,
                3218,
                3240,
                3242,
                3251,
                3253,
                3257,
                3262,
                3268,
                3270,
                3272,
                3274,
                3277,
                3285,
                3286,
                3294,
                3294,
                3296,
                3297,
                3302,
                3311,
                3330,
                3331,
                3333,
                3340,
                3342,
                3344,
                3346,
                3368,
                3370,
                3385,
                3390,
                3395,
                3398,
                3400,
                3402,
                3405,
                3415,
                3415,
                3424,
                3425,
                3430,
                3439,
                3458,
                3459,
                3461,
                3478,
                3482,
                3505,
                3507,
                3515,
                3517,
                3517,
                3520,
                3526,
                3530,
                3530,
                3535,
                3540,
                3542,
                3542,
                3544,
                3551,
                3570,
                3571,
                3585,
                3642,
                3648,
                3662,
                3664,
                3673,
                3713,
                3714,
                3716,
                3716,
                3719,
                3720,
                3722,
                3722,
                3725,
                3725,
                3732,
                3735,
                3737,
                3743,
                3745,
                3747,
                3749,
                3749,
                3751,
                3751,
                3754,
                3755,
                3757,
                3769,
                3771,
                3773,
                3776,
                3780,
                3782,
                3782,
                3784,
                3789,
                3792,
                3801,
                3804,
                3805,
                3840,
                3840,
                3864,
                3865,
                3872,
                3881,
                3893,
                3893,
                3895,
                3895,
                3897,
                3897,
                3902,
                3911,
                3913,
                3946,
                3953,
                3972,
                3974,
                3979,
                3984,
                3991,
                3993,
                4028,
                4038,
                4038,
                4096,
                4129,
                4131,
                4135,
                4137,
                4138,
                4140,
                4146,
                4150,
                4153,
                4160,
                4169,
                4176,
                4185,
                4256,
                4293,
                4304,
                4342,
                4352,
                4441,
                4447,
                4514,
                4520,
                4601,
                4608,
                4614,
                4616,
                4678,
                4680,
                4680,
                4682,
                4685,
                4688,
                4694,
                4696,
                4696,
                4698,
                4701,
                4704,
                4742,
                4744,
                4744,
                4746,
                4749,
                4752,
                4782,
                4784,
                4784,
                4786,
                4789,
                4792,
                4798,
                4800,
                4800,
                4802,
                4805,
                4808,
                4814,
                4816,
                4822,
                4824,
                4846,
                4848,
                4878,
                4880,
                4880,
                4882,
                4885,
                4888,
                4894,
                4896,
                4934,
                4936,
                4954,
                4969,
                4977,
                5024,
                5108,
                5121,
                5740,
                5743,
                5750,
                5761,
                5786,
                5792,
                5866,
                6016,
                6099,
                6112,
                6121,
                6160,
                6169,
                6176,
                6263,
                6272,
                6313,
                7680,
                7835,
                7840,
                7929,
                7936,
                7957,
                7960,
                7965,
                7968,
                8005,
                8008,
                8013,
                8016,
                8023,
                8025,
                8025,
                8027,
                8027,
                8029,
                8029,
                8031,
                8061,
                8064,
                8116,
                8118,
                8124,
                8126,
                8126,
                8130,
                8132,
                8134,
                8140,
                8144,
                8147,
                8150,
                8155,
                8160,
                8172,
                8178,
                8180,
                8182,
                8188,
                8255,
                8256,
                8319,
                8319,
                8400,
                8412,
                8417,
                8417,
                8450,
                8450,
                8455,
                8455,
                8458,
                8467,
                8469,
                8469,
                8473,
                8477,
                8484,
                8484,
                8486,
                8486,
                8488,
                8488,
                8490,
                8493,
                8495,
                8497,
                8499,
                8505,
                8544,
                8579,
                12293,
                12295,
                12321,
                12335,
                12337,
                12341,
                12344,
                12346,
                12353,
                12436,
                12441,
                12442,
                12445,
                12446,
                12449,
                12542,
                12549,
                12588,
                12593,
                12686,
                12704,
                12727,
                13312,
                19893,
                19968,
                40869,
                40960,
                42124,
                44032,
                55203,
                63744,
                64045,
                64256,
                64262,
                64275,
                64279,
                64285,
                64296,
                64298,
                64310,
                64312,
                64316,
                64318,
                64318,
                64320,
                64321,
                64323,
                64324,
                64326,
                64433,
                64467,
                64829,
                64848,
                64911,
                64914,
                64967,
                65008,
                65019,
                65056,
                65059,
                65075,
                65076,
                65101,
                65103,
                65136,
                65138,
                65140,
                65140,
                65142,
                65276,
                65296,
                65305,
                65313,
                65338,
                65343,
                65343,
                65345,
                65370,
                65381,
                65470,
                65474,
                65479,
                65482,
                65487,
                65490,
                65495,
                65498,
                65500,
            ];
            var unicodeES5IdentifierStart = [
                170,
                170,
                181,
                181,
                186,
                186,
                192,
                214,
                216,
                246,
                248,
                705,
                710,
                721,
                736,
                740,
                748,
                748,
                750,
                750,
                880,
                884,
                886,
                887,
                890,
                893,
                902,
                902,
                904,
                906,
                908,
                908,
                910,
                929,
                931,
                1013,
                1015,
                1153,
                1162,
                1319,
                1329,
                1366,
                1369,
                1369,
                1377,
                1415,
                1488,
                1514,
                1520,
                1522,
                1568,
                1610,
                1646,
                1647,
                1649,
                1747,
                1749,
                1749,
                1765,
                1766,
                1774,
                1775,
                1786,
                1788,
                1791,
                1791,
                1808,
                1808,
                1810,
                1839,
                1869,
                1957,
                1969,
                1969,
                1994,
                2026,
                2036,
                2037,
                2042,
                2042,
                2048,
                2069,
                2074,
                2074,
                2084,
                2084,
                2088,
                2088,
                2112,
                2136,
                2208,
                2208,
                2210,
                2220,
                2308,
                2361,
                2365,
                2365,
                2384,
                2384,
                2392,
                2401,
                2417,
                2423,
                2425,
                2431,
                2437,
                2444,
                2447,
                2448,
                2451,
                2472,
                2474,
                2480,
                2482,
                2482,
                2486,
                2489,
                2493,
                2493,
                2510,
                2510,
                2524,
                2525,
                2527,
                2529,
                2544,
                2545,
                2565,
                2570,
                2575,
                2576,
                2579,
                2600,
                2602,
                2608,
                2610,
                2611,
                2613,
                2614,
                2616,
                2617,
                2649,
                2652,
                2654,
                2654,
                2674,
                2676,
                2693,
                2701,
                2703,
                2705,
                2707,
                2728,
                2730,
                2736,
                2738,
                2739,
                2741,
                2745,
                2749,
                2749,
                2768,
                2768,
                2784,
                2785,
                2821,
                2828,
                2831,
                2832,
                2835,
                2856,
                2858,
                2864,
                2866,
                2867,
                2869,
                2873,
                2877,
                2877,
                2908,
                2909,
                2911,
                2913,
                2929,
                2929,
                2947,
                2947,
                2949,
                2954,
                2958,
                2960,
                2962,
                2965,
                2969,
                2970,
                2972,
                2972,
                2974,
                2975,
                2979,
                2980,
                2984,
                2986,
                2990,
                3001,
                3024,
                3024,
                3077,
                3084,
                3086,
                3088,
                3090,
                3112,
                3114,
                3123,
                3125,
                3129,
                3133,
                3133,
                3160,
                3161,
                3168,
                3169,
                3205,
                3212,
                3214,
                3216,
                3218,
                3240,
                3242,
                3251,
                3253,
                3257,
                3261,
                3261,
                3294,
                3294,
                3296,
                3297,
                3313,
                3314,
                3333,
                3340,
                3342,
                3344,
                3346,
                3386,
                3389,
                3389,
                3406,
                3406,
                3424,
                3425,
                3450,
                3455,
                3461,
                3478,
                3482,
                3505,
                3507,
                3515,
                3517,
                3517,
                3520,
                3526,
                3585,
                3632,
                3634,
                3635,
                3648,
                3654,
                3713,
                3714,
                3716,
                3716,
                3719,
                3720,
                3722,
                3722,
                3725,
                3725,
                3732,
                3735,
                3737,
                3743,
                3745,
                3747,
                3749,
                3749,
                3751,
                3751,
                3754,
                3755,
                3757,
                3760,
                3762,
                3763,
                3773,
                3773,
                3776,
                3780,
                3782,
                3782,
                3804,
                3807,
                3840,
                3840,
                3904,
                3911,
                3913,
                3948,
                3976,
                3980,
                4096,
                4138,
                4159,
                4159,
                4176,
                4181,
                4186,
                4189,
                4193,
                4193,
                4197,
                4198,
                4206,
                4208,
                4213,
                4225,
                4238,
                4238,
                4256,
                4293,
                4295,
                4295,
                4301,
                4301,
                4304,
                4346,
                4348,
                4680,
                4682,
                4685,
                4688,
                4694,
                4696,
                4696,
                4698,
                4701,
                4704,
                4744,
                4746,
                4749,
                4752,
                4784,
                4786,
                4789,
                4792,
                4798,
                4800,
                4800,
                4802,
                4805,
                4808,
                4822,
                4824,
                4880,
                4882,
                4885,
                4888,
                4954,
                4992,
                5007,
                5024,
                5108,
                5121,
                5740,
                5743,
                5759,
                5761,
                5786,
                5792,
                5866,
                5870,
                5872,
                5888,
                5900,
                5902,
                5905,
                5920,
                5937,
                5952,
                5969,
                5984,
                5996,
                5998,
                6000,
                6016,
                6067,
                6103,
                6103,
                6108,
                6108,
                6176,
                6263,
                6272,
                6312,
                6314,
                6314,
                6320,
                6389,
                6400,
                6428,
                6480,
                6509,
                6512,
                6516,
                6528,
                6571,
                6593,
                6599,
                6656,
                6678,
                6688,
                6740,
                6823,
                6823,
                6917,
                6963,
                6981,
                6987,
                7043,
                7072,
                7086,
                7087,
                7098,
                7141,
                7168,
                7203,
                7245,
                7247,
                7258,
                7293,
                7401,
                7404,
                7406,
                7409,
                7413,
                7414,
                7424,
                7615,
                7680,
                7957,
                7960,
                7965,
                7968,
                8005,
                8008,
                8013,
                8016,
                8023,
                8025,
                8025,
                8027,
                8027,
                8029,
                8029,
                8031,
                8061,
                8064,
                8116,
                8118,
                8124,
                8126,
                8126,
                8130,
                8132,
                8134,
                8140,
                8144,
                8147,
                8150,
                8155,
                8160,
                8172,
                8178,
                8180,
                8182,
                8188,
                8305,
                8305,
                8319,
                8319,
                8336,
                8348,
                8450,
                8450,
                8455,
                8455,
                8458,
                8467,
                8469,
                8469,
                8473,
                8477,
                8484,
                8484,
                8486,
                8486,
                8488,
                8488,
                8490,
                8493,
                8495,
                8505,
                8508,
                8511,
                8517,
                8521,
                8526,
                8526,
                8544,
                8584,
                11264,
                11310,
                11312,
                11358,
                11360,
                11492,
                11499,
                11502,
                11506,
                11507,
                11520,
                11557,
                11559,
                11559,
                11565,
                11565,
                11568,
                11623,
                11631,
                11631,
                11648,
                11670,
                11680,
                11686,
                11688,
                11694,
                11696,
                11702,
                11704,
                11710,
                11712,
                11718,
                11720,
                11726,
                11728,
                11734,
                11736,
                11742,
                11823,
                11823,
                12293,
                12295,
                12321,
                12329,
                12337,
                12341,
                12344,
                12348,
                12353,
                12438,
                12445,
                12447,
                12449,
                12538,
                12540,
                12543,
                12549,
                12589,
                12593,
                12686,
                12704,
                12730,
                12784,
                12799,
                13312,
                19893,
                19968,
                40908,
                40960,
                42124,
                42192,
                42237,
                42240,
                42508,
                42512,
                42527,
                42538,
                42539,
                42560,
                42606,
                42623,
                42647,
                42656,
                42735,
                42775,
                42783,
                42786,
                42888,
                42891,
                42894,
                42896,
                42899,
                42912,
                42922,
                43000,
                43009,
                43011,
                43013,
                43015,
                43018,
                43020,
                43042,
                43072,
                43123,
                43138,
                43187,
                43250,
                43255,
                43259,
                43259,
                43274,
                43301,
                43312,
                43334,
                43360,
                43388,
                43396,
                43442,
                43471,
                43471,
                43520,
                43560,
                43584,
                43586,
                43588,
                43595,
                43616,
                43638,
                43642,
                43642,
                43648,
                43695,
                43697,
                43697,
                43701,
                43702,
                43705,
                43709,
                43712,
                43712,
                43714,
                43714,
                43739,
                43741,
                43744,
                43754,
                43762,
                43764,
                43777,
                43782,
                43785,
                43790,
                43793,
                43798,
                43808,
                43814,
                43816,
                43822,
                43968,
                44002,
                44032,
                55203,
                55216,
                55238,
                55243,
                55291,
                63744,
                64109,
                64112,
                64217,
                64256,
                64262,
                64275,
                64279,
                64285,
                64285,
                64287,
                64296,
                64298,
                64310,
                64312,
                64316,
                64318,
                64318,
                64320,
                64321,
                64323,
                64324,
                64326,
                64433,
                64467,
                64829,
                64848,
                64911,
                64914,
                64967,
                65008,
                65019,
                65136,
                65140,
                65142,
                65276,
                65313,
                65338,
                65345,
                65370,
                65382,
                65470,
                65474,
                65479,
                65482,
                65487,
                65490,
                65495,
                65498,
                65500,
            ];
            var unicodeES5IdentifierPart = [
                170,
                170,
                181,
                181,
                186,
                186,
                192,
                214,
                216,
                246,
                248,
                705,
                710,
                721,
                736,
                740,
                748,
                748,
                750,
                750,
                768,
                884,
                886,
                887,
                890,
                893,
                902,
                902,
                904,
                906,
                908,
                908,
                910,
                929,
                931,
                1013,
                1015,
                1153,
                1155,
                1159,
                1162,
                1319,
                1329,
                1366,
                1369,
                1369,
                1377,
                1415,
                1425,
                1469,
                1471,
                1471,
                1473,
                1474,
                1476,
                1477,
                1479,
                1479,
                1488,
                1514,
                1520,
                1522,
                1552,
                1562,
                1568,
                1641,
                1646,
                1747,
                1749,
                1756,
                1759,
                1768,
                1770,
                1788,
                1791,
                1791,
                1808,
                1866,
                1869,
                1969,
                1984,
                2037,
                2042,
                2042,
                2048,
                2093,
                2112,
                2139,
                2208,
                2208,
                2210,
                2220,
                2276,
                2302,
                2304,
                2403,
                2406,
                2415,
                2417,
                2423,
                2425,
                2431,
                2433,
                2435,
                2437,
                2444,
                2447,
                2448,
                2451,
                2472,
                2474,
                2480,
                2482,
                2482,
                2486,
                2489,
                2492,
                2500,
                2503,
                2504,
                2507,
                2510,
                2519,
                2519,
                2524,
                2525,
                2527,
                2531,
                2534,
                2545,
                2561,
                2563,
                2565,
                2570,
                2575,
                2576,
                2579,
                2600,
                2602,
                2608,
                2610,
                2611,
                2613,
                2614,
                2616,
                2617,
                2620,
                2620,
                2622,
                2626,
                2631,
                2632,
                2635,
                2637,
                2641,
                2641,
                2649,
                2652,
                2654,
                2654,
                2662,
                2677,
                2689,
                2691,
                2693,
                2701,
                2703,
                2705,
                2707,
                2728,
                2730,
                2736,
                2738,
                2739,
                2741,
                2745,
                2748,
                2757,
                2759,
                2761,
                2763,
                2765,
                2768,
                2768,
                2784,
                2787,
                2790,
                2799,
                2817,
                2819,
                2821,
                2828,
                2831,
                2832,
                2835,
                2856,
                2858,
                2864,
                2866,
                2867,
                2869,
                2873,
                2876,
                2884,
                2887,
                2888,
                2891,
                2893,
                2902,
                2903,
                2908,
                2909,
                2911,
                2915,
                2918,
                2927,
                2929,
                2929,
                2946,
                2947,
                2949,
                2954,
                2958,
                2960,
                2962,
                2965,
                2969,
                2970,
                2972,
                2972,
                2974,
                2975,
                2979,
                2980,
                2984,
                2986,
                2990,
                3001,
                3006,
                3010,
                3014,
                3016,
                3018,
                3021,
                3024,
                3024,
                3031,
                3031,
                3046,
                3055,
                3073,
                3075,
                3077,
                3084,
                3086,
                3088,
                3090,
                3112,
                3114,
                3123,
                3125,
                3129,
                3133,
                3140,
                3142,
                3144,
                3146,
                3149,
                3157,
                3158,
                3160,
                3161,
                3168,
                3171,
                3174,
                3183,
                3202,
                3203,
                3205,
                3212,
                3214,
                3216,
                3218,
                3240,
                3242,
                3251,
                3253,
                3257,
                3260,
                3268,
                3270,
                3272,
                3274,
                3277,
                3285,
                3286,
                3294,
                3294,
                3296,
                3299,
                3302,
                3311,
                3313,
                3314,
                3330,
                3331,
                3333,
                3340,
                3342,
                3344,
                3346,
                3386,
                3389,
                3396,
                3398,
                3400,
                3402,
                3406,
                3415,
                3415,
                3424,
                3427,
                3430,
                3439,
                3450,
                3455,
                3458,
                3459,
                3461,
                3478,
                3482,
                3505,
                3507,
                3515,
                3517,
                3517,
                3520,
                3526,
                3530,
                3530,
                3535,
                3540,
                3542,
                3542,
                3544,
                3551,
                3570,
                3571,
                3585,
                3642,
                3648,
                3662,
                3664,
                3673,
                3713,
                3714,
                3716,
                3716,
                3719,
                3720,
                3722,
                3722,
                3725,
                3725,
                3732,
                3735,
                3737,
                3743,
                3745,
                3747,
                3749,
                3749,
                3751,
                3751,
                3754,
                3755,
                3757,
                3769,
                3771,
                3773,
                3776,
                3780,
                3782,
                3782,
                3784,
                3789,
                3792,
                3801,
                3804,
                3807,
                3840,
                3840,
                3864,
                3865,
                3872,
                3881,
                3893,
                3893,
                3895,
                3895,
                3897,
                3897,
                3902,
                3911,
                3913,
                3948,
                3953,
                3972,
                3974,
                3991,
                3993,
                4028,
                4038,
                4038,
                4096,
                4169,
                4176,
                4253,
                4256,
                4293,
                4295,
                4295,
                4301,
                4301,
                4304,
                4346,
                4348,
                4680,
                4682,
                4685,
                4688,
                4694,
                4696,
                4696,
                4698,
                4701,
                4704,
                4744,
                4746,
                4749,
                4752,
                4784,
                4786,
                4789,
                4792,
                4798,
                4800,
                4800,
                4802,
                4805,
                4808,
                4822,
                4824,
                4880,
                4882,
                4885,
                4888,
                4954,
                4957,
                4959,
                4992,
                5007,
                5024,
                5108,
                5121,
                5740,
                5743,
                5759,
                5761,
                5786,
                5792,
                5866,
                5870,
                5872,
                5888,
                5900,
                5902,
                5908,
                5920,
                5940,
                5952,
                5971,
                5984,
                5996,
                5998,
                6000,
                6002,
                6003,
                6016,
                6099,
                6103,
                6103,
                6108,
                6109,
                6112,
                6121,
                6155,
                6157,
                6160,
                6169,
                6176,
                6263,
                6272,
                6314,
                6320,
                6389,
                6400,
                6428,
                6432,
                6443,
                6448,
                6459,
                6470,
                6509,
                6512,
                6516,
                6528,
                6571,
                6576,
                6601,
                6608,
                6617,
                6656,
                6683,
                6688,
                6750,
                6752,
                6780,
                6783,
                6793,
                6800,
                6809,
                6823,
                6823,
                6912,
                6987,
                6992,
                7001,
                7019,
                7027,
                7040,
                7155,
                7168,
                7223,
                7232,
                7241,
                7245,
                7293,
                7376,
                7378,
                7380,
                7414,
                7424,
                7654,
                7676,
                7957,
                7960,
                7965,
                7968,
                8005,
                8008,
                8013,
                8016,
                8023,
                8025,
                8025,
                8027,
                8027,
                8029,
                8029,
                8031,
                8061,
                8064,
                8116,
                8118,
                8124,
                8126,
                8126,
                8130,
                8132,
                8134,
                8140,
                8144,
                8147,
                8150,
                8155,
                8160,
                8172,
                8178,
                8180,
                8182,
                8188,
                8204,
                8205,
                8255,
                8256,
                8276,
                8276,
                8305,
                8305,
                8319,
                8319,
                8336,
                8348,
                8400,
                8412,
                8417,
                8417,
                8421,
                8432,
                8450,
                8450,
                8455,
                8455,
                8458,
                8467,
                8469,
                8469,
                8473,
                8477,
                8484,
                8484,
                8486,
                8486,
                8488,
                8488,
                8490,
                8493,
                8495,
                8505,
                8508,
                8511,
                8517,
                8521,
                8526,
                8526,
                8544,
                8584,
                11264,
                11310,
                11312,
                11358,
                11360,
                11492,
                11499,
                11507,
                11520,
                11557,
                11559,
                11559,
                11565,
                11565,
                11568,
                11623,
                11631,
                11631,
                11647,
                11670,
                11680,
                11686,
                11688,
                11694,
                11696,
                11702,
                11704,
                11710,
                11712,
                11718,
                11720,
                11726,
                11728,
                11734,
                11736,
                11742,
                11744,
                11775,
                11823,
                11823,
                12293,
                12295,
                12321,
                12335,
                12337,
                12341,
                12344,
                12348,
                12353,
                12438,
                12441,
                12442,
                12445,
                12447,
                12449,
                12538,
                12540,
                12543,
                12549,
                12589,
                12593,
                12686,
                12704,
                12730,
                12784,
                12799,
                13312,
                19893,
                19968,
                40908,
                40960,
                42124,
                42192,
                42237,
                42240,
                42508,
                42512,
                42539,
                42560,
                42607,
                42612,
                42621,
                42623,
                42647,
                42655,
                42737,
                42775,
                42783,
                42786,
                42888,
                42891,
                42894,
                42896,
                42899,
                42912,
                42922,
                43000,
                43047,
                43072,
                43123,
                43136,
                43204,
                43216,
                43225,
                43232,
                43255,
                43259,
                43259,
                43264,
                43309,
                43312,
                43347,
                43360,
                43388,
                43392,
                43456,
                43471,
                43481,
                43520,
                43574,
                43584,
                43597,
                43600,
                43609,
                43616,
                43638,
                43642,
                43643,
                43648,
                43714,
                43739,
                43741,
                43744,
                43759,
                43762,
                43766,
                43777,
                43782,
                43785,
                43790,
                43793,
                43798,
                43808,
                43814,
                43816,
                43822,
                43968,
                44010,
                44012,
                44013,
                44016,
                44025,
                44032,
                55203,
                55216,
                55238,
                55243,
                55291,
                63744,
                64109,
                64112,
                64217,
                64256,
                64262,
                64275,
                64279,
                64285,
                64296,
                64298,
                64310,
                64312,
                64316,
                64318,
                64318,
                64320,
                64321,
                64323,
                64324,
                64326,
                64433,
                64467,
                64829,
                64848,
                64911,
                64914,
                64967,
                65008,
                65019,
                65024,
                65039,
                65056,
                65062,
                65075,
                65076,
                65101,
                65103,
                65136,
                65140,
                65142,
                65276,
                65296,
                65305,
                65313,
                65338,
                65343,
                65343,
                65345,
                65370,
                65382,
                65470,
                65474,
                65479,
                65482,
                65487,
                65490,
                65495,
                65498,
                65500,
            ];
            function lookupInUnicodeMap(code, map) {
                if (code < map[0]) {
                    return false;
                }
                var lo = 0;
                var hi = map.length;
                var mid;
                while (lo + 1 < hi) {
                    mid = lo + (hi - lo) / 2;
                    mid -= mid % 2;
                    if (map[mid] <= code && code <= map[mid + 1]) {
                        return true;
                    }
                    if (code < map[mid]) {
                        hi = mid;
                    }
                    else {
                        lo = mid + 2;
                    }
                }
                return false;
            }
            function isUnicodeIdentifierStart(code, languageVersion) {
                return languageVersion >= 1 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : lookupInUnicodeMap(code, unicodeES3IdentifierStart);
            }
            ts.isUnicodeIdentifierStart = isUnicodeIdentifierStart;
            function isUnicodeIdentifierPart(code, languageVersion) {
                return languageVersion >= 1 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : lookupInUnicodeMap(code, unicodeES3IdentifierPart);
            }
            function makeReverseMap(source) {
                var result = [];
                for (var name in source) {
                    if (source.hasOwnProperty(name)) {
                        result[source[name]] = name;
                    }
                }
                return result;
            }
            var tokenStrings = makeReverseMap(textToToken);
            function tokenToString(t) {
                return tokenStrings[t];
            }
            ts.tokenToString = tokenToString;
            function computeLineStarts(text) {
                var result = new Array();
                var pos = 0;
                var lineStart = 0;
                while (pos < text.length) {
                    var ch = text.charCodeAt(pos++);
                    switch (ch) {
                        case 13:
                            if (text.charCodeAt(pos) === 10) {
                                pos++;
                            }
                        case 10:
                            result.push(lineStart);
                            lineStart = pos;
                            break;
                        default:
                            if (ch > 127 && isLineBreak(ch)) {
                                result.push(lineStart);
                                lineStart = pos;
                            }
                            break;
                    }
                }
                result.push(lineStart);
                return result;
            }
            ts.computeLineStarts = computeLineStarts;
            function getPositionOfLineAndCharacter(sourceFile, line, character) {
                return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character);
            }
            ts.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter;
            function computePositionOfLineAndCharacter(lineStarts, line, character) {
                ts.Debug.assert(line >= 0 && line < lineStarts.length);
                return lineStarts[line] + character;
            }
            ts.computePositionOfLineAndCharacter = computePositionOfLineAndCharacter;
            function getLineStarts(sourceFile) {
                return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
            }
            ts.getLineStarts = getLineStarts;
            function computeLineAndCharacterOfPosition(lineStarts, position) {
                var lineNumber = ts.binarySearch(lineStarts, position);
                if (lineNumber < 0) {
                    lineNumber = ~lineNumber - 1;
                }
                return {
                    line: lineNumber,
                    character: position - lineStarts[lineNumber]
                };
            }
            ts.computeLineAndCharacterOfPosition = computeLineAndCharacterOfPosition;
            function getLineAndCharacterOfPosition(sourceFile, position) {
                return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
            }
            ts.getLineAndCharacterOfPosition = getLineAndCharacterOfPosition;
            var hasOwnProperty = Object.prototype.hasOwnProperty;
            function isWhiteSpace(ch) {
                return ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 5760 || ch >= 8192 && ch <= 8203 || ch === 8239 || ch === 8287 || ch === 12288 || ch === 65279;
            }
            ts.isWhiteSpace = isWhiteSpace;
            function isLineBreak(ch) {
                return ch === 10 || ch === 13 || ch === 8232 || ch === 8233 || ch === 133;
            }
            ts.isLineBreak = isLineBreak;
            function isDigit(ch) {
                return ch >= 48 && ch <= 57;
            }
            function isOctalDigit(ch) {
                return ch >= 48 && ch <= 55;
            }
            ts.isOctalDigit = isOctalDigit;
            function skipTrivia(text, pos, stopAfterLineBreak) {
                while (true) {
                    var ch = text.charCodeAt(pos);
                    switch (ch) {
                        case 13:
                            if (text.charCodeAt(pos + 1) === 10) {
                                pos++;
                            }
                        case 10:
                            pos++;
                            if (stopAfterLineBreak) {
                                return pos;
                            }
                            continue;
                        case 9:
                        case 11:
                        case 12:
                        case 32:
                            pos++;
                            continue;
                        case 47:
                            if (text.charCodeAt(pos + 1) === 47) {
                                pos += 2;
                                while (pos < text.length) {
                                    if (isLineBreak(text.charCodeAt(pos))) {
                                        break;
                                    }
                                    pos++;
                                }
                                continue;
                            }
                            if (text.charCodeAt(pos + 1) === 42) {
                                pos += 2;
                                while (pos < text.length) {
                                    if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) {
                                        pos += 2;
                                        break;
                                    }
                                    pos++;
                                }
                                continue;
                            }
                            break;
                        case 60:
                        case 61:
                        case 62:
                            if (isConflictMarkerTrivia(text, pos)) {
                                pos = scanConflictMarkerTrivia(text, pos);
                                continue;
                            }
                            break;
                        default:
                            if (ch > 127 && (isWhiteSpace(ch) || isLineBreak(ch))) {
                                pos++;
                                continue;
                            }
                            break;
                    }
                    return pos;
                }
            }
            ts.skipTrivia = skipTrivia;
            var mergeConflictMarkerLength = "<<<<<<<".length;
            function isConflictMarkerTrivia(text, pos) {
                ts.Debug.assert(pos >= 0);
                if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
                    var ch = text.charCodeAt(pos);
                    if ((pos + mergeConflictMarkerLength) < text.length) {
                        for (var i = 0, n = mergeConflictMarkerLength; i < n; i++) {
                            if (text.charCodeAt(pos + i) !== ch) {
                                return false;
                            }
                        }
                        return ch === 61 || text.charCodeAt(pos + mergeConflictMarkerLength) === 32;
                    }
                }
                return false;
            }
            function scanConflictMarkerTrivia(text, pos, error) {
                if (error) {
                    error(ts.Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
                }
                var ch = text.charCodeAt(pos);
                var len = text.length;
                if (ch === 60 || ch === 62) {
                    while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
                        pos++;
                    }
                }
                else {
                    ts.Debug.assert(ch === 61);
                    while (pos < len) {
                        var ch = text.charCodeAt(pos);
                        if (ch === 62 && isConflictMarkerTrivia(text, pos)) {
                            break;
                        }
                        pos++;
                    }
                }
                return pos;
            }
            function getCommentRanges(text, pos, trailing) {
                var result;
                var collecting = trailing || pos === 0;
                while (true) {
                    var ch = text.charCodeAt(pos);
                    switch (ch) {
                        case 13:
                            if (text.charCodeAt(pos + 1) === 10)
                                pos++;
                        case 10:
                            pos++;
                            if (trailing) {
                                return result;
                            }
                            collecting = true;
                            if (result && result.length) {
                                result[result.length - 1].hasTrailingNewLine = true;
                            }
                            continue;
                        case 9:
                        case 11:
                        case 12:
                        case 32:
                            pos++;
                            continue;
                        case 47:
                            var nextChar = text.charCodeAt(pos + 1);
                            var hasTrailingNewLine = false;
                            if (nextChar === 47 || nextChar === 42) {
                                var startPos = pos;
                                pos += 2;
                                if (nextChar === 47) {
                                    while (pos < text.length) {
                                        if (isLineBreak(text.charCodeAt(pos))) {
                                            hasTrailingNewLine = true;
                                            break;
                                        }
                                        pos++;
                                    }
                                }
                                else {
                                    while (pos < text.length) {
                                        if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) {
                                            pos += 2;
                                            break;
                                        }
                                        pos++;
                                    }
                                }
                                if (collecting) {
                                    if (!result)
                                        result = [];
                                    result.push({
                                        pos: startPos,
                                        end: pos,
                                        hasTrailingNewLine: hasTrailingNewLine
                                    });
                                }
                                continue;
                            }
                            break;
                        default:
                            if (ch > 127 && (isWhiteSpace(ch) || isLineBreak(ch))) {
                                if (result && result.length && isLineBreak(ch)) {
                                    result[result.length - 1].hasTrailingNewLine = true;
                                }
                                pos++;
                                continue;
                            }
                            break;
                    }
                    return result;
                }
            }
            function getLeadingCommentRanges(text, pos) {
                return getCommentRanges(text, pos, false);
            }
            ts.getLeadingCommentRanges = getLeadingCommentRanges;
            function getTrailingCommentRanges(text, pos) {
                return getCommentRanges(text, pos, true);
            }
            ts.getTrailingCommentRanges = getTrailingCommentRanges;
            function isIdentifierStart(ch, languageVersion) {
                return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch === 36 || ch === 95 || ch > 127 && isUnicodeIdentifierStart(ch, languageVersion);
            }
            ts.isIdentifierStart = isIdentifierStart;
            function isIdentifierPart(ch, languageVersion) {
                return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 48 && ch <= 57 || ch === 36 || ch === 95 || ch > 127 && isUnicodeIdentifierPart(ch, languageVersion);
            }
            ts.isIdentifierPart = isIdentifierPart;
            function createScanner(languageVersion, skipTrivia, text, onError) {
                var pos;
                var len;
                var startPos;
                var tokenPos;
                var token;
                var tokenValue;
                var precedingLineBreak;
                var hasExtendedUnicodeEscape;
                var tokenIsUnterminated;
                function error(message, length) {
                    if (onError) {
                        onError(message, length || 0);
                    }
                }
                function isIdentifierStart(ch) {
                    return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch === 36 || ch === 95 || ch > 127 && isUnicodeIdentifierStart(ch, languageVersion);
                }
                function isIdentifierPart(ch) {
                    return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 48 && ch <= 57 || ch === 36 || ch === 95 || ch > 127 && isUnicodeIdentifierPart(ch, languageVersion);
                }
                function scanNumber() {
                    var start = pos;
                    while (isDigit(text.charCodeAt(pos)))
                        pos++;
                    if (text.charCodeAt(pos) === 46) {
                        pos++;
                        while (isDigit(text.charCodeAt(pos)))
                            pos++;
                    }
                    var end = pos;
                    if (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101) {
                        pos++;
                        if (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45)
                            pos++;
                        if (isDigit(text.charCodeAt(pos))) {
                            pos++;
                            while (isDigit(text.charCodeAt(pos)))
                                pos++;
                            end = pos;
                        }
                        else {
                            error(ts.Diagnostics.Digit_expected);
                        }
                    }
                    return +(text.substring(start, end));
                }
                function scanOctalDigits() {
                    var start = pos;
                    while (isOctalDigit(text.charCodeAt(pos))) {
                        pos++;
                    }
                    return +(text.substring(start, pos));
                }
                function scanExactNumberOfHexDigits(count) {
                    return scanHexDigits(count, false);
                }
                function scanMinimumNumberOfHexDigits(count) {
                    return scanHexDigits(count, true);
                }
                function scanHexDigits(minCount, scanAsManyAsPossible) {
                    var digits = 0;
                    var value = 0;
                    while (digits < minCount || scanAsManyAsPossible) {
                        var ch = text.charCodeAt(pos);
                        if (ch >= 48 && ch <= 57) {
                            value = value * 16 + ch - 48;
                        }
                        else if (ch >= 65 && ch <= 70) {
                            value = value * 16 + ch - 65 + 10;
                        }
                        else if (ch >= 97 && ch <= 102) {
                            value = value * 16 + ch - 97 + 10;
                        }
                        else {
                            break;
                        }
                        pos++;
                        digits++;
                    }
                    if (digits < minCount) {
                        value = -1;
                    }
                    return value;
                }
                function scanString() {
                    var quote = text.charCodeAt(pos++);
                    var result = "";
                    var start = pos;
                    while (true) {
                        if (pos >= len) {
                            result += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_string_literal);
                            break;
                        }
                        var ch = text.charCodeAt(pos);
                        if (ch === quote) {
                            result += text.substring(start, pos);
                            pos++;
                            break;
                        }
                        if (ch === 92) {
                            result += text.substring(start, pos);
                            result += scanEscapeSequence();
                            start = pos;
                            continue;
                        }
                        if (isLineBreak(ch)) {
                            result += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_string_literal);
                            break;
                        }
                        pos++;
                    }
                    return result;
                }
                function scanTemplateAndSetTokenValue() {
                    var startedWithBacktick = text.charCodeAt(pos) === 96;
                    pos++;
                    var start = pos;
                    var contents = "";
                    var resultingToken;
                    while (true) {
                        if (pos >= len) {
                            contents += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_template_literal);
                            resultingToken = startedWithBacktick ? 10 : 13;
                            break;
                        }
                        var currChar = text.charCodeAt(pos);
                        if (currChar === 96) {
                            contents += text.substring(start, pos);
                            pos++;
                            resultingToken = startedWithBacktick ? 10 : 13;
                            break;
                        }
                        if (currChar === 36 && pos + 1 < len && text.charCodeAt(pos + 1) === 123) {
                            contents += text.substring(start, pos);
                            pos += 2;
                            resultingToken = startedWithBacktick ? 11 : 12;
                            break;
                        }
                        if (currChar === 92) {
                            contents += text.substring(start, pos);
                            contents += scanEscapeSequence();
                            start = pos;
                            continue;
                        }
                        if (currChar === 13) {
                            contents += text.substring(start, pos);
                            pos++;
                            if (pos < len && text.charCodeAt(pos) === 10) {
                                pos++;
                            }
                            contents += "\n";
                            start = pos;
                            continue;
                        }
                        pos++;
                    }
                    ts.Debug.assert(resultingToken !== undefined);
                    tokenValue = contents;
                    return resultingToken;
                }
                function scanEscapeSequence() {
                    pos++;
                    if (pos >= len) {
                        error(ts.Diagnostics.Unexpected_end_of_text);
                        return "";
                    }
                    var ch = text.charCodeAt(pos++);
                    switch (ch) {
                        case 48:
                            return "\0";
                        case 98:
                            return "\b";
                        case 116:
                            return "\t";
                        case 110:
                            return "\n";
                        case 118:
                            return "\v";
                        case 102:
                            return "\f";
                        case 114:
                            return "\r";
                        case 39:
                            return "\'";
                        case 34:
                            return "\"";
                        case 117:
                            if (pos < len && text.charCodeAt(pos) === 123) {
                                hasExtendedUnicodeEscape = true;
                                pos++;
                                return scanExtendedUnicodeEscape();
                            }
                            return scanHexadecimalEscape(4);
                        case 120:
                            return scanHexadecimalEscape(2);
                        case 13:
                            if (pos < len && text.charCodeAt(pos) === 10) {
                                pos++;
                            }
                        case 10:
                        case 8232:
                        case 8233:
                            return "";
                        default:
                            return String.fromCharCode(ch);
                    }
                }
                function scanHexadecimalEscape(numDigits) {
                    var escapedValue = scanExactNumberOfHexDigits(numDigits);
                    if (escapedValue >= 0) {
                        return String.fromCharCode(escapedValue);
                    }
                    else {
                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                        return "";
                    }
                }
                function scanExtendedUnicodeEscape() {
                    var escapedValue = scanMinimumNumberOfHexDigits(1);
                    var isInvalidExtendedEscape = false;
                    if (escapedValue < 0) {
                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                        isInvalidExtendedEscape = true;
                    }
                    else if (escapedValue > 0x10FFFF) {
                        error(ts.Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive);
                        isInvalidExtendedEscape = true;
                    }
                    if (pos >= len) {
                        error(ts.Diagnostics.Unexpected_end_of_text);
                        isInvalidExtendedEscape = true;
                    }
                    else if (text.charCodeAt(pos) == 125) {
                        pos++;
                    }
                    else {
                        error(ts.Diagnostics.Unterminated_Unicode_escape_sequence);
                        isInvalidExtendedEscape = true;
                    }
                    if (isInvalidExtendedEscape) {
                        return "";
                    }
                    return utf16EncodeAsString(escapedValue);
                }
                function utf16EncodeAsString(codePoint) {
                    ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF);
                    if (codePoint <= 65535) {
                        return String.fromCharCode(codePoint);
                    }
                    var codeUnit1 = Math.floor((codePoint - 65536) / 1024) + 0xD800;
                    var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00;
                    return String.fromCharCode(codeUnit1, codeUnit2);
                }
                function peekUnicodeEscape() {
                    if (pos + 5 < len && text.charCodeAt(pos + 1) === 117) {
                        var start = pos;
                        pos += 2;
                        var value = scanExactNumberOfHexDigits(4);
                        pos = start;
                        return value;
                    }
                    return -1;
                }
                function scanIdentifierParts() {
                    var result = "";
                    var start = pos;
                    while (pos < len) {
                        var ch = text.charCodeAt(pos);
                        if (isIdentifierPart(ch)) {
                            pos++;
                        }
                        else if (ch === 92) {
                            ch = peekUnicodeEscape();
                            if (!(ch >= 0 && isIdentifierPart(ch))) {
                                break;
                            }
                            result += text.substring(start, pos);
                            result += String.fromCharCode(ch);
                            pos += 6;
                            start = pos;
                        }
                        else {
                            break;
                        }
                    }
                    result += text.substring(start, pos);
                    return result;
                }
                function getIdentifierToken() {
                    var len = tokenValue.length;
                    if (len >= 2 && len <= 11) {
                        var ch = tokenValue.charCodeAt(0);
                        if (ch >= 97 && ch <= 122 && hasOwnProperty.call(textToToken, tokenValue)) {
                            return token = textToToken[tokenValue];
                        }
                    }
                    return token = 64;
                }
                function scanBinaryOrOctalDigits(base) {
                    ts.Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8");
                    var value = 0;
                    var numberOfDigits = 0;
                    while (true) {
                        var ch = text.charCodeAt(pos);
                        var valueOfCh = ch - 48;
                        if (!isDigit(ch) || valueOfCh >= base) {
                            break;
                        }
                        value = value * base + valueOfCh;
                        pos++;
                        numberOfDigits++;
                    }
                    if (numberOfDigits === 0) {
                        return -1;
                    }
                    return value;
                }
                function scan() {
                    startPos = pos;
                    hasExtendedUnicodeEscape = false;
                    precedingLineBreak = false;
                    tokenIsUnterminated = false;
                    while (true) {
                        tokenPos = pos;
                        if (pos >= len) {
                            return token = 1;
                        }
                        var ch = text.charCodeAt(pos);
                        switch (ch) {
                            case 10:
                            case 13:
                                precedingLineBreak = true;
                                if (skipTrivia) {
                                    pos++;
                                    continue;
                                }
                                else {
                                    if (ch === 13 && pos + 1 < len && text.charCodeAt(pos + 1) === 10) {
                                        pos += 2;
                                    }
                                    else {
                                        pos++;
                                    }
                                    return token = 4;
                                }
                            case 9:
                            case 11:
                            case 12:
                            case 32:
                                if (skipTrivia) {
                                    pos++;
                                    continue;
                                }
                                else {
                                    while (pos < len && isWhiteSpace(text.charCodeAt(pos))) {
                                        pos++;
                                    }
                                    return token = 5;
                                }
                            case 33:
                                if (text.charCodeAt(pos + 1) === 61) {
                                    if (text.charCodeAt(pos + 2) === 61) {
                                        return pos += 3, token = 31;
                                    }
                                    return pos += 2, token = 29;
                                }
                                return pos++, token = 46;
                            case 34:
                            case 39:
                                tokenValue = scanString();
                                return token = 8;
                            case 96:
                                return token = scanTemplateAndSetTokenValue();
                            case 37:
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 57;
                                }
                                return pos++, token = 37;
                            case 38:
                                if (text.charCodeAt(pos + 1) === 38) {
                                    return pos += 2, token = 48;
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 61;
                                }
                                return pos++, token = 43;
                            case 40:
                                return pos++, token = 16;
                            case 41:
                                return pos++, token = 17;
                            case 42:
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 55;
                                }
                                return pos++, token = 35;
                            case 43:
                                if (text.charCodeAt(pos + 1) === 43) {
                                    return pos += 2, token = 38;
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 53;
                                }
                                return pos++, token = 33;
                            case 44:
                                return pos++, token = 23;
                            case 45:
                                if (text.charCodeAt(pos + 1) === 45) {
                                    return pos += 2, token = 39;
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 54;
                                }
                                return pos++, token = 34;
                            case 46:
                                if (isDigit(text.charCodeAt(pos + 1))) {
                                    tokenValue = "" + scanNumber();
                                    return token = 7;
                                }
                                if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) {
                                    return pos += 3, token = 21;
                                }
                                return pos++, token = 20;
                            case 47:
                                if (text.charCodeAt(pos + 1) === 47) {
                                    pos += 2;
                                    while (pos < len) {
                                        if (isLineBreak(text.charCodeAt(pos))) {
                                            break;
                                        }
                                        pos++;
                                    }
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 2;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 42) {
                                    pos += 2;
                                    var commentClosed = false;
                                    while (pos < len) {
                                        var ch = text.charCodeAt(pos);
                                        if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
                                            pos += 2;
                                            commentClosed = true;
                                            break;
                                        }
                                        if (isLineBreak(ch)) {
                                            precedingLineBreak = true;
                                        }
                                        pos++;
                                    }
                                    if (!commentClosed) {
                                        error(ts.Diagnostics.Asterisk_Slash_expected);
                                    }
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        tokenIsUnterminated = !commentClosed;
                                        return token = 3;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 56;
                                }
                                return pos++, token = 36;
                            case 48:
                                if (pos + 2 < len && (text.charCodeAt(pos + 1) === 88 || text.charCodeAt(pos + 1) === 120)) {
                                    pos += 2;
                                    var value = scanMinimumNumberOfHexDigits(1);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7;
                                }
                                else if (pos + 2 < len && (text.charCodeAt(pos + 1) === 66 || text.charCodeAt(pos + 1) === 98)) {
                                    pos += 2;
                                    var value = scanBinaryOrOctalDigits(2);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Binary_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7;
                                }
                                else if (pos + 2 < len && (text.charCodeAt(pos + 1) === 79 || text.charCodeAt(pos + 1) === 111)) {
                                    pos += 2;
                                    var value = scanBinaryOrOctalDigits(8);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Octal_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7;
                                }
                                if (pos + 1 < len && isOctalDigit(text.charCodeAt(pos + 1))) {
                                    tokenValue = "" + scanOctalDigits();
                                    return token = 7;
                                }
                            case 49:
                            case 50:
                            case 51:
                            case 52:
                            case 53:
                            case 54:
                            case 55:
                            case 56:
                            case 57:
                                tokenValue = "" + scanNumber();
                                return token = 7;
                            case 58:
                                return pos++, token = 51;
                            case 59:
                                return pos++, token = 22;
                            case 60:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 60) {
                                    if (text.charCodeAt(pos + 2) === 61) {
                                        return pos += 3, token = 58;
                                    }
                                    return pos += 2, token = 40;
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 26;
                                }
                                return pos++, token = 24;
                            case 61:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    if (text.charCodeAt(pos + 2) === 61) {
                                        return pos += 3, token = 30;
                                    }
                                    return pos += 2, token = 28;
                                }
                                if (text.charCodeAt(pos + 1) === 62) {
                                    return pos += 2, token = 32;
                                }
                                return pos++, token = 52;
                            case 62:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6;
                                    }
                                }
                                return pos++, token = 25;
                            case 63:
                                return pos++, token = 50;
                            case 91:
                                return pos++, token = 18;
                            case 93:
                                return pos++, token = 19;
                            case 94:
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 63;
                                }
                                return pos++, token = 45;
                            case 123:
                                return pos++, token = 14;
                            case 124:
                                if (text.charCodeAt(pos + 1) === 124) {
                                    return pos += 2, token = 49;
                                }
                                if (text.charCodeAt(pos + 1) === 61) {
                                    return pos += 2, token = 62;
                                }
                                return pos++, token = 44;
                            case 125:
                                return pos++, token = 15;
                            case 126:
                                return pos++, token = 47;
                            case 92:
                                var ch = peekUnicodeEscape();
                                if (ch >= 0 && isIdentifierStart(ch)) {
                                    pos += 6;
                                    tokenValue = String.fromCharCode(ch) + scanIdentifierParts();
                                    return token = getIdentifierToken();
                                }
                                error(ts.Diagnostics.Invalid_character);
                                return pos++, token = 0;
                            default:
                                if (isIdentifierStart(ch)) {
                                    pos++;
                                    while (pos < len && isIdentifierPart(ch = text.charCodeAt(pos)))
                                        pos++;
                                    tokenValue = text.substring(tokenPos, pos);
                                    if (ch === 92) {
                                        tokenValue += scanIdentifierParts();
                                    }
                                    return token = getIdentifierToken();
                                }
                                else if (isWhiteSpace(ch)) {
                                    pos++;
                                    continue;
                                }
                                else if (isLineBreak(ch)) {
                                    precedingLineBreak = true;
                                    pos++;
                                    continue;
                                }
                                error(ts.Diagnostics.Invalid_character);
                                return pos++, token = 0;
                        }
                    }
                }
                function reScanGreaterToken() {
                    if (token === 25) {
                        if (text.charCodeAt(pos) === 62) {
                            if (text.charCodeAt(pos + 1) === 62) {
                                if (text.charCodeAt(pos + 2) === 61) {
                                    return pos += 3, token = 60;
                                }
                                return pos += 2, token = 42;
                            }
                            if (text.charCodeAt(pos + 1) === 61) {
                                return pos += 2, token = 59;
                            }
                            return pos++, token = 41;
                        }
                        if (text.charCodeAt(pos) === 61) {
                            return pos++, token = 27;
                        }
                    }
                    return token;
                }
                function reScanSlashToken() {
                    if (token === 36 || token === 56) {
                        var p = tokenPos + 1;
                        var inEscape = false;
                        var inCharacterClass = false;
                        while (true) {
                            if (p >= len) {
                                tokenIsUnterminated = true;
                                error(ts.Diagnostics.Unterminated_regular_expression_literal);
                                break;
                            }
                            var ch = text.charCodeAt(p);
                            if (isLineBreak(ch)) {
                                tokenIsUnterminated = true;
                                error(ts.Diagnostics.Unterminated_regular_expression_literal);
                                break;
                            }
                            if (inEscape) {
                                inEscape = false;
                            }
                            else if (ch === 47 && !inCharacterClass) {
                                p++;
                                break;
                            }
                            else if (ch === 91) {
                                inCharacterClass = true;
                            }
                            else if (ch === 92) {
                                inEscape = true;
                            }
                            else if (ch === 93) {
                                inCharacterClass = false;
                            }
                            p++;
                        }
                        while (p < len && isIdentifierPart(text.charCodeAt(p))) {
                            p++;
                        }
                        pos = p;
                        tokenValue = text.substring(tokenPos, pos);
                        token = 9;
                    }
                    return token;
                }
                function reScanTemplateToken() {
                    ts.Debug.assert(token === 15, "'reScanTemplateToken' should only be called on a '}'");
                    pos = tokenPos;
                    return token = scanTemplateAndSetTokenValue();
                }
                function speculationHelper(callback, isLookahead) {
                    var savePos = pos;
                    var saveStartPos = startPos;
                    var saveTokenPos = tokenPos;
                    var saveToken = token;
                    var saveTokenValue = tokenValue;
                    var savePrecedingLineBreak = precedingLineBreak;
                    var result = callback();
                    if (!result || isLookahead) {
                        pos = savePos;
                        startPos = saveStartPos;
                        tokenPos = saveTokenPos;
                        token = saveToken;
                        tokenValue = saveTokenValue;
                        precedingLineBreak = savePrecedingLineBreak;
                    }
                    return result;
                }
                function lookAhead(callback) {
                    return speculationHelper(callback, true);
                }
                function tryScan(callback) {
                    return speculationHelper(callback, false);
                }
                function setText(newText) {
                    text = newText || "";
                    len = text.length;
                    setTextPos(0);
                }
                function setTextPos(textPos) {
                    pos = textPos;
                    startPos = textPos;
                    tokenPos = textPos;
                    token = 0;
                    precedingLineBreak = false;
                }
                setText(text);
                return {
                    getStartPos: function () {
                        return startPos;
                    },
                    getTextPos: function () {
                        return pos;
                    },
                    getToken: function () {
                        return token;
                    },
                    getTokenPos: function () {
                        return tokenPos;
                    },
                    getTokenText: function () {
                        return text.substring(tokenPos, pos);
                    },
                    getTokenValue: function () {
                        return tokenValue;
                    },
                    hasExtendedUnicodeEscape: function () {
                        return hasExtendedUnicodeEscape;
                    },
                    hasPrecedingLineBreak: function () {
                        return precedingLineBreak;
                    },
                    isIdentifier: function () {
                        return token === 64 || token > 100;
                    },
                    isReservedWord: function () {
                        return token >= 65 && token <= 100;
                    },
                    isUnterminated: function () {
                        return tokenIsUnterminated;
                    },
                    reScanGreaterToken: reScanGreaterToken,
                    reScanSlashToken: reScanSlashToken,
                    reScanTemplateToken: reScanTemplateToken,
                    scan: scan,
                    setText: setText,
                    setTextPos: setTextPos,
                    tryScan: tryScan,
                    lookAhead: lookAhead
                };
            }
            ts.createScanner = createScanner;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            function getDeclarationOfKind(symbol, kind) {
                var declarations = symbol.declarations;
                for (var i = 0; i < declarations.length; i++) {
                    var declaration = declarations[i];
                    if (declaration.kind === kind) {
                        return declaration;
                    }
                }
                return undefined;
            }
            ts.getDeclarationOfKind = getDeclarationOfKind;
            var stringWriters = [];
            function getSingleLineStringWriter() {
                if (stringWriters.length == 0) {
                    var str = "";
                    var writeText = function (text) {
                        return str += text;
                    };
                    return {
                        string: function () {
                            return str;
                        },
                        writeKeyword: writeText,
                        writeOperator: writeText,
                        writePunctuation: writeText,
                        writeSpace: writeText,
                        writeStringLiteral: writeText,
                        writeParameter: writeText,
                        writeSymbol: writeText,
                        writeLine: function () {
                            return str += " ";
                        },
                        increaseIndent: function () {
                        },
                        decreaseIndent: function () {
                        },
                        clear: function () {
                            return str = "";
                        },
                        trackSymbol: function () {
                        }
                    };
                }
                return stringWriters.pop();
            }
            ts.getSingleLineStringWriter = getSingleLineStringWriter;
            function releaseStringWriter(writer) {
                writer.clear();
                stringWriters.push(writer);
            }
            ts.releaseStringWriter = releaseStringWriter;
            function getFullWidth(node) {
                return node.end - node.pos;
            }
            ts.getFullWidth = getFullWidth;
            function containsParseError(node) {
                aggregateChildData(node);
                return (node.parserContextFlags & 32) !== 0;
            }
            ts.containsParseError = containsParseError;
            function aggregateChildData(node) {
                if (!(node.parserContextFlags & 64)) {
                    var thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & 16) !== 0) || ts.forEachChild(node, containsParseError);
                    if (thisNodeOrAnySubNodesHasError) {
                        node.parserContextFlags |= 32;
                    }
                    node.parserContextFlags |= 64;
                }
            }
            function getSourceFileOfNode(node) {
                while (node && node.kind !== 221) {
                    node = node.parent;
                }
                return node;
            }
            ts.getSourceFileOfNode = getSourceFileOfNode;
            function getStartPositionOfLine(line, sourceFile) {
                ts.Debug.assert(line >= 0);
                return ts.getLineStarts(sourceFile)[line];
            }
            ts.getStartPositionOfLine = getStartPositionOfLine;
            function nodePosToString(node) {
                var file = getSourceFileOfNode(node);
                var loc = ts.getLineAndCharacterOfPosition(file, node.pos);
                return file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + ")";
            }
            ts.nodePosToString = nodePosToString;
            function getStartPosOfNode(node) {
                return node.pos;
            }
            ts.getStartPosOfNode = getStartPosOfNode;
            function nodeIsMissing(node) {
                if (!node) {
                    return true;
                }
                return node.pos === node.end && node.kind !== 1;
            }
            ts.nodeIsMissing = nodeIsMissing;
            function nodeIsPresent(node) {
                return !nodeIsMissing(node);
            }
            ts.nodeIsPresent = nodeIsPresent;
            function getTokenPosOfNode(node, sourceFile) {
                if (nodeIsMissing(node)) {
                    return node.pos;
                }
                return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
            }
            ts.getTokenPosOfNode = getTokenPosOfNode;
            function getSourceTextOfNodeFromSourceFile(sourceFile, node) {
                if (nodeIsMissing(node)) {
                    return "";
                }
                var text = sourceFile.text;
                return text.substring(ts.skipTrivia(text, node.pos), node.end);
            }
            ts.getSourceTextOfNodeFromSourceFile = getSourceTextOfNodeFromSourceFile;
            function getTextOfNodeFromSourceText(sourceText, node) {
                if (nodeIsMissing(node)) {
                    return "";
                }
                return sourceText.substring(ts.skipTrivia(sourceText, node.pos), node.end);
            }
            ts.getTextOfNodeFromSourceText = getTextOfNodeFromSourceText;
            function getTextOfNode(node) {
                return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
            }
            ts.getTextOfNode = getTextOfNode;
            function escapeIdentifier(identifier) {
                return identifier.length >= 2 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 ? "_" + identifier : identifier;
            }
            ts.escapeIdentifier = escapeIdentifier;
            function unescapeIdentifier(identifier) {
                return identifier.length >= 3 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 && identifier.charCodeAt(2) === 95 ? identifier.substr(1) : identifier;
            }
            ts.unescapeIdentifier = unescapeIdentifier;
            function makeIdentifierFromModuleName(moduleName) {
                return ts.getBaseFileName(moduleName).replace(/\W/g, "_");
            }
            ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName;
            function isBlockOrCatchScoped(declaration) {
                return (getCombinedNodeFlags(declaration) & 12288) !== 0 || isCatchClauseVariableDeclaration(declaration);
            }
            ts.isBlockOrCatchScoped = isBlockOrCatchScoped;
            function getEnclosingBlockScopeContainer(node) {
                var current = node;
                while (current) {
                    if (isFunctionLike(current)) {
                        return current;
                    }
                    switch (current.kind) {
                        case 221:
                        case 202:
                        case 217:
                        case 200:
                        case 181:
                        case 182:
                        case 183:
                            return current;
                        case 174:
                            if (!isFunctionLike(current.parent)) {
                                return current;
                            }
                    }
                    current = current.parent;
                }
            }
            ts.getEnclosingBlockScopeContainer = getEnclosingBlockScopeContainer;
            function isCatchClauseVariableDeclaration(declaration) {
                return declaration && declaration.kind === 193 && declaration.parent && declaration.parent.kind === 217;
            }
            ts.isCatchClauseVariableDeclaration = isCatchClauseVariableDeclaration;
            function declarationNameToString(name) {
                return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
            }
            ts.declarationNameToString = declarationNameToString;
            function createDiagnosticForNode(node, message, arg0, arg1, arg2) {
                var sourceFile = getSourceFileOfNode(node);
                var span = getErrorSpanForNode(sourceFile, node);
                return ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
            }
            ts.createDiagnosticForNode = createDiagnosticForNode;
            function createDiagnosticForNodeFromMessageChain(node, messageChain) {
                var sourceFile = getSourceFileOfNode(node);
                var span = getErrorSpanForNode(sourceFile, node);
                return {
                    file: sourceFile,
                    start: span.start,
                    length: span.length,
                    code: messageChain.code,
                    category: messageChain.category,
                    messageText: messageChain.next ? messageChain : messageChain.messageText
                };
            }
            ts.createDiagnosticForNodeFromMessageChain = createDiagnosticForNodeFromMessageChain;
            function getSpanOfTokenAtPosition(sourceFile, pos) {
                var scanner = ts.createScanner(sourceFile.languageVersion, true, sourceFile.text);
                scanner.setTextPos(pos);
                scanner.scan();
                var start = scanner.getTokenPos();
                return createTextSpanFromBounds(start, scanner.getTextPos());
            }
            ts.getSpanOfTokenAtPosition = getSpanOfTokenAtPosition;
            function getErrorSpanForNode(sourceFile, node) {
                var errorNode = node;
                switch (node.kind) {
                    case 193:
                    case 150:
                    case 196:
                    case 197:
                    case 200:
                    case 199:
                    case 220:
                    case 195:
                    case 160:
                        errorNode = node.name;
                        break;
                }
                if (errorNode === undefined) {
                    return getSpanOfTokenAtPosition(sourceFile, node.pos);
                }
                var pos = nodeIsMissing(errorNode) ? errorNode.pos : ts.skipTrivia(sourceFile.text, errorNode.pos);
                return createTextSpanFromBounds(pos, errorNode.end);
            }
            ts.getErrorSpanForNode = getErrorSpanForNode;
            function isExternalModule(file) {
                return file.externalModuleIndicator !== undefined;
            }
            ts.isExternalModule = isExternalModule;
            function isDeclarationFile(file) {
                return (file.flags & 2048) !== 0;
            }
            ts.isDeclarationFile = isDeclarationFile;
            function isConstEnumDeclaration(node) {
                return node.kind === 199 && isConst(node);
            }
            ts.isConstEnumDeclaration = isConstEnumDeclaration;
            function walkUpBindingElementsAndPatterns(node) {
                while (node && (node.kind === 150 || isBindingPattern(node))) {
                    node = node.parent;
                }
                return node;
            }
            function getCombinedNodeFlags(node) {
                node = walkUpBindingElementsAndPatterns(node);
                var flags = node.flags;
                if (node.kind === 193) {
                    node = node.parent;
                }
                if (node && node.kind === 194) {
                    flags |= node.flags;
                    node = node.parent;
                }
                if (node && node.kind === 175) {
                    flags |= node.flags;
                }
                return flags;
            }
            ts.getCombinedNodeFlags = getCombinedNodeFlags;
            function isConst(node) {
                return !!(getCombinedNodeFlags(node) & 8192);
            }
            ts.isConst = isConst;
            function isLet(node) {
                return !!(getCombinedNodeFlags(node) & 4096);
            }
            ts.isLet = isLet;
            function isPrologueDirective(node) {
                return node.kind === 177 && node.expression.kind === 8;
            }
            ts.isPrologueDirective = isPrologueDirective;
            function getLeadingCommentRangesOfNode(node, sourceFileOfNode) {
                sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node);
                if (node.kind === 128 || node.kind === 127) {
                    return ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
                }
                else {
                    return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
                }
            }
            ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode;
            function getJsDocComments(node, sourceFileOfNode) {
                return ts.filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
                function isJsDocComment(comment) {
                    return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 && sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 && sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47;
                }
            }
            ts.getJsDocComments = getJsDocComments;
            ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
            function forEachReturnStatement(body, visitor) {
                return traverse(body);
                function traverse(node) {
                    switch (node.kind) {
                        case 186:
                            return visitor(node);
                        case 202:
                        case 174:
                        case 178:
                        case 179:
                        case 180:
                        case 181:
                        case 182:
                        case 183:
                        case 187:
                        case 188:
                        case 214:
                        case 215:
                        case 189:
                        case 191:
                        case 217:
                            return ts.forEachChild(node, traverse);
                    }
                }
            }
            ts.forEachReturnStatement = forEachReturnStatement;
            function isVariableLike(node) {
                if (node) {
                    switch (node.kind) {
                        case 150:
                        case 220:
                        case 128:
                        case 218:
                        case 130:
                        case 129:
                        case 219:
                        case 193:
                            return true;
                    }
                }
                return false;
            }
            ts.isVariableLike = isVariableLike;
            function isFunctionLike(node) {
                if (node) {
                    switch (node.kind) {
                        case 133:
                        case 160:
                        case 195:
                        case 161:
                        case 132:
                        case 131:
                        case 134:
                        case 135:
                        case 136:
                        case 137:
                        case 138:
                        case 140:
                        case 141:
                        case 160:
                        case 161:
                        case 195:
                            return true;
                    }
                }
                return false;
            }
            ts.isFunctionLike = isFunctionLike;
            function isFunctionBlock(node) {
                return node && node.kind === 174 && isFunctionLike(node.parent);
            }
            ts.isFunctionBlock = isFunctionBlock;
            function isObjectLiteralMethod(node) {
                return node && node.kind === 132 && node.parent.kind === 152;
            }
            ts.isObjectLiteralMethod = isObjectLiteralMethod;
            function getContainingFunction(node) {
                while (true) {
                    node = node.parent;
                    if (!node || isFunctionLike(node)) {
                        return node;
                    }
                }
            }
            ts.getContainingFunction = getContainingFunction;
            function getThisContainer(node, includeArrowFunctions) {
                while (true) {
                    node = node.parent;
                    if (!node) {
                        return undefined;
                    }
                    switch (node.kind) {
                        case 126:
                            if (node.parent.parent.kind === 196) {
                                return node;
                            }
                            node = node.parent;
                            break;
                        case 161:
                            if (!includeArrowFunctions) {
                                continue;
                            }
                        case 195:
                        case 160:
                        case 200:
                        case 130:
                        case 129:
                        case 132:
                        case 131:
                        case 133:
                        case 134:
                        case 135:
                        case 199:
                        case 221:
                            return node;
                    }
                }
            }
            ts.getThisContainer = getThisContainer;
            function getSuperContainer(node, includeFunctions) {
                while (true) {
                    node = node.parent;
                    if (!node)
                        return node;
                    switch (node.kind) {
                        case 126:
                            if (node.parent.parent.kind === 196) {
                                return node;
                            }
                            node = node.parent;
                            break;
                        case 195:
                        case 160:
                        case 161:
                            if (!includeFunctions) {
                                continue;
                            }
                        case 130:
                        case 129:
                        case 132:
                        case 131:
                        case 133:
                        case 134:
                        case 135:
                            return node;
                    }
                }
            }
            ts.getSuperContainer = getSuperContainer;
            function getInvokedExpression(node) {
                if (node.kind === 157) {
                    return node.tag;
                }
                return node.expression;
            }
            ts.getInvokedExpression = getInvokedExpression;
            function isExpression(node) {
                switch (node.kind) {
                    case 92:
                    case 90:
                    case 88:
                    case 94:
                    case 79:
                    case 9:
                    case 151:
                    case 152:
                    case 153:
                    case 154:
                    case 155:
                    case 156:
                    case 157:
                    case 158:
                    case 159:
                    case 160:
                    case 161:
                    case 164:
                    case 162:
                    case 163:
                    case 165:
                    case 166:
                    case 167:
                    case 168:
                    case 171:
                    case 169:
                    case 10:
                    case 172:
                        return true;
                    case 125:
                        while (node.parent.kind === 125) {
                            node = node.parent;
                        }
                        return node.parent.kind === 142;
                    case 64:
                        if (node.parent.kind === 142) {
                            return true;
                        }
                    case 7:
                    case 8:
                        var parent = node.parent;
                        switch (parent.kind) {
                            case 193:
                            case 128:
                            case 130:
                            case 129:
                            case 220:
                            case 218:
                            case 150:
                                return parent.initializer === node;
                            case 177:
                            case 178:
                            case 179:
                            case 180:
                            case 186:
                            case 187:
                            case 188:
                            case 214:
                            case 190:
                            case 188:
                                return parent.expression === node;
                            case 181:
                                var forStatement = parent;
                                return (forStatement.initializer === node && forStatement.initializer.kind !== 194) || forStatement.condition === node || forStatement.iterator === node;
                            case 182:
                            case 183:
                                var forInStatement = parent;
                                return (forInStatement.initializer === node && forInStatement.initializer.kind !== 194) || forInStatement.expression === node;
                            case 158:
                                return node === parent.expression;
                            case 173:
                                return node === parent.expression;
                            case 126:
                                return node === parent.expression;
                            default:
                                if (isExpression(parent)) {
                                    return true;
                                }
                        }
                }
                return false;
            }
            ts.isExpression = isExpression;
            function isInstantiatedModule(node, preserveConstEnums) {
                var moduleState = ts.getModuleInstanceState(node);
                return moduleState === 1 || (preserveConstEnums && moduleState === 2);
            }
            ts.isInstantiatedModule = isInstantiatedModule;
            function isExternalModuleImportEqualsDeclaration(node) {
                return node.kind === 203 && node.moduleReference.kind === 213;
            }
            ts.isExternalModuleImportEqualsDeclaration = isExternalModuleImportEqualsDeclaration;
            function getExternalModuleImportEqualsDeclarationExpression(node) {
                ts.Debug.assert(isExternalModuleImportEqualsDeclaration(node));
                return node.moduleReference.expression;
            }
            ts.getExternalModuleImportEqualsDeclarationExpression = getExternalModuleImportEqualsDeclarationExpression;
            function isInternalModuleImportEqualsDeclaration(node) {
                return node.kind === 203 && node.moduleReference.kind !== 213;
            }
            ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration;
            function getExternalModuleName(node) {
                if (node.kind === 204) {
                    return node.moduleSpecifier;
                }
                if (node.kind === 203) {
                    var reference = node.moduleReference;
                    if (reference.kind === 213) {
                        return reference.expression;
                    }
                }
                if (node.kind === 210) {
                    return node.moduleSpecifier;
                }
            }
            ts.getExternalModuleName = getExternalModuleName;
            function hasDotDotDotToken(node) {
                return node && node.kind === 128 && node.dotDotDotToken !== undefined;
            }
            ts.hasDotDotDotToken = hasDotDotDotToken;
            function hasQuestionToken(node) {
                if (node) {
                    switch (node.kind) {
                        case 128:
                            return node.questionToken !== undefined;
                        case 132:
                        case 131:
                            return node.questionToken !== undefined;
                        case 219:
                        case 218:
                        case 130:
                        case 129:
                            return node.questionToken !== undefined;
                    }
                }
                return false;
            }
            ts.hasQuestionToken = hasQuestionToken;
            function hasRestParameters(s) {
                return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
            }
            ts.hasRestParameters = hasRestParameters;
            function isLiteralKind(kind) {
                return 7 <= kind && kind <= 10;
            }
            ts.isLiteralKind = isLiteralKind;
            function isTextualLiteralKind(kind) {
                return kind === 8 || kind === 10;
            }
            ts.isTextualLiteralKind = isTextualLiteralKind;
            function isTemplateLiteralKind(kind) {
                return 10 <= kind && kind <= 13;
            }
            ts.isTemplateLiteralKind = isTemplateLiteralKind;
            function isBindingPattern(node) {
                return !!node && (node.kind === 149 || node.kind === 148);
            }
            ts.isBindingPattern = isBindingPattern;
            function isInAmbientContext(node) {
                while (node) {
                    if (node.flags & (2 | 2048)) {
                        return true;
                    }
                    node = node.parent;
                }
                return false;
            }
            ts.isInAmbientContext = isInAmbientContext;
            function isDeclaration(node) {
                switch (node.kind) {
                    case 161:
                    case 150:
                    case 196:
                    case 133:
                    case 199:
                    case 220:
                    case 212:
                    case 195:
                    case 160:
                    case 134:
                    case 205:
                    case 203:
                    case 208:
                    case 197:
                    case 132:
                    case 131:
                    case 200:
                    case 206:
                    case 128:
                    case 218:
                    case 130:
                    case 129:
                    case 135:
                    case 219:
                    case 198:
                    case 127:
                    case 193:
                        return true;
                }
                return false;
            }
            ts.isDeclaration = isDeclaration;
            function isStatement(n) {
                switch (n.kind) {
                    case 185:
                    case 184:
                    case 192:
                    case 179:
                    case 177:
                    case 176:
                    case 182:
                    case 183:
                    case 181:
                    case 178:
                    case 189:
                    case 186:
                    case 188:
                    case 93:
                    case 191:
                    case 175:
                    case 180:
                    case 187:
                    case 209:
                        return true;
                    default:
                        return false;
                }
            }
            ts.isStatement = isStatement;
            function isDeclarationName(name) {
                if (name.kind !== 64 && name.kind !== 8 && name.kind !== 7) {
                    return false;
                }
                var parent = name.parent;
                if (parent.kind === 208 || parent.kind === 212) {
                    if (parent.propertyName) {
                        return true;
                    }
                }
                if (isDeclaration(parent)) {
                    return parent.name === name;
                }
                return false;
            }
            ts.isDeclarationName = isDeclarationName;
            function getClassBaseTypeNode(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 78);
                return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
            }
            ts.getClassBaseTypeNode = getClassBaseTypeNode;
            function getClassImplementedTypeNodes(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 102);
                return heritageClause ? heritageClause.types : undefined;
            }
            ts.getClassImplementedTypeNodes = getClassImplementedTypeNodes;
            function getInterfaceBaseTypeNodes(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 78);
                return heritageClause ? heritageClause.types : undefined;
            }
            ts.getInterfaceBaseTypeNodes = getInterfaceBaseTypeNodes;
            function getHeritageClause(clauses, kind) {
                if (clauses) {
                    for (var i = 0, n = clauses.length; i < n; i++) {
                        if (clauses[i].token === kind) {
                            return clauses[i];
                        }
                    }
                }
                return undefined;
            }
            ts.getHeritageClause = getHeritageClause;
            function tryResolveScriptReference(host, sourceFile, reference) {
                if (!host.getCompilerOptions().noResolve) {
                    var referenceFileName = ts.isRootedDiskPath(reference.fileName) ? reference.fileName : ts.combinePaths(ts.getDirectoryPath(sourceFile.fileName), reference.fileName);
                    referenceFileName = ts.getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
                    return host.getSourceFile(referenceFileName);
                }
            }
            ts.tryResolveScriptReference = tryResolveScriptReference;
            function getAncestor(node, kind) {
                while (node) {
                    if (node.kind === kind) {
                        return node;
                    }
                    node = node.parent;
                }
                return undefined;
            }
            ts.getAncestor = getAncestor;
            function getFileReferenceFromReferencePath(comment, commentRange) {
                var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
                var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
                if (simpleReferenceRegEx.exec(comment)) {
                    if (isNoDefaultLibRegEx.exec(comment)) {
                        return {
                            isNoDefaultLib: true
                        };
                    }
                    else {
                        var matchResult = ts.fullTripleSlashReferencePathRegEx.exec(comment);
                        if (matchResult) {
                            var start = commentRange.pos;
                            var end = commentRange.end;
                            return {
                                fileReference: {
                                    pos: start,
                                    end: end,
                                    fileName: matchResult[3]
                                },
                                isNoDefaultLib: false
                            };
                        }
                        else {
                            return {
                                diagnosticMessage: ts.Diagnostics.Invalid_reference_directive_syntax,
                                isNoDefaultLib: false
                            };
                        }
                    }
                }
                return undefined;
            }
            ts.getFileReferenceFromReferencePath = getFileReferenceFromReferencePath;
            function isKeyword(token) {
                return 65 <= token && token <= 124;
            }
            ts.isKeyword = isKeyword;
            function isTrivia(token) {
                return 2 <= token && token <= 6;
            }
            ts.isTrivia = isTrivia;
            function hasDynamicName(declaration) {
                return declaration.name && declaration.name.kind === 126 && !isWellKnownSymbolSyntactically(declaration.name.expression);
            }
            ts.hasDynamicName = hasDynamicName;
            function isWellKnownSymbolSyntactically(node) {
                return node.kind === 153 && isESSymbolIdentifier(node.expression);
            }
            ts.isWellKnownSymbolSyntactically = isWellKnownSymbolSyntactically;
            function getPropertyNameForPropertyNameNode(name) {
                if (name.kind === 64 || name.kind === 8 || name.kind === 7) {
                    return name.text;
                }
                if (name.kind === 126) {
                    var nameExpression = name.expression;
                    if (isWellKnownSymbolSyntactically(nameExpression)) {
                        var rightHandSideName = nameExpression.name.text;
                        return getPropertyNameForKnownSymbolName(rightHandSideName);
                    }
                }
                return undefined;
            }
            ts.getPropertyNameForPropertyNameNode = getPropertyNameForPropertyNameNode;
            function getPropertyNameForKnownSymbolName(symbolName) {
                return "__@" + symbolName;
            }
            ts.getPropertyNameForKnownSymbolName = getPropertyNameForKnownSymbolName;
            function isESSymbolIdentifier(node) {
                return node.kind === 64 && node.text === "Symbol";
            }
            ts.isESSymbolIdentifier = isESSymbolIdentifier;
            function isModifier(token) {
                switch (token) {
                    case 108:
                    case 106:
                    case 107:
                    case 109:
                    case 77:
                    case 114:
                    case 69:
                    case 72:
                        return true;
                }
                return false;
            }
            ts.isModifier = isModifier;
            function textSpanEnd(span) {
                return span.start + span.length;
            }
            ts.textSpanEnd = textSpanEnd;
            function textSpanIsEmpty(span) {
                return span.length === 0;
            }
            ts.textSpanIsEmpty = textSpanIsEmpty;
            function textSpanContainsPosition(span, position) {
                return position >= span.start && position < textSpanEnd(span);
            }
            ts.textSpanContainsPosition = textSpanContainsPosition;
            function textSpanContainsTextSpan(span, other) {
                return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span);
            }
            ts.textSpanContainsTextSpan = textSpanContainsTextSpan;
            function textSpanOverlapsWith(span, other) {
                var overlapStart = Math.max(span.start, other.start);
                var overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
                return overlapStart < overlapEnd;
            }
            ts.textSpanOverlapsWith = textSpanOverlapsWith;
            function textSpanOverlap(span1, span2) {
                var overlapStart = Math.max(span1.start, span2.start);
                var overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
                if (overlapStart < overlapEnd) {
                    return createTextSpanFromBounds(overlapStart, overlapEnd);
                }
                return undefined;
            }
            ts.textSpanOverlap = textSpanOverlap;
            function textSpanIntersectsWithTextSpan(span, other) {
                return other.start <= textSpanEnd(span) && textSpanEnd(other) >= span.start;
            }
            ts.textSpanIntersectsWithTextSpan = textSpanIntersectsWithTextSpan;
            function textSpanIntersectsWith(span, start, length) {
                var end = start + length;
                return start <= textSpanEnd(span) && end >= span.start;
            }
            ts.textSpanIntersectsWith = textSpanIntersectsWith;
            function textSpanIntersectsWithPosition(span, position) {
                return position <= textSpanEnd(span) && position >= span.start;
            }
            ts.textSpanIntersectsWithPosition = textSpanIntersectsWithPosition;
            function textSpanIntersection(span1, span2) {
                var intersectStart = Math.max(span1.start, span2.start);
                var intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
                if (intersectStart <= intersectEnd) {
                    return createTextSpanFromBounds(intersectStart, intersectEnd);
                }
                return undefined;
            }
            ts.textSpanIntersection = textSpanIntersection;
            function createTextSpan(start, length) {
                if (start < 0) {
                    throw new Error("start < 0");
                }
                if (length < 0) {
                    throw new Error("length < 0");
                }
                return {
                    start: start,
                    length: length
                };
            }
            ts.createTextSpan = createTextSpan;
            function createTextSpanFromBounds(start, end) {
                return createTextSpan(start, end - start);
            }
            ts.createTextSpanFromBounds = createTextSpanFromBounds;
            function textChangeRangeNewSpan(range) {
                return createTextSpan(range.span.start, range.newLength);
            }
            ts.textChangeRangeNewSpan = textChangeRangeNewSpan;
            function textChangeRangeIsUnchanged(range) {
                return textSpanIsEmpty(range.span) && range.newLength === 0;
            }
            ts.textChangeRangeIsUnchanged = textChangeRangeIsUnchanged;
            function createTextChangeRange(span, newLength) {
                if (newLength < 0) {
                    throw new Error("newLength < 0");
                }
                return {
                    span: span,
                    newLength: newLength
                };
            }
            ts.createTextChangeRange = createTextChangeRange;
            ts.unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
            function collapseTextChangeRangesAcrossMultipleVersions(changes) {
                if (changes.length === 0) {
                    return ts.unchangedTextChangeRange;
                }
                if (changes.length === 1) {
                    return changes[0];
                }
                var change0 = changes[0];
                var oldStartN = change0.span.start;
                var oldEndN = textSpanEnd(change0.span);
                var newEndN = oldStartN + change0.newLength;
                for (var i = 1; i < changes.length; i++) {
                    var nextChange = changes[i];
                    var oldStart1 = oldStartN;
                    var oldEnd1 = oldEndN;
                    var newEnd1 = newEndN;
                    var oldStart2 = nextChange.span.start;
                    var oldEnd2 = textSpanEnd(nextChange.span);
                    var newEnd2 = oldStart2 + nextChange.newLength;
                    oldStartN = Math.min(oldStart1, oldStart2);
                    oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
                    newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
                }
                return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), newEndN - oldStartN);
            }
            ts.collapseTextChangeRangesAcrossMultipleVersions = collapseTextChangeRangesAcrossMultipleVersions;
            function nodeStartsNewLexicalEnvironment(n) {
                return isFunctionLike(n) || n.kind === 200 || n.kind === 221;
            }
            ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment;
            function nodeIsSynthesized(node) {
                return node.pos === -1;
            }
            ts.nodeIsSynthesized = nodeIsSynthesized;
            function createSynthesizedNode(kind, startsOnNewLine) {
                var node = ts.createNode(kind);
                node.pos = -1;
                node.end = -1;
                node.startsOnNewLine = startsOnNewLine;
                return node;
            }
            ts.createSynthesizedNode = createSynthesizedNode;
            function generateUniqueName(baseName, isExistingName) {
                if (baseName.charCodeAt(0) !== 95) {
                    var baseName = "_" + baseName;
                    if (!isExistingName(baseName)) {
                        return baseName;
                    }
                }
                if (baseName.charCodeAt(baseName.length - 1) !== 95) {
                    baseName += "_";
                }
                var i = 1;
                while (true) {
                    var name = baseName + i;
                    if (!isExistingName(name)) {
                        return name;
                    }
                    i++;
                }
            }
            ts.generateUniqueName = generateUniqueName;
            function createDiagnosticCollection() {
                var nonFileDiagnostics = [];
                var fileDiagnostics = {};
                var diagnosticsModified = false;
                var modificationCount = 0;
                return {
                    add: add,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getDiagnostics: getDiagnostics,
                    getModificationCount: getModificationCount
                };
                function getModificationCount() {
                    return modificationCount;
                }
                function add(diagnostic) {
                    var diagnostics;
                    if (diagnostic.file) {
                        diagnostics = fileDiagnostics[diagnostic.file.fileName];
                        if (!diagnostics) {
                            diagnostics = [];
                            fileDiagnostics[diagnostic.file.fileName] = diagnostics;
                        }
                    }
                    else {
                        diagnostics = nonFileDiagnostics;
                    }
                    diagnostics.push(diagnostic);
                    diagnosticsModified = true;
                    modificationCount++;
                }
                function getGlobalDiagnostics() {
                    sortAndDeduplicate();
                    return nonFileDiagnostics;
                }
                function getDiagnostics(fileName) {
                    sortAndDeduplicate();
                    if (fileName) {
                        return fileDiagnostics[fileName] || [];
                    }
                    var allDiagnostics = [];
                    function pushDiagnostic(d) {
                        allDiagnostics.push(d);
                    }
                    ts.forEach(nonFileDiagnostics, pushDiagnostic);
                    for (var key in fileDiagnostics) {
                        if (ts.hasProperty(fileDiagnostics, key)) {
                            ts.forEach(fileDiagnostics[key], pushDiagnostic);
                        }
                    }
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function sortAndDeduplicate() {
                    if (!diagnosticsModified) {
                        return;
                    }
                    diagnosticsModified = false;
                    nonFileDiagnostics = ts.sortAndDeduplicateDiagnostics(nonFileDiagnostics);
                    for (var key in fileDiagnostics) {
                        if (ts.hasProperty(fileDiagnostics, key)) {
                            fileDiagnostics[key] = ts.sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
                        }
                    }
                }
            }
            ts.createDiagnosticCollection = createDiagnosticCollection;
            var escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
            var escapedCharsMap = {
                "\0": "\\0",
                "\t": "\\t",
                "\v": "\\v",
                "\f": "\\f",
                "\b": "\\b",
                "\r": "\\r",
                "\n": "\\n",
                "\\": "\\\\",
                "\"": "\\\"",
                "\u2028": "\\u2028",
                "\u2029": "\\u2029",
                "\u0085": "\\u0085"
            };
            function escapeString(s) {
                s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
                return s;
                function getReplacement(c) {
                    return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
                }
            }
            ts.escapeString = escapeString;
            function get16BitUnicodeEscapeSequence(charCode) {
                var hexCharCode = charCode.toString(16).toUpperCase();
                var paddedHexCode = ("0000" + hexCharCode).slice(-4);
                return "\\u" + paddedHexCode;
            }
            var nonAsciiCharacters = /[^\u0000-\u007F]/g;
            function escapeNonAsciiCharacters(s) {
                return nonAsciiCharacters.test(s) ? s.replace(nonAsciiCharacters, function (c) {
                    return get16BitUnicodeEscapeSequence(c.charCodeAt(0));
                }) : s;
            }
            ts.escapeNonAsciiCharacters = escapeNonAsciiCharacters;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var nodeConstructors = new Array(223);
            ts.parseTime = 0;
            function getNodeConstructor(kind) {
                return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind));
            }
            ts.getNodeConstructor = getNodeConstructor;
            function createNode(kind) {
                return new (getNodeConstructor(kind))();
            }
            ts.createNode = createNode;
            function visitNode(cbNode, node) {
                if (node) {
                    return cbNode(node);
                }
            }
            function visitNodeArray(cbNodes, nodes) {
                if (nodes) {
                    return cbNodes(nodes);
                }
            }
            function visitEachNode(cbNode, nodes) {
                if (nodes) {
                    for (var i = 0, len = nodes.length; i < len; i++) {
                        var result = cbNode(nodes[i]);
                        if (result) {
                            return result;
                        }
                    }
                }
            }
            function forEachChild(node, cbNode, cbNodeArray) {
                if (!node) {
                    return;
                }
                var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode;
                var cbNodes = cbNodeArray || cbNode;
                switch (node.kind) {
                    case 125:
                        return visitNode(cbNode, node.left) || visitNode(cbNode, node.right);
                    case 127:
                        return visitNode(cbNode, node.name) || visitNode(cbNode, node.constraint) || visitNode(cbNode, node.expression);
                    case 128:
                    case 130:
                    case 129:
                    case 218:
                    case 219:
                    case 193:
                    case 150:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer);
                    case 140:
                    case 141:
                    case 136:
                    case 137:
                    case 138:
                        return visitNodes(cbNodes, node.modifiers) || visitNodes(cbNodes, node.typeParameters) || visitNodes(cbNodes, node.parameters) || visitNode(cbNode, node.type);
                    case 132:
                    case 131:
                    case 133:
                    case 134:
                    case 135:
                    case 160:
                    case 195:
                    case 161:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNodes(cbNodes, node.typeParameters) || visitNodes(cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
                    case 139:
                        return visitNode(cbNode, node.typeName) || visitNodes(cbNodes, node.typeArguments);
                    case 142:
                        return visitNode(cbNode, node.exprName);
                    case 143:
                        return visitNodes(cbNodes, node.members);
                    case 144:
                        return visitNode(cbNode, node.elementType);
                    case 145:
                        return visitNodes(cbNodes, node.elementTypes);
                    case 146:
                        return visitNodes(cbNodes, node.types);
                    case 147:
                        return visitNode(cbNode, node.type);
                    case 148:
                    case 149:
                        return visitNodes(cbNodes, node.elements);
                    case 151:
                        return visitNodes(cbNodes, node.elements);
                    case 152:
                        return visitNodes(cbNodes, node.properties);
                    case 153:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.dotToken) || visitNode(cbNode, node.name);
                    case 154:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.argumentExpression);
                    case 155:
                    case 156:
                        return visitNode(cbNode, node.expression) || visitNodes(cbNodes, node.typeArguments) || visitNodes(cbNodes, node.arguments);
                    case 157:
                        return visitNode(cbNode, node.tag) || visitNode(cbNode, node.template);
                    case 158:
                        return visitNode(cbNode, node.type) || visitNode(cbNode, node.expression);
                    case 159:
                        return visitNode(cbNode, node.expression);
                    case 162:
                        return visitNode(cbNode, node.expression);
                    case 163:
                        return visitNode(cbNode, node.expression);
                    case 164:
                        return visitNode(cbNode, node.expression);
                    case 165:
                        return visitNode(cbNode, node.operand);
                    case 170:
                        return visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.expression);
                    case 166:
                        return visitNode(cbNode, node.operand);
                    case 167:
                        return visitNode(cbNode, node.left) || visitNode(cbNode, node.operatorToken) || visitNode(cbNode, node.right);
                    case 168:
                        return visitNode(cbNode, node.condition) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.whenTrue) || visitNode(cbNode, node.colonToken) || visitNode(cbNode, node.whenFalse);
                    case 171:
                        return visitNode(cbNode, node.expression);
                    case 174:
                    case 201:
                        return visitNodes(cbNodes, node.statements);
                    case 221:
                        return visitNodes(cbNodes, node.statements) || visitNode(cbNode, node.endOfFileToken);
                    case 175:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.declarationList);
                    case 194:
                        return visitNodes(cbNodes, node.declarations);
                    case 177:
                        return visitNode(cbNode, node.expression);
                    case 178:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.thenStatement) || visitNode(cbNode, node.elseStatement);
                    case 179:
                        return visitNode(cbNode, node.statement) || visitNode(cbNode, node.expression);
                    case 180:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
                    case 181:
                        return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.condition) || visitNode(cbNode, node.iterator) || visitNode(cbNode, node.statement);
                    case 182:
                        return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
                    case 183:
                        return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
                    case 184:
                    case 185:
                        return visitNode(cbNode, node.label);
                    case 186:
                        return visitNode(cbNode, node.expression);
                    case 187:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
                    case 188:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.caseBlock);
                    case 202:
                        return visitNodes(cbNodes, node.clauses);
                    case 214:
                        return visitNode(cbNode, node.expression) || visitNodes(cbNodes, node.statements);
                    case 215:
                        return visitNodes(cbNodes, node.statements);
                    case 189:
                        return visitNode(cbNode, node.label) || visitNode(cbNode, node.statement);
                    case 190:
                        return visitNode(cbNode, node.expression);
                    case 191:
                        return visitNode(cbNode, node.tryBlock) || visitNode(cbNode, node.catchClause) || visitNode(cbNode, node.finallyBlock);
                    case 217:
                        return visitNode(cbNode, node.variableDeclaration) || visitNode(cbNode, node.block);
                    case 196:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNodes, node.typeParameters) || visitNodes(cbNodes, node.heritageClauses) || visitNodes(cbNodes, node.members);
                    case 197:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNodes, node.typeParameters) || visitNodes(cbNodes, node.heritageClauses) || visitNodes(cbNodes, node.members);
                    case 198:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.type);
                    case 199:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNodes, node.members);
                    case 220:
                        return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer);
                    case 200:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.body);
                    case 203:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.moduleReference);
                    case 204:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.importClause) || visitNode(cbNode, node.moduleSpecifier);
                    case 205:
                        return visitNode(cbNode, node.name) || visitNode(cbNode, node.namedBindings);
                    case 206:
                        return visitNode(cbNode, node.name);
                    case 207:
                    case 211:
                        return visitNodes(cbNodes, node.elements);
                    case 210:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.exportClause) || visitNode(cbNode, node.moduleSpecifier);
                    case 208:
                    case 212:
                        return visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name);
                    case 209:
                        return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, node.expression);
                    case 169:
                        return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans);
                    case 173:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal);
                    case 126:
                        return visitNode(cbNode, node.expression);
                    case 216:
                        return visitNodes(cbNodes, node.types);
                    case 213:
                        return visitNode(cbNode, node.expression);
                }
            }
            ts.forEachChild = forEachChild;
            var ParsingContext;
            (function (ParsingContext) {
                ParsingContext[ParsingContext["SourceElements"] = 0] = "SourceElements";
                ParsingContext[ParsingContext["ModuleElements"] = 1] = "ModuleElements";
                ParsingContext[ParsingContext["BlockStatements"] = 2] = "BlockStatements";
                ParsingContext[ParsingContext["SwitchClauses"] = 3] = "SwitchClauses";
                ParsingContext[ParsingContext["SwitchClauseStatements"] = 4] = "SwitchClauseStatements";
                ParsingContext[ParsingContext["TypeMembers"] = 5] = "TypeMembers";
                ParsingContext[ParsingContext["ClassMembers"] = 6] = "ClassMembers";
                ParsingContext[ParsingContext["EnumMembers"] = 7] = "EnumMembers";
                ParsingContext[ParsingContext["TypeReferences"] = 8] = "TypeReferences";
                ParsingContext[ParsingContext["VariableDeclarations"] = 9] = "VariableDeclarations";
                ParsingContext[ParsingContext["ObjectBindingElements"] = 10] = "ObjectBindingElements";
                ParsingContext[ParsingContext["ArrayBindingElements"] = 11] = "ArrayBindingElements";
                ParsingContext[ParsingContext["ArgumentExpressions"] = 12] = "ArgumentExpressions";
                ParsingContext[ParsingContext["ObjectLiteralMembers"] = 13] = "ObjectLiteralMembers";
                ParsingContext[ParsingContext["ArrayLiteralMembers"] = 14] = "ArrayLiteralMembers";
                ParsingContext[ParsingContext["Parameters"] = 15] = "Parameters";
                ParsingContext[ParsingContext["TypeParameters"] = 16] = "TypeParameters";
                ParsingContext[ParsingContext["TypeArguments"] = 17] = "TypeArguments";
                ParsingContext[ParsingContext["TupleElementTypes"] = 18] = "TupleElementTypes";
                ParsingContext[ParsingContext["HeritageClauses"] = 19] = "HeritageClauses";
                ParsingContext[ParsingContext["ImportOrExportSpecifiers"] = 20] = "ImportOrExportSpecifiers";
                ParsingContext[ParsingContext["Count"] = 21] = "Count";
            })(ParsingContext || (ParsingContext = {}));
            var Tristate;
            (function (Tristate) {
                Tristate[Tristate["False"] = 0] = "False";
                Tristate[Tristate["True"] = 1] = "True";
                Tristate[Tristate["Unknown"] = 2] = "Unknown";
            })(Tristate || (Tristate = {}));
            function parsingContextErrors(context) {
                switch (context) {
                    case 0:
                        return ts.Diagnostics.Declaration_or_statement_expected;
                    case 1:
                        return ts.Diagnostics.Declaration_or_statement_expected;
                    case 2:
                        return ts.Diagnostics.Statement_expected;
                    case 3:
                        return ts.Diagnostics.case_or_default_expected;
                    case 4:
                        return ts.Diagnostics.Statement_expected;
                    case 5:
                        return ts.Diagnostics.Property_or_signature_expected;
                    case 6:
                        return ts.Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
                    case 7:
                        return ts.Diagnostics.Enum_member_expected;
                    case 8:
                        return ts.Diagnostics.Type_reference_expected;
                    case 9:
                        return ts.Diagnostics.Variable_declaration_expected;
                    case 10:
                        return ts.Diagnostics.Property_destructuring_pattern_expected;
                    case 11:
                        return ts.Diagnostics.Array_element_destructuring_pattern_expected;
                    case 12:
                        return ts.Diagnostics.Argument_expression_expected;
                    case 13:
                        return ts.Diagnostics.Property_assignment_expected;
                    case 14:
                        return ts.Diagnostics.Expression_or_comma_expected;
                    case 15:
                        return ts.Diagnostics.Parameter_declaration_expected;
                    case 16:
                        return ts.Diagnostics.Type_parameter_declaration_expected;
                    case 17:
                        return ts.Diagnostics.Type_argument_expected;
                    case 18:
                        return ts.Diagnostics.Type_expected;
                    case 19:
                        return ts.Diagnostics.Unexpected_token_expected;
                    case 20:
                        return ts.Diagnostics.Identifier_expected;
                }
            }
            ;
            function modifierToFlag(token) {
                switch (token) {
                    case 109:
                        return 128;
                    case 108:
                        return 16;
                    case 107:
                        return 64;
                    case 106:
                        return 32;
                    case 77:
                        return 1;
                    case 114:
                        return 2;
                    case 69:
                        return 8192;
                    case 72:
                        return 256;
                }
                return 0;
            }
            ts.modifierToFlag = modifierToFlag;
            function fixupParentReferences(sourceFile) {
                var parent = sourceFile;
                forEachChild(sourceFile, visitNode);
                return;
                function visitNode(n) {
                    if (n.parent !== parent) {
                        n.parent = parent;
                        var saveParent = parent;
                        parent = n;
                        forEachChild(n, visitNode);
                        parent = saveParent;
                    }
                }
            }
            function shouldCheckNode(node) {
                switch (node.kind) {
                    case 8:
                    case 7:
                    case 64:
                        return true;
                }
                return false;
            }
            function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) {
                if (isArray) {
                    visitArray(element);
                }
                else {
                    visitNode(element);
                }
                return;
                function visitNode(node) {
                    if (aggressiveChecks && shouldCheckNode(node)) {
                        var text = oldText.substring(node.pos, node.end);
                    }
                    node._children = undefined;
                    node.pos += delta;
                    node.end += delta;
                    if (aggressiveChecks && shouldCheckNode(node)) {
                        ts.Debug.assert(text === newText.substring(node.pos, node.end));
                    }
                    forEachChild(node, visitNode, visitArray);
                    checkNodePositions(node, aggressiveChecks);
                }
                function visitArray(array) {
                    array._children = undefined;
                    array.pos += delta;
                    array.end += delta;
                    for (var i = 0, n = array.length; i < n; i++) {
                        visitNode(array[i]);
                    }
                }
            }
            function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) {
                ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
                ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
                ts.Debug.assert(element.pos <= element.end);
                element.pos = Math.min(element.pos, changeRangeNewEnd);
                if (element.end >= changeRangeOldEnd) {
                    element.end += delta;
                }
                else {
                    element.end = Math.min(element.end, changeRangeNewEnd);
                }
                ts.Debug.assert(element.pos <= element.end);
                if (element.parent) {
                    ts.Debug.assert(element.pos >= element.parent.pos);
                    ts.Debug.assert(element.end <= element.parent.end);
                }
            }
            function checkNodePositions(node, aggressiveChecks) {
                if (aggressiveChecks) {
                    var pos = node.pos;
                    forEachChild(node, function (child) {
                        ts.Debug.assert(child.pos >= pos);
                        pos = child.end;
                    });
                    ts.Debug.assert(pos <= node.end);
                }
            }
            function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) {
                visitNode(sourceFile);
                return;
                function visitNode(child) {
                    ts.Debug.assert(child.pos <= child.end);
                    if (child.pos > changeRangeOldEnd) {
                        moveElementEntirelyPastChangeRange(child, false, delta, oldText, newText, aggressiveChecks);
                        return;
                    }
                    var fullEnd = child.end;
                    if (fullEnd >= changeStart) {
                        child.intersectsChange = true;
                        child._children = undefined;
                        adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
                        forEachChild(child, visitNode, visitArray);
                        checkNodePositions(child, aggressiveChecks);
                        return;
                    }
                    ts.Debug.assert(fullEnd < changeStart);
                }
                function visitArray(array) {
                    ts.Debug.assert(array.pos <= array.end);
                    if (array.pos > changeRangeOldEnd) {
                        moveElementEntirelyPastChangeRange(array, true, delta, oldText, newText, aggressiveChecks);
                        return;
                    }
                    var fullEnd = array.end;
                    if (fullEnd >= changeStart) {
                        array.intersectsChange = true;
                        array._children = undefined;
                        adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
                        for (var i = 0, n = array.length; i < n; i++) {
                            visitNode(array[i]);
                        }
                        return;
                    }
                    ts.Debug.assert(fullEnd < changeStart);
                }
            }
            function extendToAffectedRange(sourceFile, changeRange) {
                var maxLookahead = 1;
                var start = changeRange.span.start;
                for (var i = 0; start > 0 && i <= maxLookahead; i++) {
                    var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
                    ts.Debug.assert(nearestNode.pos <= start);
                    var position = nearestNode.pos;
                    start = Math.max(0, position - 1);
                }
                var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span));
                var finalLength = changeRange.newLength + (changeRange.span.start - start);
                return ts.createTextChangeRange(finalSpan, finalLength);
            }
            function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) {
                var bestResult = sourceFile;
                var lastNodeEntirelyBeforePosition;
                forEachChild(sourceFile, visit);
                if (lastNodeEntirelyBeforePosition) {
                    var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
                    if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
                        bestResult = lastChildOfLastEntireNodeBeforePosition;
                    }
                }
                return bestResult;
                function getLastChild(node) {
                    while (true) {
                        var lastChild = getLastChildWorker(node);
                        if (lastChild) {
                            node = lastChild;
                        }
                        else {
                            return node;
                        }
                    }
                }
                function getLastChildWorker(node) {
                    var last = undefined;
                    forEachChild(node, function (child) {
                        if (ts.nodeIsPresent(child)) {
                            last = child;
                        }
                    });
                    return last;
                }
                function visit(child) {
                    if (ts.nodeIsMissing(child)) {
                        return;
                    }
                    if (child.pos <= position) {
                        if (child.pos >= bestResult.pos) {
                            bestResult = child;
                        }
                        if (position < child.end) {
                            forEachChild(child, visit);
                            return true;
                        }
                        else {
                            ts.Debug.assert(child.end <= position);
                            lastNodeEntirelyBeforePosition = child;
                        }
                    }
                    else {
                        ts.Debug.assert(child.pos > position);
                        return true;
                    }
                }
            }
            function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) {
                var oldText = sourceFile.text;
                if (textChangeRange) {
                    ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
                    if (aggressiveChecks || ts.Debug.shouldAssert(3)) {
                        var oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
                        var newTextPrefix = newText.substr(0, textChangeRange.span.start);
                        ts.Debug.assert(oldTextPrefix === newTextPrefix);
                        var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length);
                        var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length);
                        ts.Debug.assert(oldTextSuffix === newTextSuffix);
                    }
                }
            }
            function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) {
                aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2);
                checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
                if (ts.textChangeRangeIsUnchanged(textChangeRange)) {
                    return sourceFile;
                }
                if (sourceFile.statements.length === 0) {
                    return parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true);
                }
                var incrementalSourceFile = sourceFile;
                ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
                incrementalSourceFile.hasBeenIncrementallyParsed = true;
                var oldText = sourceFile.text;
                var syntaxCursor = createSyntaxCursor(sourceFile);
                var changeRange = extendToAffectedRange(sourceFile, textChangeRange);
                checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
                ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start);
                ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span));
                ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)));
                var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
                updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
                var result = parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true);
                return result;
            }
            ts.updateSourceFile = updateSourceFile;
            function isEvalOrArgumentsIdentifier(node) {
                return node.kind === 64 && (node.text === "eval" || node.text === "arguments");
            }
            ts.isEvalOrArgumentsIdentifier = isEvalOrArgumentsIdentifier;
            function isUseStrictPrologueDirective(sourceFile, node) {
                ts.Debug.assert(ts.isPrologueDirective(node));
                var nodeText = ts.getSourceTextOfNodeFromSourceFile(sourceFile, node.expression);
                return nodeText === '"use strict"' || nodeText === "'use strict'";
            }
            var InvalidPosition;
            (function (InvalidPosition) {
                InvalidPosition[InvalidPosition["Value"] = -1] = "Value";
            })(InvalidPosition || (InvalidPosition = {}));
            function createSyntaxCursor(sourceFile) {
                var currentArray = sourceFile.statements;
                var currentArrayIndex = 0;
                ts.Debug.assert(currentArrayIndex < currentArray.length);
                var current = currentArray[currentArrayIndex];
                var lastQueriedPosition = -1;
                return {
                    currentNode: function (position) {
                        if (position !== lastQueriedPosition) {
                            if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
                                currentArrayIndex++;
                                current = currentArray[currentArrayIndex];
                            }
                            if (!current || current.pos !== position) {
                                findHighestListElementThatStartsAtPosition(position);
                            }
                        }
                        lastQueriedPosition = position;
                        ts.Debug.assert(!current || current.pos === position);
                        return current;
                    }
                };
                function findHighestListElementThatStartsAtPosition(position) {
                    currentArray = undefined;
                    currentArrayIndex = -1;
                    current = undefined;
                    forEachChild(sourceFile, visitNode, visitArray);
                    return;
                    function visitNode(node) {
                        if (position >= node.pos && position < node.end) {
                            forEachChild(node, visitNode, visitArray);
                            return true;
                        }
                        return false;
                    }
                    function visitArray(array) {
                        if (position >= array.pos && position < array.end) {
                            for (var i = 0, n = array.length; i < n; i++) {
                                var child = array[i];
                                if (child) {
                                    if (child.pos === position) {
                                        currentArray = array;
                                        currentArrayIndex = i;
                                        current = child;
                                        return true;
                                    }
                                    else {
                                        if (child.pos < position && position < child.end) {
                                            forEachChild(child, visitNode, visitArray);
                                            return true;
                                        }
                                    }
                                }
                            }
                        }
                        return false;
                    }
                }
            }
            function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) {
                if (setParentNodes === void 0) { setParentNodes = false; }
                var start = new Date().getTime();
                var result = parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes);
                ts.parseTime += new Date().getTime() - start;
                return result;
            }
            ts.createSourceFile = createSourceFile;
            function parseSourceFile(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes) {
                if (setParentNodes === void 0) { setParentNodes = false; }
                var parsingContext = 0;
                var identifiers = {};
                var identifierCount = 0;
                var nodeCount = 0;
                var token;
                var sourceFile = createNode(221, 0);
                sourceFile.pos = 0;
                sourceFile.end = sourceText.length;
                sourceFile.text = sourceText;
                sourceFile.parseDiagnostics = [];
                sourceFile.bindDiagnostics = [];
                sourceFile.languageVersion = languageVersion;
                sourceFile.fileName = ts.normalizePath(fileName);
                sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 2048 : 0;
                var contextFlags = 0;
                var parseErrorBeforeNextFinishedNode = false;
                var scanner = ts.createScanner(languageVersion, true, sourceText, scanError);
                token = nextToken();
                processReferenceComments(sourceFile);
                sourceFile.statements = parseList(0, true, parseSourceElement);
                ts.Debug.assert(token === 1);
                sourceFile.endOfFileToken = parseTokenNode();
                setExternalModuleIndicator(sourceFile);
                sourceFile.nodeCount = nodeCount;
                sourceFile.identifierCount = identifierCount;
                sourceFile.identifiers = identifiers;
                if (setParentNodes) {
                    fixupParentReferences(sourceFile);
                }
                syntaxCursor = undefined;
                return sourceFile;
                function setContextFlag(val, flag) {
                    if (val) {
                        contextFlags |= flag;
                    }
                    else {
                        contextFlags &= ~flag;
                    }
                }
                function setStrictModeContext(val) {
                    setContextFlag(val, 1);
                }
                function setDisallowInContext(val) {
                    setContextFlag(val, 2);
                }
                function setYieldContext(val) {
                    setContextFlag(val, 4);
                }
                function setGeneratorParameterContext(val) {
                    setContextFlag(val, 8);
                }
                function allowInAnd(func) {
                    if (contextFlags & 2) {
                        setDisallowInContext(false);
                        var result = func();
                        setDisallowInContext(true);
                        return result;
                    }
                    return func();
                }
                function disallowInAnd(func) {
                    if (contextFlags & 2) {
                        return func();
                    }
                    setDisallowInContext(true);
                    var result = func();
                    setDisallowInContext(false);
                    return result;
                }
                function doInYieldContext(func) {
                    if (contextFlags & 4) {
                        return func();
                    }
                    setYieldContext(true);
                    var result = func();
                    setYieldContext(false);
                    return result;
                }
                function doOutsideOfYieldContext(func) {
                    if (contextFlags & 4) {
                        setYieldContext(false);
                        var result = func();
                        setYieldContext(true);
                        return result;
                    }
                    return func();
                }
                function inYieldContext() {
                    return (contextFlags & 4) !== 0;
                }
                function inStrictModeContext() {
                    return (contextFlags & 1) !== 0;
                }
                function inGeneratorParameterContext() {
                    return (contextFlags & 8) !== 0;
                }
                function inDisallowInContext() {
                    return (contextFlags & 2) !== 0;
                }
                function parseErrorAtCurrentToken(message, arg0) {
                    var start = scanner.getTokenPos();
                    var length = scanner.getTextPos() - start;
                    parseErrorAtPosition(start, length, message, arg0);
                }
                function parseErrorAtPosition(start, length, message, arg0) {
                    var lastError = ts.lastOrUndefined(sourceFile.parseDiagnostics);
                    if (!lastError || start !== lastError.start) {
                        sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0));
                    }
                    parseErrorBeforeNextFinishedNode = true;
                }
                function scanError(message, length) {
                    var pos = scanner.getTextPos();
                    parseErrorAtPosition(pos, length || 0, message);
                }
                function getNodePos() {
                    return scanner.getStartPos();
                }
                function getNodeEnd() {
                    return scanner.getStartPos();
                }
                function nextToken() {
                    return token = scanner.scan();
                }
                function getTokenPos(pos) {
                    return ts.skipTrivia(sourceText, pos);
                }
                function reScanGreaterToken() {
                    return token = scanner.reScanGreaterToken();
                }
                function reScanSlashToken() {
                    return token = scanner.reScanSlashToken();
                }
                function reScanTemplateToken() {
                    return token = scanner.reScanTemplateToken();
                }
                function speculationHelper(callback, isLookAhead) {
                    var saveToken = token;
                    var saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length;
                    var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
                    var saveContextFlags = contextFlags;
                    var result = isLookAhead ? scanner.lookAhead(callback) : scanner.tryScan(callback);
                    ts.Debug.assert(saveContextFlags === contextFlags);
                    if (!result || isLookAhead) {
                        token = saveToken;
                        sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength;
                        parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
                    }
                    return result;
                }
                function lookAhead(callback) {
                    return speculationHelper(callback, true);
                }
                function tryParse(callback) {
                    return speculationHelper(callback, false);
                }
                function isIdentifier() {
                    if (token === 64) {
                        return true;
                    }
                    if (token === 110 && inYieldContext()) {
                        return false;
                    }
                    return inStrictModeContext() ? token > 110 : token > 100;
                }
                function parseExpected(kind, diagnosticMessage) {
                    if (token === kind) {
                        nextToken();
                        return true;
                    }
                    if (diagnosticMessage) {
                        parseErrorAtCurrentToken(diagnosticMessage);
                    }
                    else {
                        parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind));
                    }
                    return false;
                }
                function parseOptional(t) {
                    if (token === t) {
                        nextToken();
                        return true;
                    }
                    return false;
                }
                function parseOptionalToken(t) {
                    if (token === t) {
                        return parseTokenNode();
                    }
                    return undefined;
                }
                function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) {
                    return parseOptionalToken(t) || createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0);
                }
                function parseTokenNode() {
                    var node = createNode(token);
                    nextToken();
                    return finishNode(node);
                }
                function canParseSemicolon() {
                    if (token === 22) {
                        return true;
                    }
                    return token === 15 || token === 1 || scanner.hasPrecedingLineBreak();
                }
                function parseSemicolon() {
                    if (canParseSemicolon()) {
                        if (token === 22) {
                            nextToken();
                        }
                        return true;
                    }
                    else {
                        return parseExpected(22);
                    }
                }
                function createNode(kind, pos) {
                    nodeCount++;
                    var node = new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))();
                    if (!(pos >= 0)) {
                        pos = scanner.getStartPos();
                    }
                    node.pos = pos;
                    node.end = pos;
                    return node;
                }
                function finishNode(node) {
                    node.end = scanner.getStartPos();
                    if (contextFlags) {
                        node.parserContextFlags = contextFlags;
                    }
                    if (parseErrorBeforeNextFinishedNode) {
                        parseErrorBeforeNextFinishedNode = false;
                        node.parserContextFlags |= 16;
                    }
                    return node;
                }
                function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) {
                    if (reportAtCurrentPosition) {
                        parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
                    }
                    else {
                        parseErrorAtCurrentToken(diagnosticMessage, arg0);
                    }
                    var result = createNode(kind, scanner.getStartPos());
                    result.text = "";
                    return finishNode(result);
                }
                function internIdentifier(text) {
                    text = ts.escapeIdentifier(text);
                    return ts.hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
                }
                function createIdentifier(isIdentifier, diagnosticMessage) {
                    identifierCount++;
                    if (isIdentifier) {
                        var node = createNode(64);
                        node.text = internIdentifier(scanner.getTokenValue());
                        nextToken();
                        return finishNode(node);
                    }
                    return createMissingNode(64, false, diagnosticMessage || ts.Diagnostics.Identifier_expected);
                }
                function parseIdentifier(diagnosticMessage) {
                    return createIdentifier(isIdentifier(), diagnosticMessage);
                }
                function parseIdentifierName() {
                    return createIdentifier(isIdentifierOrKeyword());
                }
                function isLiteralPropertyName() {
                    return isIdentifierOrKeyword() || token === 8 || token === 7;
                }
                function parsePropertyName() {
                    if (token === 8 || token === 7) {
                        return parseLiteralNode(true);
                    }
                    if (token === 18) {
                        return parseComputedPropertyName();
                    }
                    return parseIdentifierName();
                }
                function parseComputedPropertyName() {
                    var node = createNode(126);
                    parseExpected(18);
                    var yieldContext = inYieldContext();
                    if (inGeneratorParameterContext()) {
                        setYieldContext(false);
                    }
                    node.expression = allowInAnd(parseExpression);
                    if (inGeneratorParameterContext()) {
                        setYieldContext(yieldContext);
                    }
                    parseExpected(19);
                    return finishNode(node);
                }
                function parseContextualModifier(t) {
                    return token === t && tryParse(nextTokenCanFollowModifier);
                }
                function nextTokenCanFollowModifier() {
                    nextToken();
                    return canFollowModifier();
                }
                function parseAnyContextualModifier() {
                    return ts.isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
                }
                function nextTokenCanFollowContextualModifier() {
                    if (token === 69) {
                        return nextToken() === 76;
                    }
                    if (token === 77) {
                        nextToken();
                        if (token === 72) {
                            return lookAhead(nextTokenIsClassOrFunction);
                        }
                        return token !== 35 && token !== 14 && canFollowModifier();
                    }
                    if (token === 72) {
                        return nextTokenIsClassOrFunction();
                    }
                    nextToken();
                    return canFollowModifier();
                }
                function canFollowModifier() {
                    return token === 18 || token === 14 || token === 35 || isLiteralPropertyName();
                }
                function nextTokenIsClassOrFunction() {
                    nextToken();
                    return token === 68 || token === 82;
                }
                function isListElement(parsingContext, inErrorRecovery) {
                    var node = currentNode(parsingContext);
                    if (node) {
                        return true;
                    }
                    switch (parsingContext) {
                        case 0:
                        case 1:
                            return isSourceElement(inErrorRecovery);
                        case 2:
                        case 4:
                            return isStartOfStatement(inErrorRecovery);
                        case 3:
                            return token === 66 || token === 72;
                        case 5:
                            return isStartOfTypeMember();
                        case 6:
                            return lookAhead(isClassMemberStart);
                        case 7:
                            return token === 18 || isLiteralPropertyName();
                        case 13:
                            return token === 18 || token === 35 || isLiteralPropertyName();
                        case 10:
                            return isLiteralPropertyName();
                        case 8:
                            return isIdentifier() && !isNotHeritageClauseTypeName();
                        case 9:
                            return isIdentifierOrPattern();
                        case 11:
                            return token === 23 || token === 21 || isIdentifierOrPattern();
                        case 16:
                            return isIdentifier();
                        case 12:
                        case 14:
                            return token === 23 || token === 21 || isStartOfExpression();
                        case 15:
                            return isStartOfParameter();
                        case 17:
                        case 18:
                            return token === 23 || isStartOfType();
                        case 19:
                            return isHeritageClause();
                        case 20:
                            return isIdentifierOrKeyword();
                    }
                    ts.Debug.fail("Non-exhaustive case in 'isListElement'.");
                }
                function nextTokenIsIdentifier() {
                    nextToken();
                    return isIdentifier();
                }
                function isNotHeritageClauseTypeName() {
                    if (token === 102 || token === 78) {
                        return lookAhead(nextTokenIsIdentifier);
                    }
                    return false;
                }
                function isListTerminator(kind) {
                    if (token === 1) {
                        return true;
                    }
                    switch (kind) {
                        case 1:
                        case 2:
                        case 3:
                        case 5:
                        case 6:
                        case 7:
                        case 13:
                        case 10:
                        case 20:
                            return token === 15;
                        case 4:
                            return token === 15 || token === 66 || token === 72;
                        case 8:
                            return token === 14 || token === 78 || token === 102;
                        case 9:
                            return isVariableDeclaratorListTerminator();
                        case 16:
                            return token === 25 || token === 16 || token === 14 || token === 78 || token === 102;
                        case 12:
                            return token === 17 || token === 22;
                        case 14:
                        case 18:
                        case 11:
                            return token === 19;
                        case 15:
                            return token === 17 || token === 19;
                        case 17:
                            return token === 25 || token === 16;
                        case 19:
                            return token === 14 || token === 15;
                    }
                }
                function isVariableDeclaratorListTerminator() {
                    if (canParseSemicolon()) {
                        return true;
                    }
                    if (isInOrOfKeyword(token)) {
                        return true;
                    }
                    if (token === 32) {
                        return true;
                    }
                    return false;
                }
                function isInSomeParsingContext() {
                    for (var kind = 0; kind < 21; kind++) {
                        if (parsingContext & (1 << kind)) {
                            if (isListElement(kind, true) || isListTerminator(kind)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                function parseList(kind, checkForStrictMode, parseElement) {
                    var saveParsingContext = parsingContext;
                    parsingContext |= 1 << kind;
                    var result = [];
                    result.pos = getNodePos();
                    var savedStrictModeContext = inStrictModeContext();
                    while (!isListTerminator(kind)) {
                        if (isListElement(kind, false)) {
                            var element = parseListElement(kind, parseElement);
                            result.push(element);
                            if (checkForStrictMode && !inStrictModeContext()) {
                                if (ts.isPrologueDirective(element)) {
                                    if (isUseStrictPrologueDirective(sourceFile, element)) {
                                        setStrictModeContext(true);
                                        checkForStrictMode = false;
                                    }
                                }
                                else {
                                    checkForStrictMode = false;
                                }
                            }
                            continue;
                        }
                        if (abortParsingListOrMoveToNextToken(kind)) {
                            break;
                        }
                    }
                    setStrictModeContext(savedStrictModeContext);
                    result.end = getNodeEnd();
                    parsingContext = saveParsingContext;
                    return result;
                }
                function parseListElement(parsingContext, parseElement) {
                    var node = currentNode(parsingContext);
                    if (node) {
                        return consumeNode(node);
                    }
                    return parseElement();
                }
                function currentNode(parsingContext) {
                    if (parseErrorBeforeNextFinishedNode) {
                        return undefined;
                    }
                    if (!syntaxCursor) {
                        return undefined;
                    }
                    var node = syntaxCursor.currentNode(scanner.getStartPos());
                    if (ts.nodeIsMissing(node)) {
                        return undefined;
                    }
                    if (node.intersectsChange) {
                        return undefined;
                    }
                    if (ts.containsParseError(node)) {
                        return undefined;
                    }
                    var nodeContextFlags = node.parserContextFlags & 31;
                    if (nodeContextFlags !== contextFlags) {
                        return undefined;
                    }
                    if (!canReuseNode(node, parsingContext)) {
                        return undefined;
                    }
                    return node;
                }
                function consumeNode(node) {
                    scanner.setTextPos(node.end);
                    nextToken();
                    return node;
                }
                function canReuseNode(node, parsingContext) {
                    switch (parsingContext) {
                        case 1:
                            return isReusableModuleElement(node);
                        case 6:
                            return isReusableClassMember(node);
                        case 3:
                            return isReusableSwitchClause(node);
                        case 2:
                        case 4:
                            return isReusableStatement(node);
                        case 7:
                            return isReusableEnumMember(node);
                        case 5:
                            return isReusableTypeMember(node);
                        case 9:
                            return isReusableVariableDeclaration(node);
                        case 15:
                            return isReusableParameter(node);
                        case 19:
                        case 8:
                        case 16:
                        case 18:
                        case 17:
                        case 12:
                        case 13:
                    }
                    return false;
                }
                function isReusableModuleElement(node) {
                    if (node) {
                        switch (node.kind) {
                            case 204:
                            case 203:
                            case 210:
                            case 209:
                            case 196:
                            case 197:
                            case 200:
                            case 199:
                                return true;
                        }
                        return isReusableStatement(node);
                    }
                    return false;
                }
                function isReusableClassMember(node) {
                    if (node) {
                        switch (node.kind) {
                            case 133:
                            case 138:
                            case 132:
                            case 134:
                            case 135:
                            case 130:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableSwitchClause(node) {
                    if (node) {
                        switch (node.kind) {
                            case 214:
                            case 215:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableStatement(node) {
                    if (node) {
                        switch (node.kind) {
                            case 195:
                            case 175:
                            case 174:
                            case 178:
                            case 177:
                            case 190:
                            case 186:
                            case 188:
                            case 185:
                            case 184:
                            case 182:
                            case 183:
                            case 181:
                            case 180:
                            case 187:
                            case 176:
                            case 191:
                            case 189:
                            case 179:
                            case 192:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableEnumMember(node) {
                    return node.kind === 220;
                }
                function isReusableTypeMember(node) {
                    if (node) {
                        switch (node.kind) {
                            case 137:
                            case 131:
                            case 138:
                            case 129:
                            case 136:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableVariableDeclaration(node) {
                    if (node.kind !== 193) {
                        return false;
                    }
                    var variableDeclarator = node;
                    return variableDeclarator.initializer === undefined;
                }
                function isReusableParameter(node) {
                    if (node.kind !== 128) {
                        return false;
                    }
                    var parameter = node;
                    return parameter.initializer === undefined;
                }
                function abortParsingListOrMoveToNextToken(kind) {
                    parseErrorAtCurrentToken(parsingContextErrors(kind));
                    if (isInSomeParsingContext()) {
                        return true;
                    }
                    nextToken();
                    return false;
                }
                function parseDelimitedList(kind, parseElement, considerSemicolonAsDelimeter) {
                    var saveParsingContext = parsingContext;
                    parsingContext |= 1 << kind;
                    var result = [];
                    result.pos = getNodePos();
                    var commaStart = -1;
                    while (true) {
                        if (isListElement(kind, false)) {
                            result.push(parseListElement(kind, parseElement));
                            commaStart = scanner.getTokenPos();
                            if (parseOptional(23)) {
                                continue;
                            }
                            commaStart = -1;
                            if (isListTerminator(kind)) {
                                break;
                            }
                            parseExpected(23);
                            if (considerSemicolonAsDelimeter && token === 22 && !scanner.hasPrecedingLineBreak()) {
                                nextToken();
                            }
                            continue;
                        }
                        if (isListTerminator(kind)) {
                            break;
                        }
                        if (abortParsingListOrMoveToNextToken(kind)) {
                            break;
                        }
                    }
                    if (commaStart >= 0) {
                        result.hasTrailingComma = true;
                    }
                    result.end = getNodeEnd();
                    parsingContext = saveParsingContext;
                    return result;
                }
                function createMissingList() {
                    var pos = getNodePos();
                    var result = [];
                    result.pos = pos;
                    result.end = pos;
                    return result;
                }
                function parseBracketedList(kind, parseElement, open, close) {
                    if (parseExpected(open)) {
                        var result = parseDelimitedList(kind, parseElement);
                        parseExpected(close);
                        return result;
                    }
                    return createMissingList();
                }
                function parseEntityName(allowReservedWords, diagnosticMessage) {
                    var entity = parseIdentifier(diagnosticMessage);
                    while (parseOptional(20)) {
                        var node = createNode(125, entity.pos);
                        node.left = entity;
                        node.right = parseRightSideOfDot(allowReservedWords);
                        entity = finishNode(node);
                    }
                    return entity;
                }
                function parseRightSideOfDot(allowIdentifierNames) {
                    if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) {
                        var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
                        if (matchesPattern) {
                            return createMissingNode(64, true, ts.Diagnostics.Identifier_expected);
                        }
                    }
                    return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
                }
                function parseTemplateExpression() {
                    var template = createNode(169);
                    template.head = parseLiteralNode();
                    ts.Debug.assert(template.head.kind === 11, "Template head has wrong token kind");
                    var templateSpans = [];
                    templateSpans.pos = getNodePos();
                    do {
                        templateSpans.push(parseTemplateSpan());
                    } while (templateSpans[templateSpans.length - 1].literal.kind === 12);
                    templateSpans.end = getNodeEnd();
                    template.templateSpans = templateSpans;
                    return finishNode(template);
                }
                function parseTemplateSpan() {
                    var span = createNode(173);
                    span.expression = allowInAnd(parseExpression);
                    var literal;
                    if (token === 15) {
                        reScanTemplateToken();
                        literal = parseLiteralNode();
                    }
                    else {
                        literal = parseExpectedToken(13, false, ts.Diagnostics._0_expected, ts.tokenToString(15));
                    }
                    span.literal = literal;
                    return finishNode(span);
                }
                function parseLiteralNode(internName) {
                    var node = createNode(token);
                    var text = scanner.getTokenValue();
                    node.text = internName ? internIdentifier(text) : text;
                    if (scanner.hasExtendedUnicodeEscape()) {
                        node.hasExtendedUnicodeEscape = true;
                    }
                    if (scanner.isUnterminated()) {
                        node.isUnterminated = true;
                    }
                    var tokenPos = scanner.getTokenPos();
                    nextToken();
                    finishNode(node);
                    if (node.kind === 7 && sourceText.charCodeAt(tokenPos) === 48 && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) {
                        node.flags |= 16384;
                    }
                    return node;
                }
                function parseTypeReference() {
                    var node = createNode(139);
                    node.typeName = parseEntityName(false, ts.Diagnostics.Type_expected);
                    if (!scanner.hasPrecedingLineBreak() && token === 24) {
                        node.typeArguments = parseBracketedList(17, parseType, 24, 25);
                    }
                    return finishNode(node);
                }
                function parseTypeQuery() {
                    var node = createNode(142);
                    parseExpected(96);
                    node.exprName = parseEntityName(true);
                    return finishNode(node);
                }
                function parseTypeParameter() {
                    var node = createNode(127);
                    node.name = parseIdentifier();
                    if (parseOptional(78)) {
                        if (isStartOfType() || !isStartOfExpression()) {
                            node.constraint = parseType();
                        }
                        else {
                            node.expression = parseUnaryExpressionOrHigher();
                        }
                    }
                    return finishNode(node);
                }
                function parseTypeParameters() {
                    if (token === 24) {
                        return parseBracketedList(16, parseTypeParameter, 24, 25);
                    }
                }
                function parseParameterType() {
                    if (parseOptional(51)) {
                        return token === 8 ? parseLiteralNode(true) : parseType();
                    }
                    return undefined;
                }
                function isStartOfParameter() {
                    return token === 21 || isIdentifierOrPattern() || ts.isModifier(token);
                }
                function setModifiers(node, modifiers) {
                    if (modifiers) {
                        node.flags |= modifiers.flags;
                        node.modifiers = modifiers;
                    }
                }
                function parseParameter() {
                    var node = createNode(128);
                    setModifiers(node, parseModifiers());
                    node.dotDotDotToken = parseOptionalToken(21);
                    node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
                    if (ts.getFullWidth(node.name) === 0 && node.flags === 0 && ts.isModifier(token)) {
                        nextToken();
                    }
                    node.questionToken = parseOptionalToken(50);
                    node.type = parseParameterType();
                    node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
                    return finishNode(node);
                }
                function parseParameterInitializer() {
                    return parseInitializer(true);
                }
                function fillSignature(returnToken, yieldAndGeneratorParameterContext, requireCompleteParameterList, signature) {
                    var returnTokenRequired = returnToken === 32;
                    signature.typeParameters = parseTypeParameters();
                    signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
                    if (returnTokenRequired) {
                        parseExpected(returnToken);
                        signature.type = parseType();
                    }
                    else if (parseOptional(returnToken)) {
                        signature.type = parseType();
                    }
                }
                function parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList) {
                    if (parseExpected(16)) {
                        var savedYieldContext = inYieldContext();
                        var savedGeneratorParameterContext = inGeneratorParameterContext();
                        setYieldContext(yieldAndGeneratorParameterContext);
                        setGeneratorParameterContext(yieldAndGeneratorParameterContext);
                        var result = parseDelimitedList(15, parseParameter);
                        setYieldContext(savedYieldContext);
                        setGeneratorParameterContext(savedGeneratorParameterContext);
                        if (!parseExpected(17) && requireCompleteParameterList) {
                            return undefined;
                        }
                        return result;
                    }
                    return requireCompleteParameterList ? undefined : createMissingList();
                }
                function parseTypeMemberSemicolon() {
                    if (parseOptional(23)) {
                        return;
                    }
                    parseSemicolon();
                }
                function parseSignatureMember(kind) {
                    var node = createNode(kind);
                    if (kind === 137) {
                        parseExpected(87);
                    }
                    fillSignature(51, false, false, node);
                    parseTypeMemberSemicolon();
                    return finishNode(node);
                }
                function isIndexSignature() {
                    if (token !== 18) {
                        return false;
                    }
                    return lookAhead(isUnambiguouslyIndexSignature);
                }
                function isUnambiguouslyIndexSignature() {
                    nextToken();
                    if (token === 21 || token === 19) {
                        return true;
                    }
                    if (ts.isModifier(token)) {
                        nextToken();
                        if (isIdentifier()) {
                            return true;
                        }
                    }
                    else if (!isIdentifier()) {
                        return false;
                    }
                    else {
                        nextToken();
                    }
                    if (token === 51 || token === 23) {
                        return true;
                    }
                    if (token !== 50) {
                        return false;
                    }
                    nextToken();
                    return token === 51 || token === 23 || token === 19;
                }
                function parseIndexSignatureDeclaration(modifiers) {
                    var fullStart = modifiers ? modifiers.pos : scanner.getStartPos();
                    var node = createNode(138, fullStart);
                    setModifiers(node, modifiers);
                    node.parameters = parseBracketedList(15, parseParameter, 18, 19);
                    node.type = parseTypeAnnotation();
                    parseTypeMemberSemicolon();
                    return finishNode(node);
                }
                function parsePropertyOrMethodSignature() {
                    var fullStart = scanner.getStartPos();
                    var name = parsePropertyName();
                    var questionToken = parseOptionalToken(50);
                    if (token === 16 || token === 24) {
                        var method = createNode(131, fullStart);
                        method.name = name;
                        method.questionToken = questionToken;
                        fillSignature(51, false, false, method);
                        parseTypeMemberSemicolon();
                        return finishNode(method);
                    }
                    else {
                        var property = createNode(129, fullStart);
                        property.name = name;
                        property.questionToken = questionToken;
                        property.type = parseTypeAnnotation();
                        parseTypeMemberSemicolon();
                        return finishNode(property);
                    }
                }
                function isStartOfTypeMember() {
                    switch (token) {
                        case 16:
                        case 24:
                        case 18:
                            return true;
                        default:
                            if (ts.isModifier(token)) {
                                var result = lookAhead(isStartOfIndexSignatureDeclaration);
                                if (result) {
                                    return result;
                                }
                            }
                            return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName);
                    }
                }
                function isStartOfIndexSignatureDeclaration() {
                    while (ts.isModifier(token)) {
                        nextToken();
                    }
                    return isIndexSignature();
                }
                function isTypeMemberWithLiteralPropertyName() {
                    nextToken();
                    return token === 16 || token === 24 || token === 50 || token === 51 || canParseSemicolon();
                }
                function parseTypeMember() {
                    switch (token) {
                        case 16:
                        case 24:
                            return parseSignatureMember(136);
                        case 18:
                            return isIndexSignature() ? parseIndexSignatureDeclaration(undefined) : parsePropertyOrMethodSignature();
                        case 87:
                            if (lookAhead(isStartOfConstructSignature)) {
                                return parseSignatureMember(137);
                            }
                        case 8:
                        case 7:
                            return parsePropertyOrMethodSignature();
                        default:
                            if (ts.isModifier(token)) {
                                var result = tryParse(parseIndexSignatureWithModifiers);
                                if (result) {
                                    return result;
                                }
                            }
                            if (isIdentifierOrKeyword()) {
                                return parsePropertyOrMethodSignature();
                            }
                    }
                }
                function parseIndexSignatureWithModifiers() {
                    var modifiers = parseModifiers();
                    return isIndexSignature() ? parseIndexSignatureDeclaration(modifiers) : undefined;
                }
                function isStartOfConstructSignature() {
                    nextToken();
                    return token === 16 || token === 24;
                }
                function parseTypeLiteral() {
                    var node = createNode(143);
                    node.members = parseObjectTypeMembers();
                    return finishNode(node);
                }
                function parseObjectTypeMembers() {
                    var members;
                    if (parseExpected(14)) {
                        members = parseList(5, false, parseTypeMember);
                        parseExpected(15);
                    }
                    else {
                        members = createMissingList();
                    }
                    return members;
                }
                function parseTupleType() {
                    var node = createNode(145);
                    node.elementTypes = parseBracketedList(18, parseType, 18, 19);
                    return finishNode(node);
                }
                function parseParenthesizedType() {
                    var node = createNode(147);
                    parseExpected(16);
                    node.type = parseType();
                    parseExpected(17);
                    return finishNode(node);
                }
                function parseFunctionOrConstructorType(kind) {
                    var node = createNode(kind);
                    if (kind === 141) {
                        parseExpected(87);
                    }
                    fillSignature(32, false, false, node);
                    return finishNode(node);
                }
                function parseKeywordAndNoDot() {
                    var node = parseTokenNode();
                    return token === 20 ? undefined : node;
                }
                function parseNonArrayType() {
                    switch (token) {
                        case 111:
                        case 120:
                        case 118:
                        case 112:
                        case 121:
                            var node = tryParse(parseKeywordAndNoDot);
                            return node || parseTypeReference();
                        case 98:
                            return parseTokenNode();
                        case 96:
                            return parseTypeQuery();
                        case 14:
                            return parseTypeLiteral();
                        case 18:
                            return parseTupleType();
                        case 16:
                            return parseParenthesizedType();
                        default:
                            return parseTypeReference();
                    }
                }
                function isStartOfType() {
                    switch (token) {
                        case 111:
                        case 120:
                        case 118:
                        case 112:
                        case 121:
                        case 98:
                        case 96:
                        case 14:
                        case 18:
                        case 24:
                        case 87:
                            return true;
                        case 16:
                            return lookAhead(isStartOfParenthesizedOrFunctionType);
                        default:
                            return isIdentifier();
                    }
                }
                function isStartOfParenthesizedOrFunctionType() {
                    nextToken();
                    return token === 17 || isStartOfParameter() || isStartOfType();
                }
                function parseArrayTypeOrHigher() {
                    var type = parseNonArrayType();
                    while (!scanner.hasPrecedingLineBreak() && parseOptional(18)) {
                        parseExpected(19);
                        var node = createNode(144, type.pos);
                        node.elementType = type;
                        type = finishNode(node);
                    }
                    return type;
                }
                function parseUnionTypeOrHigher() {
                    var type = parseArrayTypeOrHigher();
                    if (token === 44) {
                        var types = [
                            type
                        ];
                        types.pos = type.pos;
                        while (parseOptional(44)) {
                            types.push(parseArrayTypeOrHigher());
                        }
                        types.end = getNodeEnd();
                        var node = createNode(146, type.pos);
                        node.types = types;
                        type = finishNode(node);
                    }
                    return type;
                }
                function isStartOfFunctionType() {
                    if (token === 24) {
                        return true;
                    }
                    return token === 16 && lookAhead(isUnambiguouslyStartOfFunctionType);
                }
                function isUnambiguouslyStartOfFunctionType() {
                    nextToken();
                    if (token === 17 || token === 21) {
                        return true;
                    }
                    if (isIdentifier() || ts.isModifier(token)) {
                        nextToken();
                        if (token === 51 || token === 23 || token === 50 || token === 52 || isIdentifier() || ts.isModifier(token)) {
                            return true;
                        }
                        if (token === 17) {
                            nextToken();
                            if (token === 32) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                function parseType() {
                    var savedYieldContext = inYieldContext();
                    var savedGeneratorParameterContext = inGeneratorParameterContext();
                    setYieldContext(false);
                    setGeneratorParameterContext(false);
                    var result = parseTypeWorker();
                    setYieldContext(savedYieldContext);
                    setGeneratorParameterContext(savedGeneratorParameterContext);
                    return result;
                }
                function parseTypeWorker() {
                    if (isStartOfFunctionType()) {
                        return parseFunctionOrConstructorType(140);
                    }
                    if (token === 87) {
                        return parseFunctionOrConstructorType(141);
                    }
                    return parseUnionTypeOrHigher();
                }
                function parseTypeAnnotation() {
                    return parseOptional(51) ? parseType() : undefined;
                }
                function isStartOfExpression() {
                    switch (token) {
                        case 92:
                        case 90:
                        case 88:
                        case 94:
                        case 79:
                        case 7:
                        case 8:
                        case 10:
                        case 11:
                        case 16:
                        case 18:
                        case 14:
                        case 82:
                        case 87:
                        case 36:
                        case 56:
                        case 33:
                        case 34:
                        case 47:
                        case 46:
                        case 73:
                        case 96:
                        case 98:
                        case 38:
                        case 39:
                        case 24:
                        case 64:
                        case 110:
                            return true;
                        default:
                            if (isBinaryOperator()) {
                                return true;
                            }
                            return isIdentifier();
                    }
                }
                function isStartOfExpressionStatement() {
                    return token !== 14 && token !== 82 && isStartOfExpression();
                }
                function parseExpression() {
                    var expr = parseAssignmentExpressionOrHigher();
                    var operatorToken;
                    while ((operatorToken = parseOptionalToken(23))) {
                        expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
                    }
                    return expr;
                }
                function parseInitializer(inParameter) {
                    if (token !== 52) {
                        if (scanner.hasPrecedingLineBreak() || (inParameter && token === 14) || !isStartOfExpression()) {
                            return undefined;
                        }
                    }
                    parseExpected(52);
                    return parseAssignmentExpressionOrHigher();
                }
                function parseAssignmentExpressionOrHigher() {
                    if (isYieldExpression()) {
                        return parseYieldExpression();
                    }
                    var arrowExpression = tryParseParenthesizedArrowFunctionExpression();
                    if (arrowExpression) {
                        return arrowExpression;
                    }
                    var expr = parseBinaryExpressionOrHigher(0);
                    if (expr.kind === 64 && token === 32) {
                        return parseSimpleArrowFunctionExpression(expr);
                    }
                    if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
                        return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
                    }
                    return parseConditionalExpressionRest(expr);
                }
                function isYieldExpression() {
                    if (token === 110) {
                        if (inYieldContext()) {
                            return true;
                        }
                        if (inStrictModeContext()) {
                            return true;
                        }
                        return lookAhead(nextTokenIsIdentifierOnSameLine);
                    }
                    return false;
                }
                function nextTokenIsIdentifierOnSameLine() {
                    nextToken();
                    return !scanner.hasPrecedingLineBreak() && isIdentifier();
                }
                function parseYieldExpression() {
                    var node = createNode(170);
                    nextToken();
                    if (!scanner.hasPrecedingLineBreak() && (token === 35 || isStartOfExpression())) {
                        node.asteriskToken = parseOptionalToken(35);
                        node.expression = parseAssignmentExpressionOrHigher();
                        return finishNode(node);
                    }
                    else {
                        return finishNode(node);
                    }
                }
                function parseSimpleArrowFunctionExpression(identifier) {
                    ts.Debug.assert(token === 32, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
                    var node = createNode(161, identifier.pos);
                    var parameter = createNode(128, identifier.pos);
                    parameter.name = identifier;
                    finishNode(parameter);
                    node.parameters = [
                        parameter
                    ];
                    node.parameters.pos = parameter.pos;
                    node.parameters.end = parameter.end;
                    parseExpected(32);
                    node.body = parseArrowFunctionExpressionBody();
                    return finishNode(node);
                }
                function tryParseParenthesizedArrowFunctionExpression() {
                    var triState = isParenthesizedArrowFunctionExpression();
                    if (triState === 0) {
                        return undefined;
                    }
                    var arrowFunction = triState === 1 ? parseParenthesizedArrowFunctionExpressionHead(true) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
                    if (!arrowFunction) {
                        return undefined;
                    }
                    if (parseExpected(32) || token === 14) {
                        arrowFunction.body = parseArrowFunctionExpressionBody();
                    }
                    else {
                        arrowFunction.body = parseIdentifier();
                    }
                    return finishNode(arrowFunction);
                }
                function isParenthesizedArrowFunctionExpression() {
                    if (token === 16 || token === 24) {
                        return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
                    }
                    if (token === 32) {
                        return 1;
                    }
                    return 0;
                }
                function isParenthesizedArrowFunctionExpressionWorker() {
                    var first = token;
                    var second = nextToken();
                    if (first === 16) {
                        if (second === 17) {
                            var third = nextToken();
                            switch (third) {
                                case 32:
                                case 51:
                                case 14:
                                    return 1;
                                default:
                                    return 0;
                            }
                        }
                        if (second === 21) {
                            return 1;
                        }
                        if (!isIdentifier()) {
                            return 0;
                        }
                        if (nextToken() === 51) {
                            return 1;
                        }
                        return 2;
                    }
                    else {
                        ts.Debug.assert(first === 24);
                        if (!isIdentifier()) {
                            return 0;
                        }
                        return 2;
                    }
                }
                function parsePossibleParenthesizedArrowFunctionExpressionHead() {
                    return parseParenthesizedArrowFunctionExpressionHead(false);
                }
                function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) {
                    var node = createNode(161);
                    fillSignature(51, false, !allowAmbiguity, node);
                    if (!node.parameters) {
                        return undefined;
                    }
                    if (!allowAmbiguity && token !== 32 && token !== 14) {
                        return undefined;
                    }
                    return node;
                }
                function parseArrowFunctionExpressionBody() {
                    if (token === 14) {
                        return parseFunctionBlock(false, false);
                    }
                    if (isStartOfStatement(true) && !isStartOfExpressionStatement() && token !== 82) {
                        return parseFunctionBlock(false, true);
                    }
                    return parseAssignmentExpressionOrHigher();
                }
                function parseConditionalExpressionRest(leftOperand) {
                    var questionToken = parseOptionalToken(50);
                    if (!questionToken) {
                        return leftOperand;
                    }
                    var node = createNode(168, leftOperand.pos);
                    node.condition = leftOperand;
                    node.questionToken = questionToken;
                    node.whenTrue = allowInAnd(parseAssignmentExpressionOrHigher);
                    node.colonToken = parseExpectedToken(51, false, ts.Diagnostics._0_expected, ts.tokenToString(51));
                    node.whenFalse = parseAssignmentExpressionOrHigher();
                    return finishNode(node);
                }
                function parseBinaryExpressionOrHigher(precedence) {
                    var leftOperand = parseUnaryExpressionOrHigher();
                    return parseBinaryExpressionRest(precedence, leftOperand);
                }
                function isInOrOfKeyword(t) {
                    return t === 85 || t === 124;
                }
                function parseBinaryExpressionRest(precedence, leftOperand) {
                    while (true) {
                        reScanGreaterToken();
                        var newPrecedence = getBinaryOperatorPrecedence();
                        if (newPrecedence <= precedence) {
                            break;
                        }
                        if (token === 85 && inDisallowInContext()) {
                            break;
                        }
                        leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
                    }
                    return leftOperand;
                }
                function isBinaryOperator() {
                    if (inDisallowInContext() && token === 85) {
                        return false;
                    }
                    return getBinaryOperatorPrecedence() > 0;
                }
                function getBinaryOperatorPrecedence() {
                    switch (token) {
                        case 49:
                            return 1;
                        case 48:
                            return 2;
                        case 44:
                            return 3;
                        case 45:
                            return 4;
                        case 43:
                            return 5;
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                            return 6;
                        case 24:
                        case 25:
                        case 26:
                        case 27:
                        case 86:
                        case 85:
                            return 7;
                        case 40:
                        case 41:
                        case 42:
                            return 8;
                        case 33:
                        case 34:
                            return 9;
                        case 35:
                        case 36:
                        case 37:
                            return 10;
                    }
                    return -1;
                }
                function makeBinaryExpression(left, operatorToken, right) {
                    var node = createNode(167, left.pos);
                    node.left = left;
                    node.operatorToken = operatorToken;
                    node.right = right;
                    return finishNode(node);
                }
                function parsePrefixUnaryExpression() {
                    var node = createNode(165);
                    node.operator = token;
                    nextToken();
                    node.operand = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseDeleteExpression() {
                    var node = createNode(162);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseTypeOfExpression() {
                    var node = createNode(163);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseVoidExpression() {
                    var node = createNode(164);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseUnaryExpressionOrHigher() {
                    switch (token) {
                        case 33:
                        case 34:
                        case 47:
                        case 46:
                        case 38:
                        case 39:
                            return parsePrefixUnaryExpression();
                        case 73:
                            return parseDeleteExpression();
                        case 96:
                            return parseTypeOfExpression();
                        case 98:
                            return parseVoidExpression();
                        case 24:
                            return parseTypeAssertion();
                        default:
                            return parsePostfixExpressionOrHigher();
                    }
                }
                function parsePostfixExpressionOrHigher() {
                    var expression = parseLeftHandSideExpressionOrHigher();
                    ts.Debug.assert(isLeftHandSideExpression(expression));
                    if ((token === 38 || token === 39) && !scanner.hasPrecedingLineBreak()) {
                        var node = createNode(166, expression.pos);
                        node.operand = expression;
                        node.operator = token;
                        nextToken();
                        return finishNode(node);
                    }
                    return expression;
                }
                function parseLeftHandSideExpressionOrHigher() {
                    var expression = token === 90 ? parseSuperExpression() : parseMemberExpressionOrHigher();
                    return parseCallExpressionRest(expression);
                }
                function parseMemberExpressionOrHigher() {
                    var expression = parsePrimaryExpression();
                    return parseMemberExpressionRest(expression);
                }
                function parseSuperExpression() {
                    var expression = parseTokenNode();
                    if (token === 16 || token === 20) {
                        return expression;
                    }
                    var node = createNode(153, expression.pos);
                    node.expression = expression;
                    node.dotToken = parseExpectedToken(20, false, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
                    node.name = parseRightSideOfDot(true);
                    return finishNode(node);
                }
                function parseTypeAssertion() {
                    var node = createNode(158);
                    parseExpected(24);
                    node.type = parseType();
                    parseExpected(25);
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseMemberExpressionRest(expression) {
                    while (true) {
                        var dotToken = parseOptionalToken(20);
                        if (dotToken) {
                            var propertyAccess = createNode(153, expression.pos);
                            propertyAccess.expression = expression;
                            propertyAccess.dotToken = dotToken;
                            propertyAccess.name = parseRightSideOfDot(true);
                            expression = finishNode(propertyAccess);
                            continue;
                        }
                        if (parseOptional(18)) {
                            var indexedAccess = createNode(154, expression.pos);
                            indexedAccess.expression = expression;
                            if (token !== 19) {
                                indexedAccess.argumentExpression = allowInAnd(parseExpression);
                                if (indexedAccess.argumentExpression.kind === 8 || indexedAccess.argumentExpression.kind === 7) {
                                    var literal = indexedAccess.argumentExpression;
                                    literal.text = internIdentifier(literal.text);
                                }
                            }
                            parseExpected(19);
                            expression = finishNode(indexedAccess);
                            continue;
                        }
                        if (token === 10 || token === 11) {
                            var tagExpression = createNode(157, expression.pos);
                            tagExpression.tag = expression;
                            tagExpression.template = token === 10 ? parseLiteralNode() : parseTemplateExpression();
                            expression = finishNode(tagExpression);
                            continue;
                        }
                        return expression;
                    }
                }
                function parseCallExpressionRest(expression) {
                    while (true) {
                        expression = parseMemberExpressionRest(expression);
                        if (token === 24) {
                            var typeArguments = tryParse(parseTypeArgumentsInExpression);
                            if (!typeArguments) {
                                return expression;
                            }
                            var callExpr = createNode(155, expression.pos);
                            callExpr.expression = expression;
                            callExpr.typeArguments = typeArguments;
                            callExpr.arguments = parseArgumentList();
                            expression = finishNode(callExpr);
                            continue;
                        }
                        else if (token === 16) {
                            var callExpr = createNode(155, expression.pos);
                            callExpr.expression = expression;
                            callExpr.arguments = parseArgumentList();
                            expression = finishNode(callExpr);
                            continue;
                        }
                        return expression;
                    }
                }
                function parseArgumentList() {
                    parseExpected(16);
                    var result = parseDelimitedList(12, parseArgumentExpression);
                    parseExpected(17);
                    return result;
                }
                function parseTypeArgumentsInExpression() {
                    if (!parseOptional(24)) {
                        return undefined;
                    }
                    var typeArguments = parseDelimitedList(17, parseType);
                    if (!parseExpected(25)) {
                        return undefined;
                    }
                    return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : undefined;
                }
                function canFollowTypeArgumentsInExpression() {
                    switch (token) {
                        case 16:
                        case 20:
                        case 17:
                        case 19:
                        case 51:
                        case 22:
                        case 23:
                        case 50:
                        case 28:
                        case 30:
                        case 29:
                        case 31:
                        case 48:
                        case 49:
                        case 45:
                        case 43:
                        case 44:
                        case 15:
                        case 1:
                            return true;
                        default:
                            return false;
                    }
                }
                function parsePrimaryExpression() {
                    switch (token) {
                        case 7:
                        case 8:
                        case 10:
                            return parseLiteralNode();
                        case 92:
                        case 90:
                        case 88:
                        case 94:
                        case 79:
                            return parseTokenNode();
                        case 16:
                            return parseParenthesizedExpression();
                        case 18:
                            return parseArrayLiteralExpression();
                        case 14:
                            return parseObjectLiteralExpression();
                        case 82:
                            return parseFunctionExpression();
                        case 87:
                            return parseNewExpression();
                        case 36:
                        case 56:
                            if (reScanSlashToken() === 9) {
                                return parseLiteralNode();
                            }
                            break;
                        case 11:
                            return parseTemplateExpression();
                    }
                    return parseIdentifier(ts.Diagnostics.Expression_expected);
                }
                function parseParenthesizedExpression() {
                    var node = createNode(159);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    return finishNode(node);
                }
                function parseSpreadElement() {
                    var node = createNode(171);
                    parseExpected(21);
                    node.expression = parseAssignmentExpressionOrHigher();
                    return finishNode(node);
                }
                function parseArgumentOrArrayLiteralElement() {
                    return token === 21 ? parseSpreadElement() : token === 23 ? createNode(172) : parseAssignmentExpressionOrHigher();
                }
                function parseArgumentExpression() {
                    return allowInAnd(parseArgumentOrArrayLiteralElement);
                }
                function parseArrayLiteralExpression() {
                    var node = createNode(151);
                    parseExpected(18);
                    if (scanner.hasPrecedingLineBreak())
                        node.flags |= 512;
                    node.elements = parseDelimitedList(14, parseArgumentOrArrayLiteralElement);
                    parseExpected(19);
                    return finishNode(node);
                }
                function tryParseAccessorDeclaration(fullStart, modifiers) {
                    if (parseContextualModifier(115)) {
                        return parseAccessorDeclaration(134, fullStart, modifiers);
                    }
                    else if (parseContextualModifier(119)) {
                        return parseAccessorDeclaration(135, fullStart, modifiers);
                    }
                    return undefined;
                }
                function parseObjectLiteralElement() {
                    var fullStart = scanner.getStartPos();
                    var modifiers = parseModifiers();
                    var accessor = tryParseAccessorDeclaration(fullStart, modifiers);
                    if (accessor) {
                        return accessor;
                    }
                    var asteriskToken = parseOptionalToken(35);
                    var tokenIsIdentifier = isIdentifier();
                    var nameToken = token;
                    var propertyName = parsePropertyName();
                    var questionToken = parseOptionalToken(50);
                    if (asteriskToken || token === 16 || token === 24) {
                        return parseMethodDeclaration(fullStart, modifiers, asteriskToken, propertyName, questionToken);
                    }
                    if ((token === 23 || token === 15) && tokenIsIdentifier) {
                        var shorthandDeclaration = createNode(219, fullStart);
                        shorthandDeclaration.name = propertyName;
                        shorthandDeclaration.questionToken = questionToken;
                        return finishNode(shorthandDeclaration);
                    }
                    else {
                        var propertyAssignment = createNode(218, fullStart);
                        propertyAssignment.name = propertyName;
                        propertyAssignment.questionToken = questionToken;
                        parseExpected(51);
                        propertyAssignment.initializer = allowInAnd(parseAssignmentExpressionOrHigher);
                        return finishNode(propertyAssignment);
                    }
                }
                function parseObjectLiteralExpression() {
                    var node = createNode(152);
                    parseExpected(14);
                    if (scanner.hasPrecedingLineBreak()) {
                        node.flags |= 512;
                    }
                    node.properties = parseDelimitedList(13, parseObjectLiteralElement, true);
                    parseExpected(15);
                    return finishNode(node);
                }
                function parseFunctionExpression() {
                    var node = createNode(160);
                    parseExpected(82);
                    node.asteriskToken = parseOptionalToken(35);
                    node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
                    fillSignature(51, !!node.asteriskToken, false, node);
                    node.body = parseFunctionBlock(!!node.asteriskToken, false);
                    return finishNode(node);
                }
                function parseOptionalIdentifier() {
                    return isIdentifier() ? parseIdentifier() : undefined;
                }
                function parseNewExpression() {
                    var node = createNode(156);
                    parseExpected(87);
                    node.expression = parseMemberExpressionOrHigher();
                    node.typeArguments = tryParse(parseTypeArgumentsInExpression);
                    if (node.typeArguments || token === 16) {
                        node.arguments = parseArgumentList();
                    }
                    return finishNode(node);
                }
                function parseBlock(ignoreMissingOpenBrace, checkForStrictMode, diagnosticMessage) {
                    var node = createNode(174);
                    if (parseExpected(14, diagnosticMessage) || ignoreMissingOpenBrace) {
                        node.statements = parseList(2, checkForStrictMode, parseStatement);
                        parseExpected(15);
                    }
                    else {
                        node.statements = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseFunctionBlock(allowYield, ignoreMissingOpenBrace, diagnosticMessage) {
                    var savedYieldContext = inYieldContext();
                    setYieldContext(allowYield);
                    var block = parseBlock(ignoreMissingOpenBrace, true, diagnosticMessage);
                    setYieldContext(savedYieldContext);
                    return block;
                }
                function parseEmptyStatement() {
                    var node = createNode(176);
                    parseExpected(22);
                    return finishNode(node);
                }
                function parseIfStatement() {
                    var node = createNode(178);
                    parseExpected(83);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    node.thenStatement = parseStatement();
                    node.elseStatement = parseOptional(75) ? parseStatement() : undefined;
                    return finishNode(node);
                }
                function parseDoStatement() {
                    var node = createNode(179);
                    parseExpected(74);
                    node.statement = parseStatement();
                    parseExpected(99);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    parseOptional(22);
                    return finishNode(node);
                }
                function parseWhileStatement() {
                    var node = createNode(180);
                    parseExpected(99);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    node.statement = parseStatement();
                    return finishNode(node);
                }
                function parseForOrForInOrForOfStatement() {
                    var pos = getNodePos();
                    parseExpected(81);
                    parseExpected(16);
                    var initializer = undefined;
                    if (token !== 22) {
                        if (token === 97 || token === 104 || token === 69) {
                            initializer = parseVariableDeclarationList(true);
                        }
                        else {
                            initializer = disallowInAnd(parseExpression);
                        }
                    }
                    var forOrForInOrForOfStatement;
                    if (parseOptional(85)) {
                        var forInStatement = createNode(182, pos);
                        forInStatement.initializer = initializer;
                        forInStatement.expression = allowInAnd(parseExpression);
                        parseExpected(17);
                        forOrForInOrForOfStatement = forInStatement;
                    }
                    else if (parseOptional(124)) {
                        var forOfStatement = createNode(183, pos);
                        forOfStatement.initializer = initializer;
                        forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
                        parseExpected(17);
                        forOrForInOrForOfStatement = forOfStatement;
                    }
                    else {
                        var forStatement = createNode(181, pos);
                        forStatement.initializer = initializer;
                        parseExpected(22);
                        if (token !== 22 && token !== 17) {
                            forStatement.condition = allowInAnd(parseExpression);
                        }
                        parseExpected(22);
                        if (token !== 17) {
                            forStatement.iterator = allowInAnd(parseExpression);
                        }
                        parseExpected(17);
                        forOrForInOrForOfStatement = forStatement;
                    }
                    forOrForInOrForOfStatement.statement = parseStatement();
                    return finishNode(forOrForInOrForOfStatement);
                }
                function parseBreakOrContinueStatement(kind) {
                    var node = createNode(kind);
                    parseExpected(kind === 185 ? 65 : 70);
                    if (!canParseSemicolon()) {
                        node.label = parseIdentifier();
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseReturnStatement() {
                    var node = createNode(186);
                    parseExpected(89);
                    if (!canParseSemicolon()) {
                        node.expression = allowInAnd(parseExpression);
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseWithStatement() {
                    var node = createNode(187);
                    parseExpected(100);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    node.statement = parseStatement();
                    return finishNode(node);
                }
                function parseCaseClause() {
                    var node = createNode(214);
                    parseExpected(66);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(51);
                    node.statements = parseList(4, false, parseStatement);
                    return finishNode(node);
                }
                function parseDefaultClause() {
                    var node = createNode(215);
                    parseExpected(72);
                    parseExpected(51);
                    node.statements = parseList(4, false, parseStatement);
                    return finishNode(node);
                }
                function parseCaseOrDefaultClause() {
                    return token === 66 ? parseCaseClause() : parseDefaultClause();
                }
                function parseSwitchStatement() {
                    var node = createNode(188);
                    parseExpected(91);
                    parseExpected(16);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17);
                    var caseBlock = createNode(202, scanner.getStartPos());
                    parseExpected(14);
                    caseBlock.clauses = parseList(3, false, parseCaseOrDefaultClause);
                    parseExpected(15);
                    node.caseBlock = finishNode(caseBlock);
                    return finishNode(node);
                }
                function parseThrowStatement() {
                    var node = createNode(190);
                    parseExpected(93);
                    node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseTryStatement() {
                    var node = createNode(191);
                    parseExpected(95);
                    node.tryBlock = parseBlock(false, false);
                    node.catchClause = token === 67 ? parseCatchClause() : undefined;
                    if (!node.catchClause || token === 80) {
                        parseExpected(80);
                        node.finallyBlock = parseBlock(false, false);
                    }
                    return finishNode(node);
                }
                function parseCatchClause() {
                    var result = createNode(217);
                    parseExpected(67);
                    if (parseExpected(16)) {
                        result.variableDeclaration = parseVariableDeclaration();
                    }
                    parseExpected(17);
                    result.block = parseBlock(false, false);
                    return finishNode(result);
                }
                function parseDebuggerStatement() {
                    var node = createNode(192);
                    parseExpected(71);
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseExpressionOrLabeledStatement() {
                    var fullStart = scanner.getStartPos();
                    var expression = allowInAnd(parseExpression);
                    if (expression.kind === 64 && parseOptional(51)) {
                        var labeledStatement = createNode(189, fullStart);
                        labeledStatement.label = expression;
                        labeledStatement.statement = parseStatement();
                        return finishNode(labeledStatement);
                    }
                    else {
                        var expressionStatement = createNode(177, fullStart);
                        expressionStatement.expression = expression;
                        parseSemicolon();
                        return finishNode(expressionStatement);
                    }
                }
                function isStartOfStatement(inErrorRecovery) {
                    if (ts.isModifier(token)) {
                        var result = lookAhead(parseVariableStatementOrFunctionDeclarationWithModifiers);
                        if (result) {
                            return true;
                        }
                    }
                    switch (token) {
                        case 22:
                            return !inErrorRecovery;
                        case 14:
                        case 97:
                        case 104:
                        case 82:
                        case 83:
                        case 74:
                        case 99:
                        case 81:
                        case 70:
                        case 65:
                        case 89:
                        case 100:
                        case 91:
                        case 93:
                        case 95:
                        case 71:
                        case 67:
                        case 80:
                            return true;
                        case 69:
                            var isConstEnum = lookAhead(nextTokenIsEnumKeyword);
                            return !isConstEnum;
                        case 103:
                        case 68:
                        case 116:
                        case 76:
                        case 122:
                            if (isDeclarationStart()) {
                                return false;
                            }
                        case 108:
                        case 106:
                        case 107:
                        case 109:
                            if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) {
                                return false;
                            }
                        default:
                            return isStartOfExpression();
                    }
                }
                function nextTokenIsEnumKeyword() {
                    nextToken();
                    return token === 76;
                }
                function nextTokenIsIdentifierOrKeywordOnSameLine() {
                    nextToken();
                    return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();
                }
                function parseStatement() {
                    switch (token) {
                        case 14:
                            return parseBlock(false, false);
                        case 97:
                        case 69:
                            return parseVariableStatement(scanner.getStartPos(), undefined);
                        case 82:
                            return parseFunctionDeclaration(scanner.getStartPos(), undefined);
                        case 22:
                            return parseEmptyStatement();
                        case 83:
                            return parseIfStatement();
                        case 74:
                            return parseDoStatement();
                        case 99:
                            return parseWhileStatement();
                        case 81:
                            return parseForOrForInOrForOfStatement();
                        case 70:
                            return parseBreakOrContinueStatement(184);
                        case 65:
                            return parseBreakOrContinueStatement(185);
                        case 89:
                            return parseReturnStatement();
                        case 100:
                            return parseWithStatement();
                        case 91:
                            return parseSwitchStatement();
                        case 93:
                            return parseThrowStatement();
                        case 95:
                        case 67:
                        case 80:
                            return parseTryStatement();
                        case 71:
                            return parseDebuggerStatement();
                        case 104:
                            if (isLetDeclaration()) {
                                return parseVariableStatement(scanner.getStartPos(), undefined);
                            }
                        default:
                            if (ts.isModifier(token)) {
                                var result = tryParse(parseVariableStatementOrFunctionDeclarationWithModifiers);
                                if (result) {
                                    return result;
                                }
                            }
                            return parseExpressionOrLabeledStatement();
                    }
                }
                function parseVariableStatementOrFunctionDeclarationWithModifiers() {
                    var start = scanner.getStartPos();
                    var modifiers = parseModifiers();
                    switch (token) {
                        case 69:
                            var nextTokenIsEnum = lookAhead(nextTokenIsEnumKeyword);
                            if (nextTokenIsEnum) {
                                return undefined;
                            }
                            return parseVariableStatement(start, modifiers);
                        case 104:
                            if (!isLetDeclaration()) {
                                return undefined;
                            }
                            return parseVariableStatement(start, modifiers);
                        case 97:
                            return parseVariableStatement(start, modifiers);
                        case 82:
                            return parseFunctionDeclaration(start, modifiers);
                    }
                    return undefined;
                }
                function parseFunctionBlockOrSemicolon(isGenerator, diagnosticMessage) {
                    if (token !== 14 && canParseSemicolon()) {
                        parseSemicolon();
                        return;
                    }
                    return parseFunctionBlock(isGenerator, false, diagnosticMessage);
                }
                function parseArrayBindingElement() {
                    if (token === 23) {
                        return createNode(172);
                    }
                    var node = createNode(150);
                    node.dotDotDotToken = parseOptionalToken(21);
                    node.name = parseIdentifierOrPattern();
                    node.initializer = parseInitializer(false);
                    return finishNode(node);
                }
                function parseObjectBindingElement() {
                    var node = createNode(150);
                    var id = parsePropertyName();
                    if (id.kind === 64 && token !== 51) {
                        node.name = id;
                    }
                    else {
                        parseExpected(51);
                        node.propertyName = id;
                        node.name = parseIdentifierOrPattern();
                    }
                    node.initializer = parseInitializer(false);
                    return finishNode(node);
                }
                function parseObjectBindingPattern() {
                    var node = createNode(148);
                    parseExpected(14);
                    node.elements = parseDelimitedList(10, parseObjectBindingElement);
                    parseExpected(15);
                    return finishNode(node);
                }
                function parseArrayBindingPattern() {
                    var node = createNode(149);
                    parseExpected(18);
                    node.elements = parseDelimitedList(11, parseArrayBindingElement);
                    parseExpected(19);
                    return finishNode(node);
                }
                function isIdentifierOrPattern() {
                    return token === 14 || token === 18 || isIdentifier();
                }
                function parseIdentifierOrPattern() {
                    if (token === 18) {
                        return parseArrayBindingPattern();
                    }
                    if (token === 14) {
                        return parseObjectBindingPattern();
                    }
                    return parseIdentifier();
                }
                function parseVariableDeclaration() {
                    var node = createNode(193);
                    node.name = parseIdentifierOrPattern();
                    node.type = parseTypeAnnotation();
                    if (!isInOrOfKeyword(token)) {
                        node.initializer = parseInitializer(false);
                    }
                    return finishNode(node);
                }
                function parseVariableDeclarationList(inForStatementInitializer) {
                    var node = createNode(194);
                    switch (token) {
                        case 97:
                            break;
                        case 104:
                            node.flags |= 4096;
                            break;
                        case 69:
                            node.flags |= 8192;
                            break;
                        default:
                            ts.Debug.fail();
                    }
                    nextToken();
                    if (token === 124 && lookAhead(canFollowContextualOfKeyword)) {
                        node.declarations = createMissingList();
                    }
                    else {
                        var savedDisallowIn = inDisallowInContext();
                        setDisallowInContext(inForStatementInitializer);
                        node.declarations = parseDelimitedList(9, parseVariableDeclaration);
                        setDisallowInContext(savedDisallowIn);
                    }
                    return finishNode(node);
                }
                function canFollowContextualOfKeyword() {
                    return nextTokenIsIdentifier() && nextToken() === 17;
                }
                function parseVariableStatement(fullStart, modifiers) {
                    var node = createNode(175, fullStart);
                    setModifiers(node, modifiers);
                    node.declarationList = parseVariableDeclarationList(false);
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseFunctionDeclaration(fullStart, modifiers) {
                    var node = createNode(195, fullStart);
                    setModifiers(node, modifiers);
                    parseExpected(82);
                    node.asteriskToken = parseOptionalToken(35);
                    node.name = node.flags & 256 ? parseOptionalIdentifier() : parseIdentifier();
                    fillSignature(51, !!node.asteriskToken, false, node);
                    node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, ts.Diagnostics.or_expected);
                    return finishNode(node);
                }
                function parseConstructorDeclaration(pos, modifiers) {
                    var node = createNode(133, pos);
                    setModifiers(node, modifiers);
                    parseExpected(113);
                    fillSignature(51, false, false, node);
                    node.body = parseFunctionBlockOrSemicolon(false, ts.Diagnostics.or_expected);
                    return finishNode(node);
                }
                function parseMethodDeclaration(fullStart, modifiers, asteriskToken, name, questionToken, diagnosticMessage) {
                    var method = createNode(132, fullStart);
                    setModifiers(method, modifiers);
                    method.asteriskToken = asteriskToken;
                    method.name = name;
                    method.questionToken = questionToken;
                    fillSignature(51, !!asteriskToken, false, method);
                    method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
                    return finishNode(method);
                }
                function parsePropertyOrMethodDeclaration(fullStart, modifiers) {
                    var asteriskToken = parseOptionalToken(35);
                    var name = parsePropertyName();
                    var questionToken = parseOptionalToken(50);
                    if (asteriskToken || token === 16 || token === 24) {
                        return parseMethodDeclaration(fullStart, modifiers, asteriskToken, name, questionToken, ts.Diagnostics.or_expected);
                    }
                    else {
                        var property = createNode(130, fullStart);
                        setModifiers(property, modifiers);
                        property.name = name;
                        property.questionToken = questionToken;
                        property.type = parseTypeAnnotation();
                        property.initializer = allowInAnd(parseNonParameterInitializer);
                        parseSemicolon();
                        return finishNode(property);
                    }
                }
                function parseNonParameterInitializer() {
                    return parseInitializer(false);
                }
                function parseAccessorDeclaration(kind, fullStart, modifiers) {
                    var node = createNode(kind, fullStart);
                    setModifiers(node, modifiers);
                    node.name = parsePropertyName();
                    fillSignature(51, false, false, node);
                    node.body = parseFunctionBlockOrSemicolon(false);
                    return finishNode(node);
                }
                function isClassMemberStart() {
                    var idToken;
                    while (ts.isModifier(token)) {
                        idToken = token;
                        nextToken();
                    }
                    if (token === 35) {
                        return true;
                    }
                    if (isLiteralPropertyName()) {
                        idToken = token;
                        nextToken();
                    }
                    if (token === 18) {
                        return true;
                    }
                    if (idToken !== undefined) {
                        if (!ts.isKeyword(idToken) || idToken === 119 || idToken === 115) {
                            return true;
                        }
                        switch (token) {
                            case 16:
                            case 24:
                            case 51:
                            case 52:
                            case 50:
                                return true;
                            default:
                                return canParseSemicolon();
                        }
                    }
                    return false;
                }
                function parseModifiers() {
                    var flags = 0;
                    var modifiers;
                    while (true) {
                        var modifierStart = scanner.getStartPos();
                        var modifierKind = token;
                        if (!parseAnyContextualModifier()) {
                            break;
                        }
                        if (!modifiers) {
                            modifiers = [];
                            modifiers.pos = modifierStart;
                        }
                        flags |= modifierToFlag(modifierKind);
                        modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
                    }
                    if (modifiers) {
                        modifiers.flags = flags;
                        modifiers.end = scanner.getStartPos();
                    }
                    return modifiers;
                }
                function parseClassElement() {
                    var fullStart = getNodePos();
                    var modifiers = parseModifiers();
                    var accessor = tryParseAccessorDeclaration(fullStart, modifiers);
                    if (accessor) {
                        return accessor;
                    }
                    if (token === 113) {
                        return parseConstructorDeclaration(fullStart, modifiers);
                    }
                    if (isIndexSignature()) {
                        return parseIndexSignatureDeclaration(modifiers);
                    }
                    if (isIdentifierOrKeyword() || token === 8 || token === 7 || token === 35 || token === 18) {
                        return parsePropertyOrMethodDeclaration(fullStart, modifiers);
                    }
                    ts.Debug.fail("Should not have attempted to parse class member declaration.");
                }
                function parseClassDeclaration(fullStart, modifiers) {
                    var node = createNode(196, fullStart);
                    setModifiers(node, modifiers);
                    parseExpected(68);
                    node.name = node.flags & 256 ? parseOptionalIdentifier() : parseIdentifier();
                    node.typeParameters = parseTypeParameters();
                    node.heritageClauses = parseHeritageClauses(true);
                    if (parseExpected(14)) {
                        node.members = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseClassMembers) : parseClassMembers();
                        parseExpected(15);
                    }
                    else {
                        node.members = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseHeritageClauses(isClassHeritageClause) {
                    if (isHeritageClause()) {
                        return isClassHeritageClause && inGeneratorParameterContext() ? doOutsideOfYieldContext(parseHeritageClausesWorker) : parseHeritageClausesWorker();
                    }
                    return undefined;
                }
                function parseHeritageClausesWorker() {
                    return parseList(19, false, parseHeritageClause);
                }
                function parseHeritageClause() {
                    if (token === 78 || token === 102) {
                        var node = createNode(216);
                        node.token = token;
                        nextToken();
                        node.types = parseDelimitedList(8, parseTypeReference);
                        return finishNode(node);
                    }
                    return undefined;
                }
                function isHeritageClause() {
                    return token === 78 || token === 102;
                }
                function parseClassMembers() {
                    return parseList(6, false, parseClassElement);
                }
                function parseInterfaceDeclaration(fullStart, modifiers) {
                    var node = createNode(197, fullStart);
                    setModifiers(node, modifiers);
                    parseExpected(103);
                    node.name = parseIdentifier();
                    node.typeParameters = parseTypeParameters();
                    node.heritageClauses = parseHeritageClauses(false);
                    node.members = parseObjectTypeMembers();
                    return finishNode(node);
                }
                function parseTypeAliasDeclaration(fullStart, modifiers) {
                    var node = createNode(198, fullStart);
                    setModifiers(node, modifiers);
                    parseExpected(122);
                    node.name = parseIdentifier();
                    parseExpected(52);
                    node.type = parseType();
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseEnumMember() {
                    var node = createNode(220, scanner.getStartPos());
                    node.name = parsePropertyName();
                    node.initializer = allowInAnd(parseNonParameterInitializer);
                    return finishNode(node);
                }
                function parseEnumDeclaration(fullStart, modifiers) {
                    var node = createNode(199, fullStart);
                    setModifiers(node, modifiers);
                    parseExpected(76);
                    node.name = parseIdentifier();
                    if (parseExpected(14)) {
                        node.members = parseDelimitedList(7, parseEnumMember);
                        parseExpected(15);
                    }
                    else {
                        node.members = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseModuleBlock() {
                    var node = createNode(201, scanner.getStartPos());
                    if (parseExpected(14)) {
                        node.statements = parseList(1, false, parseModuleElement);
                        parseExpected(15);
                    }
                    else {
                        node.statements = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseInternalModuleTail(fullStart, modifiers, flags) {
                    var node = createNode(200, fullStart);
                    setModifiers(node, modifiers);
                    node.flags |= flags;
                    node.name = parseIdentifier();
                    node.body = parseOptional(20) ? parseInternalModuleTail(getNodePos(), undefined, 1) : parseModuleBlock();
                    return finishNode(node);
                }
                function parseAmbientExternalModuleDeclaration(fullStart, modifiers) {
                    var node = createNode(200, fullStart);
                    setModifiers(node, modifiers);
                    node.name = parseLiteralNode(true);
                    node.body = parseModuleBlock();
                    return finishNode(node);
                }
                function parseModuleDeclaration(fullStart, modifiers) {
                    parseExpected(116);
                    return token === 8 ? parseAmbientExternalModuleDeclaration(fullStart, modifiers) : parseInternalModuleTail(fullStart, modifiers, modifiers ? modifiers.flags : 0);
                }
                function isExternalModuleReference() {
                    return token === 117 && lookAhead(nextTokenIsOpenParen);
                }
                function nextTokenIsOpenParen() {
                    return nextToken() === 16;
                }
                function nextTokenIsCommaOrFromKeyword() {
                    nextToken();
                    return token === 23 || token === 123;
                }
                function parseImportDeclarationOrImportEqualsDeclaration(fullStart, modifiers) {
                    parseExpected(84);
                    var afterImportPos = scanner.getStartPos();
                    var identifier;
                    if (isIdentifier()) {
                        identifier = parseIdentifier();
                        if (token !== 23 && token !== 123) {
                            var importEqualsDeclaration = createNode(203, fullStart);
                            setModifiers(importEqualsDeclaration, modifiers);
                            importEqualsDeclaration.name = identifier;
                            parseExpected(52);
                            importEqualsDeclaration.moduleReference = parseModuleReference();
                            parseSemicolon();
                            return finishNode(importEqualsDeclaration);
                        }
                    }
                    var importDeclaration = createNode(204, fullStart);
                    setModifiers(importDeclaration, modifiers);
                    if (identifier || token === 35 || token === 14) {
                        importDeclaration.importClause = parseImportClause(identifier, afterImportPos);
                        parseExpected(123);
                    }
                    importDeclaration.moduleSpecifier = parseModuleSpecifier();
                    parseSemicolon();
                    return finishNode(importDeclaration);
                }
                function parseImportClause(identifier, fullStart) {
                    var importClause = createNode(205, fullStart);
                    if (identifier) {
                        importClause.name = identifier;
                    }
                    if (!importClause.name || parseOptional(23)) {
                        importClause.namedBindings = token === 35 ? parseNamespaceImport() : parseNamedImportsOrExports(207);
                    }
                    return finishNode(importClause);
                }
                function parseModuleReference() {
                    return isExternalModuleReference() ? parseExternalModuleReference() : parseEntityName(false);
                }
                function parseExternalModuleReference() {
                    var node = createNode(213);
                    parseExpected(117);
                    parseExpected(16);
                    node.expression = parseModuleSpecifier();
                    parseExpected(17);
                    return finishNode(node);
                }
                function parseModuleSpecifier() {
                    var result = parseExpression();
                    if (result.kind === 8) {
                        internIdentifier(result.text);
                    }
                    return result;
                }
                function parseNamespaceImport() {
                    var namespaceImport = createNode(206);
                    parseExpected(35);
                    parseExpected(101);
                    namespaceImport.name = parseIdentifier();
                    return finishNode(namespaceImport);
                }
                function parseNamedImportsOrExports(kind) {
                    var node = createNode(kind);
                    node.elements = parseBracketedList(20, kind === 207 ? parseImportSpecifier : parseExportSpecifier, 14, 15);
                    return finishNode(node);
                }
                function parseExportSpecifier() {
                    return parseImportOrExportSpecifier(212);
                }
                function parseImportSpecifier() {
                    return parseImportOrExportSpecifier(208);
                }
                function parseImportOrExportSpecifier(kind) {
                    var node = createNode(kind);
                    var isFirstIdentifierNameNotAnIdentifier = ts.isKeyword(token) && !isIdentifier();
                    var start = scanner.getTokenPos();
                    var identifierName = parseIdentifierName();
                    if (token === 101) {
                        node.propertyName = identifierName;
                        parseExpected(101);
                        if (isIdentifier()) {
                            node.name = parseIdentifierName();
                        }
                        else {
                            parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected);
                        }
                    }
                    else {
                        node.name = identifierName;
                        if (isFirstIdentifierNameNotAnIdentifier) {
                            parseErrorAtPosition(start, identifierName.end - start, ts.Diagnostics.Identifier_expected);
                        }
                    }
                    return finishNode(node);
                }
                function parseExportDeclaration(fullStart, modifiers) {
                    var node = createNode(210, fullStart);
                    setModifiers(node, modifiers);
                    if (parseOptional(35)) {
                        parseExpected(123);
                        node.moduleSpecifier = parseModuleSpecifier();
                    }
                    else {
                        node.exportClause = parseNamedImportsOrExports(211);
                        if (parseOptional(123)) {
                            node.moduleSpecifier = parseModuleSpecifier();
                        }
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseExportAssignment(fullStart, modifiers) {
                    var node = createNode(209, fullStart);
                    setModifiers(node, modifiers);
                    if (parseOptional(52)) {
                        node.isExportEquals = true;
                    }
                    else {
                        parseExpected(72);
                    }
                    node.expression = parseAssignmentExpressionOrHigher();
                    parseSemicolon();
                    return finishNode(node);
                }
                function isLetDeclaration() {
                    return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOnSameLine);
                }
                function isDeclarationStart() {
                    switch (token) {
                        case 97:
                        case 69:
                        case 82:
                            return true;
                        case 104:
                            return isLetDeclaration();
                        case 68:
                        case 103:
                        case 76:
                        case 122:
                            return lookAhead(nextTokenIsIdentifierOrKeyword);
                        case 84:
                            return lookAhead(nextTokenCanFollowImportKeyword);
                        case 116:
                            return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral);
                        case 77:
                            return lookAhead(nextTokenCanFollowExportKeyword);
                        case 114:
                        case 108:
                        case 106:
                        case 107:
                        case 109:
                            return lookAhead(nextTokenIsDeclarationStart);
                    }
                }
                function isIdentifierOrKeyword() {
                    return token >= 64;
                }
                function nextTokenIsIdentifierOrKeyword() {
                    nextToken();
                    return isIdentifierOrKeyword();
                }
                function nextTokenIsIdentifierOrKeywordOrStringLiteral() {
                    nextToken();
                    return isIdentifierOrKeyword() || token === 8;
                }
                function nextTokenCanFollowImportKeyword() {
                    nextToken();
                    return isIdentifierOrKeyword() || token === 8 || token === 35 || token === 14;
                }
                function nextTokenCanFollowExportKeyword() {
                    nextToken();
                    return token === 52 || token === 35 || token === 14 || token === 72 || isDeclarationStart();
                }
                function nextTokenIsDeclarationStart() {
                    nextToken();
                    return isDeclarationStart();
                }
                function nextTokenIsAsKeyword() {
                    return nextToken() === 101;
                }
                function parseDeclaration() {
                    var fullStart = getNodePos();
                    var modifiers = parseModifiers();
                    if (token === 77) {
                        nextToken();
                        if (token === 72 || token === 52) {
                            return parseExportAssignment(fullStart, modifiers);
                        }
                        if (token === 35 || token === 14) {
                            return parseExportDeclaration(fullStart, modifiers);
                        }
                    }
                    switch (token) {
                        case 97:
                        case 104:
                        case 69:
                            return parseVariableStatement(fullStart, modifiers);
                        case 82:
                            return parseFunctionDeclaration(fullStart, modifiers);
                        case 68:
                            return parseClassDeclaration(fullStart, modifiers);
                        case 103:
                            return parseInterfaceDeclaration(fullStart, modifiers);
                        case 122:
                            return parseTypeAliasDeclaration(fullStart, modifiers);
                        case 76:
                            return parseEnumDeclaration(fullStart, modifiers);
                        case 116:
                            return parseModuleDeclaration(fullStart, modifiers);
                        case 84:
                            return parseImportDeclarationOrImportEqualsDeclaration(fullStart, modifiers);
                        default:
                            ts.Debug.fail("Mismatch between isDeclarationStart and parseDeclaration");
                    }
                }
                function isSourceElement(inErrorRecovery) {
                    return isDeclarationStart() || isStartOfStatement(inErrorRecovery);
                }
                function parseSourceElement() {
                    return parseSourceElementOrModuleElement();
                }
                function parseModuleElement() {
                    return parseSourceElementOrModuleElement();
                }
                function parseSourceElementOrModuleElement() {
                    return isDeclarationStart() ? parseDeclaration() : parseStatement();
                }
                function processReferenceComments(sourceFile) {
                    var triviaScanner = ts.createScanner(sourceFile.languageVersion, false, sourceText);
                    var referencedFiles = [];
                    var amdDependencies = [];
                    var amdModuleName;
                    while (true) {
                        var kind = triviaScanner.scan();
                        if (kind === 5 || kind === 4 || kind === 3) {
                            continue;
                        }
                        if (kind !== 2) {
                            break;
                        }
                        var range = {
                            pos: triviaScanner.getTokenPos(),
                            end: triviaScanner.getTextPos()
                        };
                        var comment = sourceText.substring(range.pos, range.end);
                        var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, range);
                        if (referencePathMatchResult) {
                            var fileReference = referencePathMatchResult.fileReference;
                            sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
                            var diagnosticMessage = referencePathMatchResult.diagnosticMessage;
                            if (fileReference) {
                                referencedFiles.push(fileReference);
                            }
                            if (diagnosticMessage) {
                                sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
                            }
                        }
                        else {
                            var amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
                            var amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
                            if (amdModuleNameMatchResult) {
                                if (amdModuleName) {
                                    sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
                                }
                                amdModuleName = amdModuleNameMatchResult[2];
                            }
                            var amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
                            var pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
                            var nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
                            var amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
                            if (amdDependencyMatchResult) {
                                var pathMatchResult = pathRegex.exec(comment);
                                var nameMatchResult = nameRegex.exec(comment);
                                if (pathMatchResult) {
                                    var amdDependency = {
                                        path: pathMatchResult[2],
                                        name: nameMatchResult ? nameMatchResult[2] : undefined
                                    };
                                    amdDependencies.push(amdDependency);
                                }
                            }
                        }
                    }
                    sourceFile.referencedFiles = referencedFiles;
                    sourceFile.amdDependencies = amdDependencies;
                    sourceFile.amdModuleName = amdModuleName;
                }
                function setExternalModuleIndicator(sourceFile) {
                    sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, function (node) {
                        return node.flags & 1 || node.kind === 203 && node.moduleReference.kind === 213 || node.kind === 204 || node.kind === 209 || node.kind === 210 ? node : undefined;
                    });
                }
            }
            function isLeftHandSideExpression(expr) {
                if (expr) {
                    switch (expr.kind) {
                        case 153:
                        case 154:
                        case 156:
                        case 155:
                        case 157:
                        case 151:
                        case 159:
                        case 152:
                        case 160:
                        case 64:
                        case 9:
                        case 7:
                        case 8:
                        case 10:
                        case 169:
                        case 79:
                        case 88:
                        case 92:
                        case 94:
                        case 90:
                            return true;
                    }
                }
                return false;
            }
            ts.isLeftHandSideExpression = isLeftHandSideExpression;
            function isAssignmentOperator(token) {
                return token >= 52 && token <= 63;
            }
            ts.isAssignmentOperator = isAssignmentOperator;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            ts.bindTime = 0;
            (function (ModuleInstanceState) {
                ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated";
                ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated";
                ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly";
            })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {}));
            var ModuleInstanceState = ts.ModuleInstanceState;
            function getModuleInstanceState(node) {
                if (node.kind === 197 || node.kind === 198) {
                    return 0;
                }
                else if (ts.isConstEnumDeclaration(node)) {
                    return 2;
                }
                else if ((node.kind === 204 || node.kind === 203) && !(node.flags & 1)) {
                    return 0;
                }
                else if (node.kind === 201) {
                    var state = 0;
                    ts.forEachChild(node, function (n) {
                        switch (getModuleInstanceState(n)) {
                            case 0:
                                return false;
                            case 2:
                                state = 2;
                                return false;
                            case 1:
                                state = 1;
                                return true;
                        }
                    });
                    return state;
                }
                else if (node.kind === 200) {
                    return getModuleInstanceState(node.body);
                }
                else {
                    return 1;
                }
            }
            ts.getModuleInstanceState = getModuleInstanceState;
            function bindSourceFile(file) {
                var start = new Date().getTime();
                bindSourceFileWorker(file);
                ts.bindTime += new Date().getTime() - start;
            }
            ts.bindSourceFile = bindSourceFile;
            function bindSourceFileWorker(file) {
                var parent;
                var container;
                var blockScopeContainer;
                var lastContainer;
                var symbolCount = 0;
                var Symbol = ts.objectAllocator.getSymbolConstructor();
                if (!file.locals) {
                    file.locals = {};
                    container = file;
                    setBlockScopeContainer(file, false);
                    bind(file);
                    file.symbolCount = symbolCount;
                }
                function createSymbol(flags, name) {
                    symbolCount++;
                    return new Symbol(flags, name);
                }
                function setBlockScopeContainer(node, cleanLocals) {
                    blockScopeContainer = node;
                    if (cleanLocals) {
                        blockScopeContainer.locals = undefined;
                    }
                }
                function addDeclarationToSymbol(symbol, node, symbolKind) {
                    symbol.flags |= symbolKind;
                    if (!symbol.declarations)
                        symbol.declarations = [];
                    symbol.declarations.push(node);
                    if (symbolKind & 1952 && !symbol.exports)
                        symbol.exports = {};
                    if (symbolKind & 6240 && !symbol.members)
                        symbol.members = {};
                    node.symbol = symbol;
                    if (symbolKind & 107455 && !symbol.valueDeclaration)
                        symbol.valueDeclaration = node;
                }
                function getDeclarationName(node) {
                    if (node.name) {
                        if (node.kind === 200 && node.name.kind === 8) {
                            return '"' + node.name.text + '"';
                        }
                        if (node.name.kind === 126) {
                            var nameExpression = node.name.expression;
                            ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression));
                            return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text);
                        }
                        return node.name.text;
                    }
                    switch (node.kind) {
                        case 141:
                        case 133:
                            return "__constructor";
                        case 140:
                        case 136:
                            return "__call";
                        case 137:
                            return "__new";
                        case 138:
                            return "__index";
                        case 210:
                            return "__export";
                        case 209:
                            return "default";
                        case 195:
                        case 196:
                            return node.flags & 256 ? "default" : undefined;
                    }
                }
                function getDisplayName(node) {
                    return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node);
                }
                function declareSymbol(symbols, parent, node, includes, excludes) {
                    ts.Debug.assert(!ts.hasDynamicName(node));
                    var name = node.flags & 256 && parent ? "default" : getDeclarationName(node);
                    if (name !== undefined) {
                        var symbol = ts.hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
                        if (symbol.flags & excludes) {
                            if (node.name) {
                                node.name.parent = node;
                            }
                            var message = symbol.flags & 2 ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0;
                            ts.forEach(symbol.declarations, function (declaration) {
                                file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
                            });
                            file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
                            symbol = createSymbol(0, name);
                        }
                    }
                    else {
                        symbol = createSymbol(0, "__missing");
                    }
                    addDeclarationToSymbol(symbol, node, includes);
                    symbol.parent = parent;
                    if (node.kind === 196 && symbol.exports) {
                        var prototypeSymbol = createSymbol(4 | 134217728, "prototype");
                        if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) {
                            if (node.name) {
                                node.name.parent = node;
                            }
                            file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
                        }
                        symbol.exports[prototypeSymbol.name] = prototypeSymbol;
                        prototypeSymbol.parent = symbol;
                    }
                    return symbol;
                }
                function isAmbientContext(node) {
                    while (node) {
                        if (node.flags & 2)
                            return true;
                        node = node.parent;
                    }
                    return false;
                }
                function declareModuleMember(node, symbolKind, symbolExcludes) {
                    var hasExportModifier = ts.getCombinedNodeFlags(node) & 1;
                    if (symbolKind & 8388608) {
                        if (node.kind === 212 || (node.kind === 203 && hasExportModifier)) {
                            declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                        }
                        else {
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                        }
                    }
                    else {
                        if (hasExportModifier || isAmbientContext(container)) {
                            var exportKind = (symbolKind & 107455 ? 1048576 : 0) | (symbolKind & 793056 ? 2097152 : 0) | (symbolKind & 1536 ? 4194304 : 0);
                            var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
                            local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                            node.localSymbol = local;
                        }
                        else {
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                        }
                    }
                }
                function bindChildren(node, symbolKind, isBlockScopeContainer) {
                    if (symbolKind & 255504) {
                        node.locals = {};
                    }
                    var saveParent = parent;
                    var saveContainer = container;
                    var savedBlockScopeContainer = blockScopeContainer;
                    parent = node;
                    if (symbolKind & 262128) {
                        container = node;
                        if (lastContainer) {
                            lastContainer.nextContainer = container;
                        }
                        lastContainer = container;
                    }
                    if (isBlockScopeContainer) {
                        setBlockScopeContainer(node, (symbolKind & 255504) === 0 && node.kind !== 221);
                    }
                    ts.forEachChild(node, bind);
                    container = saveContainer;
                    parent = saveParent;
                    blockScopeContainer = savedBlockScopeContainer;
                }
                function bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
                    switch (container.kind) {
                        case 200:
                            declareModuleMember(node, symbolKind, symbolExcludes);
                            break;
                        case 221:
                            if (ts.isExternalModule(container)) {
                                declareModuleMember(node, symbolKind, symbolExcludes);
                                break;
                            }
                        case 140:
                        case 141:
                        case 136:
                        case 137:
                        case 138:
                        case 132:
                        case 131:
                        case 133:
                        case 134:
                        case 135:
                        case 195:
                        case 160:
                        case 161:
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                            break;
                        case 196:
                            if (node.flags & 128) {
                                declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                                break;
                            }
                        case 143:
                        case 152:
                        case 197:
                            declareSymbol(container.symbol.members, container.symbol, node, symbolKind, symbolExcludes);
                            break;
                        case 199:
                            declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                            break;
                    }
                    bindChildren(node, symbolKind, isBlockScopeContainer);
                }
                function bindModuleDeclaration(node) {
                    if (node.name.kind === 8) {
                        bindDeclaration(node, 512, 106639, true);
                    }
                    else {
                        var state = getModuleInstanceState(node);
                        if (state === 0) {
                            bindDeclaration(node, 1024, 0, true);
                        }
                        else {
                            bindDeclaration(node, 512, 106639, true);
                            if (state === 2) {
                                node.symbol.constEnumOnlyModule = true;
                            }
                            else if (node.symbol.constEnumOnlyModule) {
                                node.symbol.constEnumOnlyModule = false;
                            }
                        }
                    }
                }
                function bindFunctionOrConstructorType(node) {
                    var symbol = createSymbol(131072, getDeclarationName(node));
                    addDeclarationToSymbol(symbol, node, 131072);
                    bindChildren(node, 131072, false);
                    var typeLiteralSymbol = createSymbol(2048, "__type");
                    addDeclarationToSymbol(typeLiteralSymbol, node, 2048);
                    typeLiteralSymbol.members = {};
                    typeLiteralSymbol.members[node.kind === 140 ? "__call" : "__new"] = symbol;
                }
                function bindAnonymousDeclaration(node, symbolKind, name, isBlockScopeContainer) {
                    var symbol = createSymbol(symbolKind, name);
                    addDeclarationToSymbol(symbol, node, symbolKind);
                    bindChildren(node, symbolKind, isBlockScopeContainer);
                }
                function bindCatchVariableDeclaration(node) {
                    bindChildren(node, 0, true);
                }
                function bindBlockScopedVariableDeclaration(node) {
                    switch (blockScopeContainer.kind) {
                        case 200:
                            declareModuleMember(node, 2, 107455);
                            break;
                        case 221:
                            if (ts.isExternalModule(container)) {
                                declareModuleMember(node, 2, 107455);
                                break;
                            }
                        default:
                            if (!blockScopeContainer.locals) {
                                blockScopeContainer.locals = {};
                            }
                            declareSymbol(blockScopeContainer.locals, undefined, node, 2, 107455);
                    }
                    bindChildren(node, 2, false);
                }
                function getDestructuringParameterName(node) {
                    return "__" + ts.indexOf(node.parent.parameters, node);
                }
                function bind(node) {
                    node.parent = parent;
                    switch (node.kind) {
                        case 127:
                            bindDeclaration(node, 262144, 530912, false);
                            break;
                        case 128:
                            bindParameter(node);
                            break;
                        case 193:
                        case 150:
                            if (ts.isBindingPattern(node.name)) {
                                bindChildren(node, 0, false);
                            }
                            else if (ts.isBlockOrCatchScoped(node)) {
                                bindBlockScopedVariableDeclaration(node);
                            }
                            else {
                                bindDeclaration(node, 1, 107454, false);
                            }
                            break;
                        case 130:
                        case 129:
                            bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 536870912 : 0), 107455, false);
                            break;
                        case 218:
                        case 219:
                            bindPropertyOrMethodOrAccessor(node, 4, 107455, false);
                            break;
                        case 220:
                            bindPropertyOrMethodOrAccessor(node, 8, 107455, false);
                            break;
                        case 136:
                        case 137:
                        case 138:
                            bindDeclaration(node, 131072, 0, false);
                            break;
                        case 132:
                        case 131:
                            bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 536870912 : 0), ts.isObjectLiteralMethod(node) ? 107455 : 99263, true);
                            break;
                        case 195:
                            bindDeclaration(node, 16, 106927, true);
                            break;
                        case 133:
                            bindDeclaration(node, 16384, 0, true);
                            break;
                        case 134:
                            bindPropertyOrMethodOrAccessor(node, 32768, 41919, true);
                            break;
                        case 135:
                            bindPropertyOrMethodOrAccessor(node, 65536, 74687, true);
                            break;
                        case 140:
                        case 141:
                            bindFunctionOrConstructorType(node);
                            break;
                        case 143:
                            bindAnonymousDeclaration(node, 2048, "__type", false);
                            break;
                        case 152:
                            bindAnonymousDeclaration(node, 4096, "__object", false);
                            break;
                        case 160:
                        case 161:
                            bindAnonymousDeclaration(node, 16, "__function", true);
                            break;
                        case 217:
                            bindCatchVariableDeclaration(node);
                            break;
                        case 196:
                            bindDeclaration(node, 32, 899583, false);
                            break;
                        case 197:
                            bindDeclaration(node, 64, 792992, false);
                            break;
                        case 198:
                            bindDeclaration(node, 524288, 793056, false);
                            break;
                        case 199:
                            if (ts.isConst(node)) {
                                bindDeclaration(node, 128, 899967, false);
                            }
                            else {
                                bindDeclaration(node, 256, 899327, false);
                            }
                            break;
                        case 200:
                            bindModuleDeclaration(node);
                            break;
                        case 203:
                        case 206:
                        case 208:
                        case 212:
                            bindDeclaration(node, 8388608, 8388608, false);
                            break;
                        case 205:
                            if (node.name) {
                                bindDeclaration(node, 8388608, 8388608, false);
                            }
                            else {
                                bindChildren(node, 0, false);
                            }
                            break;
                        case 210:
                            if (!node.exportClause) {
                                declareSymbol(container.symbol.exports, container.symbol, node, 1073741824, 0);
                            }
                            bindChildren(node, 0, false);
                            break;
                        case 209:
                            if (node.expression.kind === 64) {
                                declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 8388608);
                            }
                            else {
                                declareSymbol(container.symbol.exports, container.symbol, node, 4, 107455);
                            }
                            bindChildren(node, 0, false);
                            break;
                        case 221:
                            if (ts.isExternalModule(node)) {
                                bindAnonymousDeclaration(node, 512, '"' + ts.removeFileExtension(node.fileName) + '"', true);
                                break;
                            }
                        case 174:
                            bindChildren(node, 0, !ts.isFunctionLike(node.parent));
                            break;
                        case 217:
                        case 181:
                        case 182:
                        case 183:
                        case 202:
                            bindChildren(node, 0, true);
                            break;
                        default:
                            var saveParent = parent;
                            parent = node;
                            ts.forEachChild(node, bind);
                            parent = saveParent;
                    }
                }
                function bindParameter(node) {
                    if (ts.isBindingPattern(node.name)) {
                        bindAnonymousDeclaration(node, 1, getDestructuringParameterName(node), false);
                    }
                    else {
                        bindDeclaration(node, 1, 107455, false);
                    }
                    if (node.flags & 112 && node.parent.kind === 133 && node.parent.parent.kind === 196) {
                        var classDeclaration = node.parent.parent;
                        declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4, 107455);
                    }
                }
                function bindPropertyOrMethodOrAccessor(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
                    if (ts.hasDynamicName(node)) {
                        bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer);
                    }
                    else {
                        bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer);
                    }
                }
            }
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var nextSymbolId = 1;
            var nextNodeId = 1;
            var nextMergeId = 1;
            ts.checkTime = 0;
            function createTypeChecker(host, produceDiagnostics) {
                var Symbol = ts.objectAllocator.getSymbolConstructor();
                var Type = ts.objectAllocator.getTypeConstructor();
                var Signature = ts.objectAllocator.getSignatureConstructor();
                var typeCount = 0;
                var emptyArray = [];
                var emptySymbols = {};
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0;
                var emitResolver = createResolver();
                var checker = {
                    getNodeCount: function () {
                        return ts.sum(host.getSourceFiles(), "nodeCount");
                    },
                    getIdentifierCount: function () {
                        return ts.sum(host.getSourceFiles(), "identifierCount");
                    },
                    getSymbolCount: function () {
                        return ts.sum(host.getSourceFiles(), "symbolCount");
                    },
                    getTypeCount: function () {
                        return typeCount;
                    },
                    isUndefinedSymbol: function (symbol) {
                        return symbol === undefinedSymbol;
                    },
                    isArgumentsSymbol: function (symbol) {
                        return symbol === argumentsSymbol;
                    },
                    getDiagnostics: getDiagnostics,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getTypeOfSymbolAtLocation: getTypeOfSymbolAtLocation,
                    getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
                    getPropertiesOfType: getPropertiesOfType,
                    getPropertyOfType: getPropertyOfType,
                    getSignaturesOfType: getSignaturesOfType,
                    getIndexTypeOfType: getIndexTypeOfType,
                    getReturnTypeOfSignature: getReturnTypeOfSignature,
                    getSymbolsInScope: getSymbolsInScope,
                    getSymbolAtLocation: getSymbolAtLocation,
                    getShorthandAssignmentValueSymbol: getShorthandAssignmentValueSymbol,
                    getTypeAtLocation: getTypeAtLocation,
                    typeToString: typeToString,
                    getSymbolDisplayBuilder: getSymbolDisplayBuilder,
                    symbolToString: symbolToString,
                    getAugmentedPropertiesOfType: getAugmentedPropertiesOfType,
                    getRootSymbols: getRootSymbols,
                    getContextualType: getContextualType,
                    getFullyQualifiedName: getFullyQualifiedName,
                    getResolvedSignature: getResolvedSignature,
                    getConstantValue: getConstantValue,
                    isValidPropertyAccess: isValidPropertyAccess,
                    getSignatureFromDeclaration: getSignatureFromDeclaration,
                    isImplementationOfOverload: isImplementationOfOverload,
                    getAliasedSymbol: resolveAlias,
                    getEmitResolver: getEmitResolver,
                    getExportsOfExternalModule: getExportsOfExternalModule
                };
                var undefinedSymbol = createSymbol(4 | 67108864, "undefined");
                var argumentsSymbol = createSymbol(4 | 67108864, "arguments");
                var unknownSymbol = createSymbol(4 | 67108864, "unknown");
                var resolvingSymbol = createSymbol(67108864, "__resolving__");
                var anyType = createIntrinsicType(1, "any");
                var stringType = createIntrinsicType(2, "string");
                var numberType = createIntrinsicType(4, "number");
                var booleanType = createIntrinsicType(8, "boolean");
                var esSymbolType = createIntrinsicType(1048576, "symbol");
                var voidType = createIntrinsicType(16, "void");
                var undefinedType = createIntrinsicType(32 | 262144, "undefined");
                var nullType = createIntrinsicType(64 | 262144, "null");
                var unknownType = createIntrinsicType(1, "unknown");
                var resolvingType = createIntrinsicType(1, "__resolving__");
                var emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var inferenceFailureType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
                var unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
                var globals = {};
                var globalArraySymbol;
                var globalESSymbolConstructorSymbol;
                var globalObjectType;
                var globalFunctionType;
                var globalArrayType;
                var globalStringType;
                var globalNumberType;
                var globalBooleanType;
                var globalRegExpType;
                var globalTemplateStringsArrayType;
                var globalESSymbolType;
                var globalIterableType;
                var anyArrayType;
                var tupleTypes = {};
                var unionTypes = {};
                var stringLiteralTypes = {};
                var emitExtends = false;
                var mergedSymbols = [];
                var symbolLinks = [];
                var nodeLinks = [];
                var potentialThisCollisions = [];
                var diagnostics = ts.createDiagnosticCollection();
                var primitiveTypeInfo = {
                    "string": {
                        type: stringType,
                        flags: 258
                    },
                    "number": {
                        type: numberType,
                        flags: 132
                    },
                    "boolean": {
                        type: booleanType,
                        flags: 8
                    },
                    "symbol": {
                        type: esSymbolType,
                        flags: 1048576
                    }
                };
                function getEmitResolver(sourceFile) {
                    getDiagnostics(sourceFile);
                    return emitResolver;
                }
                function error(location, message, arg0, arg1, arg2) {
                    var diagnostic = location ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2) : ts.createCompilerDiagnostic(message, arg0, arg1, arg2);
                    diagnostics.add(diagnostic);
                }
                function createSymbol(flags, name) {
                    return new Symbol(flags, name);
                }
                function getExcludedSymbolFlags(flags) {
                    var result = 0;
                    if (flags & 2)
                        result |= 107455;
                    if (flags & 1)
                        result |= 107454;
                    if (flags & 4)
                        result |= 107455;
                    if (flags & 8)
                        result |= 107455;
                    if (flags & 16)
                        result |= 106927;
                    if (flags & 32)
                        result |= 899583;
                    if (flags & 64)
                        result |= 792992;
                    if (flags & 256)
                        result |= 899327;
                    if (flags & 128)
                        result |= 899967;
                    if (flags & 512)
                        result |= 106639;
                    if (flags & 8192)
                        result |= 99263;
                    if (flags & 32768)
                        result |= 41919;
                    if (flags & 65536)
                        result |= 74687;
                    if (flags & 262144)
                        result |= 530912;
                    if (flags & 524288)
                        result |= 793056;
                    if (flags & 8388608)
                        result |= 8388608;
                    return result;
                }
                function recordMergedSymbol(target, source) {
                    if (!source.mergeId)
                        source.mergeId = nextMergeId++;
                    mergedSymbols[source.mergeId] = target;
                }
                function cloneSymbol(symbol) {
                    var result = createSymbol(symbol.flags | 33554432, symbol.name);
                    result.declarations = symbol.declarations.slice(0);
                    result.parent = symbol.parent;
                    if (symbol.valueDeclaration)
                        result.valueDeclaration = symbol.valueDeclaration;
                    if (symbol.constEnumOnlyModule)
                        result.constEnumOnlyModule = true;
                    if (symbol.members)
                        result.members = cloneSymbolTable(symbol.members);
                    if (symbol.exports)
                        result.exports = cloneSymbolTable(symbol.exports);
                    recordMergedSymbol(result, symbol);
                    return result;
                }
                function mergeSymbol(target, source) {
                    if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
                        if (source.flags & 512 && target.flags & 512 && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
                            target.constEnumOnlyModule = false;
                        }
                        target.flags |= source.flags;
                        if (!target.valueDeclaration && source.valueDeclaration)
                            target.valueDeclaration = source.valueDeclaration;
                        ts.forEach(source.declarations, function (node) {
                            target.declarations.push(node);
                        });
                        if (source.members) {
                            if (!target.members)
                                target.members = {};
                            mergeSymbolTable(target.members, source.members);
                        }
                        if (source.exports) {
                            if (!target.exports)
                                target.exports = {};
                            mergeSymbolTable(target.exports, source.exports);
                        }
                        recordMergedSymbol(target, source);
                    }
                    else {
                        var message = target.flags & 2 || source.flags & 2 ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0;
                        ts.forEach(source.declarations, function (node) {
                            error(node.name ? node.name : node, message, symbolToString(source));
                        });
                        ts.forEach(target.declarations, function (node) {
                            error(node.name ? node.name : node, message, symbolToString(source));
                        });
                    }
                }
                function cloneSymbolTable(symbolTable) {
                    var result = {};
                    for (var id in symbolTable) {
                        if (ts.hasProperty(symbolTable, id)) {
                            result[id] = symbolTable[id];
                        }
                    }
                    return result;
                }
                function mergeSymbolTable(target, source) {
                    for (var id in source) {
                        if (ts.hasProperty(source, id)) {
                            if (!ts.hasProperty(target, id)) {
                                target[id] = source[id];
                            }
                            else {
                                var symbol = target[id];
                                if (!(symbol.flags & 33554432)) {
                                    target[id] = symbol = cloneSymbol(symbol);
                                }
                                mergeSymbol(symbol, source[id]);
                            }
                        }
                    }
                }
                function getSymbolLinks(symbol) {
                    if (symbol.flags & 67108864)
                        return symbol;
                    if (!symbol.id)
                        symbol.id = nextSymbolId++;
                    return symbolLinks[symbol.id] || (symbolLinks[symbol.id] = {});
                }
                function getNodeLinks(node) {
                    if (!node.id)
                        node.id = nextNodeId++;
                    return nodeLinks[node.id] || (nodeLinks[node.id] = {});
                }
                function getSourceFile(node) {
                    return ts.getAncestor(node, 221);
                }
                function isGlobalSourceFile(node) {
                    return node.kind === 221 && !ts.isExternalModule(node);
                }
                function getSymbol(symbols, name, meaning) {
                    if (meaning && ts.hasProperty(symbols, name)) {
                        var symbol = symbols[name];
                        ts.Debug.assert((symbol.flags & 16777216) === 0, "Should never get an instantiated symbol here.");
                        if (symbol.flags & meaning) {
                            return symbol;
                        }
                        if (symbol.flags & 8388608) {
                            var target = resolveAlias(symbol);
                            if (target === unknownSymbol || target.flags & meaning) {
                                return symbol;
                            }
                        }
                    }
                }
                function isDefinedBefore(node1, node2) {
                    var file1 = ts.getSourceFileOfNode(node1);
                    var file2 = ts.getSourceFileOfNode(node2);
                    if (file1 === file2) {
                        return node1.pos <= node2.pos;
                    }
                    if (!compilerOptions.out) {
                        return true;
                    }
                    var sourceFiles = host.getSourceFiles();
                    return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
                }
                function resolveName(location, name, meaning, nameNotFoundMessage, nameArg) {
                    var result;
                    var lastLocation;
                    var propertyWithInvalidInitializer;
                    var errorLocation = location;
                    loop: while (location) {
                        if (location.locals && !isGlobalSourceFile(location)) {
                            if (result = getSymbol(location.locals, name, meaning)) {
                                break loop;
                            }
                        }
                        switch (location.kind) {
                            case 221:
                                if (!ts.isExternalModule(location))
                                    break;
                            case 200:
                                if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8914931)) {
                                    if (!(result.flags & 8388608 && getDeclarationOfAliasSymbol(result).kind === 212)) {
                                        break loop;
                                    }
                                    result = undefined;
                                }
                                break;
                            case 199:
                                if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8)) {
                                    break loop;
                                }
                                break;
                            case 130:
                            case 129:
                                if (location.parent.kind === 196 && !(location.flags & 128)) {
                                    var ctor = findConstructorDeclaration(location.parent);
                                    if (ctor && ctor.locals) {
                                        if (getSymbol(ctor.locals, name, meaning & 107455)) {
                                            propertyWithInvalidInitializer = location;
                                        }
                                    }
                                }
                                break;
                            case 196:
                            case 197:
                                if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & 793056)) {
                                    if (lastLocation && lastLocation.flags & 128) {
                                        error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters);
                                        return undefined;
                                    }
                                    break loop;
                                }
                                break;
                            case 126:
                                var grandparent = location.parent.parent;
                                if (grandparent.kind === 196 || grandparent.kind === 197) {
                                    if (result = getSymbol(getSymbolOfNode(grandparent).members, name, meaning & 793056)) {
                                        error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type);
                                        return undefined;
                                    }
                                }
                                break;
                            case 132:
                            case 131:
                            case 133:
                            case 134:
                            case 135:
                            case 195:
                            case 161:
                                if (name === "arguments") {
                                    result = argumentsSymbol;
                                    break loop;
                                }
                                break;
                            case 160:
                                if (name === "arguments") {
                                    result = argumentsSymbol;
                                    break loop;
                                }
                                var id = location.name;
                                if (id && name === id.text) {
                                    result = location.symbol;
                                    break loop;
                                }
                                break;
                        }
                        lastLocation = location;
                        location = location.parent;
                    }
                    if (!result) {
                        result = getSymbol(globals, name, meaning);
                    }
                    if (!result) {
                        if (nameNotFoundMessage) {
                            error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
                        }
                        return undefined;
                    }
                    if (nameNotFoundMessage) {
                        if (propertyWithInvalidInitializer) {
                            var propertyName = propertyWithInvalidInitializer.name;
                            error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, ts.declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
                            return undefined;
                        }
                        if (result.flags & 2) {
                            checkResolvedBlockScopedVariable(result, errorLocation);
                        }
                    }
                    return result;
                }
                function checkResolvedBlockScopedVariable(result, errorLocation) {
                    ts.Debug.assert((result.flags & 2) !== 0);
                    var declaration = ts.forEach(result.declarations, function (d) {
                        return ts.isBlockOrCatchScoped(d) ? d : undefined;
                    });
                    ts.Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
                    var isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
                    if (!isUsedBeforeDeclaration) {
                        var variableDeclaration = ts.getAncestor(declaration, 193);
                        var container = ts.getEnclosingBlockScopeContainer(variableDeclaration);
                        if (variableDeclaration.parent.parent.kind === 175 || variableDeclaration.parent.parent.kind === 181) {
                            isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
                        }
                        else if (variableDeclaration.parent.parent.kind === 183 || variableDeclaration.parent.parent.kind === 182) {
                            var expression = variableDeclaration.parent.parent.expression;
                            isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
                        }
                    }
                    if (isUsedBeforeDeclaration) {
                        error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.declarationNameToString(declaration.name));
                    }
                }
                function isSameScopeDescendentOf(initial, parent, stopAt) {
                    if (!parent) {
                        return false;
                    }
                    for (var current = initial; current && current !== stopAt && !ts.isFunctionLike(current); current = current.parent) {
                        if (current === parent) {
                            return true;
                        }
                    }
                    return false;
                }
                function isAliasSymbolDeclaration(node) {
                    return node.kind === 203 || node.kind === 205 && !!node.name || node.kind === 206 || node.kind === 208 || node.kind === 212 || node.kind === 209;
                }
                function getDeclarationOfAliasSymbol(symbol) {
                    return ts.forEach(symbol.declarations, function (d) {
                        return isAliasSymbolDeclaration(d) ? d : undefined;
                    });
                }
                function getTargetOfImportEqualsDeclaration(node) {
                    if (node.moduleReference.kind === 213) {
                        var moduleSymbol = resolveExternalModuleName(node, ts.getExternalModuleImportEqualsDeclarationExpression(node));
                        var exportAssignmentSymbol = moduleSymbol && getResolvedExportAssignmentSymbol(moduleSymbol);
                        return exportAssignmentSymbol || moduleSymbol;
                    }
                    return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, node);
                }
                function getTargetOfImportClause(node) {
                    var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
                    if (moduleSymbol) {
                        var exportAssignmentSymbol = getResolvedExportAssignmentSymbol(moduleSymbol);
                        if (!exportAssignmentSymbol) {
                            error(node.name, ts.Diagnostics.External_module_0_has_no_default_export_or_export_assignment, symbolToString(moduleSymbol));
                        }
                        return exportAssignmentSymbol;
                    }
                }
                function getTargetOfNamespaceImport(node) {
                    return resolveExternalModuleName(node, node.parent.parent.moduleSpecifier);
                }
                function getExternalModuleMember(node, specifier) {
                    var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
                    if (moduleSymbol) {
                        var name = specifier.propertyName || specifier.name;
                        if (name.text) {
                            var symbol = getSymbol(getExportsOfSymbol(moduleSymbol), name.text, 107455 | 793056 | 1536);
                            if (!symbol) {
                                error(name, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name));
                                return;
                            }
                            return symbol.flags & (107455 | 793056 | 1536) ? symbol : resolveAlias(symbol);
                        }
                    }
                }
                function getTargetOfImportSpecifier(node) {
                    return getExternalModuleMember(node.parent.parent.parent, node);
                }
                function getTargetOfExportSpecifier(node) {
                    return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : resolveEntityName(node.propertyName || node.name, 107455 | 793056 | 1536);
                }
                function getTargetOfExportAssignment(node) {
                    return resolveEntityName(node.expression, 107455 | 793056 | 1536);
                }
                function getTargetOfImportDeclaration(node) {
                    switch (node.kind) {
                        case 203:
                            return getTargetOfImportEqualsDeclaration(node);
                        case 205:
                            return getTargetOfImportClause(node);
                        case 206:
                            return getTargetOfNamespaceImport(node);
                        case 208:
                            return getTargetOfImportSpecifier(node);
                        case 212:
                            return getTargetOfExportSpecifier(node);
                        case 209:
                            return getTargetOfExportAssignment(node);
                    }
                }
                function resolveAlias(symbol) {
                    ts.Debug.assert((symbol.flags & 8388608) !== 0, "Should only get Alias here.");
                    var links = getSymbolLinks(symbol);
                    if (!links.target) {
                        links.target = resolvingSymbol;
                        var node = getDeclarationOfAliasSymbol(symbol);
                        var target = getTargetOfImportDeclaration(node);
                        if (links.target === resolvingSymbol) {
                            links.target = target || unknownSymbol;
                        }
                        else {
                            error(node, ts.Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
                        }
                    }
                    else if (links.target === resolvingSymbol) {
                        links.target = unknownSymbol;
                    }
                    return links.target;
                }
                function markExportAsReferenced(node) {
                    var symbol = getSymbolOfNode(node);
                    var target = resolveAlias(symbol);
                    if (target && target !== unknownSymbol && target.flags & 107455 && !isConstEnumOrConstEnumOnlyModule(target)) {
                        markAliasSymbolAsReferenced(symbol);
                    }
                }
                function markAliasSymbolAsReferenced(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.referenced) {
                        links.referenced = true;
                        var node = getDeclarationOfAliasSymbol(symbol);
                        if (node.kind === 209) {
                            checkExpressionCached(node.expression);
                        }
                        else if (node.kind === 212) {
                            checkExpressionCached(node.propertyName || node.name);
                        }
                        else if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                            checkExpressionCached(node.moduleReference);
                        }
                    }
                }
                function getSymbolOfPartOfRightHandSideOfImportEquals(entityName, importDeclaration) {
                    if (!importDeclaration) {
                        importDeclaration = ts.getAncestor(entityName, 203);
                        ts.Debug.assert(importDeclaration !== undefined);
                    }
                    if (entityName.kind === 64 && isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
                        entityName = entityName.parent;
                    }
                    if (entityName.kind === 64 || entityName.parent.kind === 125) {
                        return resolveEntityName(entityName, 1536);
                    }
                    else {
                        ts.Debug.assert(entityName.parent.kind === 203);
                        return resolveEntityName(entityName, 107455 | 793056 | 1536);
                    }
                }
                function getFullyQualifiedName(symbol) {
                    return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
                }
                function resolveEntityName(name, meaning) {
                    if (ts.getFullWidth(name) === 0) {
                        return undefined;
                    }
                    if (name.kind === 64) {
                        var symbol = resolveName(name, name.text, meaning, ts.Diagnostics.Cannot_find_name_0, name);
                        if (!symbol) {
                            return undefined;
                        }
                    }
                    else if (name.kind === 125) {
                        var namespace = resolveEntityName(name.left, 1536);
                        if (!namespace || namespace === unknownSymbol || ts.getFullWidth(name.right) === 0) {
                            return undefined;
                        }
                        var right = name.right;
                        var symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
                        if (!symbol) {
                            error(right, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right));
                            return undefined;
                        }
                    }
                    ts.Debug.assert((symbol.flags & 16777216) === 0, "Should never get an instantiated symbol here.");
                    return symbol.flags & meaning ? symbol : resolveAlias(symbol);
                }
                function isExternalModuleNameRelative(moduleName) {
                    return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\";
                }
                function resolveExternalModuleName(location, moduleReferenceExpression) {
                    if (moduleReferenceExpression.kind !== 8) {
                        return;
                    }
                    var moduleReferenceLiteral = moduleReferenceExpression;
                    var searchPath = ts.getDirectoryPath(getSourceFile(location).fileName);
                    var moduleName = ts.escapeIdentifier(moduleReferenceLiteral.text);
                    if (!moduleName)
                        return;
                    var isRelative = isExternalModuleNameRelative(moduleName);
                    if (!isRelative) {
                        var symbol = getSymbol(globals, '"' + moduleName + '"', 512);
                        if (symbol) {
                            return symbol;
                        }
                    }
                    while (true) {
                        var fileName = ts.normalizePath(ts.combinePaths(searchPath, moduleName));
                        var sourceFile = host.getSourceFile(fileName + ".ts") || host.getSourceFile(fileName + ".d.ts");
                        if (sourceFile || isRelative)
                            break;
                        var parentPath = ts.getDirectoryPath(searchPath);
                        if (parentPath === searchPath)
                            break;
                        searchPath = parentPath;
                    }
                    if (sourceFile) {
                        if (sourceFile.symbol) {
                            return sourceFile.symbol;
                        }
                        error(moduleReferenceLiteral, ts.Diagnostics.File_0_is_not_an_external_module, sourceFile.fileName);
                        return;
                    }
                    error(moduleReferenceLiteral, ts.Diagnostics.Cannot_find_external_module_0, moduleName);
                }
                function getExportAssignmentSymbol(moduleSymbol) {
                    return moduleSymbol.exports["default"];
                }
                function getResolvedExportAssignmentSymbol(moduleSymbol) {
                    var symbol = getExportAssignmentSymbol(moduleSymbol);
                    if (symbol) {
                        if (symbol.flags & (107455 | 793056 | 1536)) {
                            return symbol;
                        }
                        if (symbol.flags & 8388608) {
                            return resolveAlias(symbol);
                        }
                    }
                }
                function getExportsOfSymbol(symbol) {
                    return symbol.flags & 1536 ? getExportsOfModule(symbol) : symbol.exports;
                }
                function getExportsOfModule(moduleSymbol) {
                    var links = getSymbolLinks(moduleSymbol);
                    return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
                }
                function extendExportSymbols(target, source) {
                    for (var id in source) {
                        if (id !== "default" && !ts.hasProperty(target, id)) {
                            target[id] = source[id];
                        }
                    }
                }
                function getExportsForModule(moduleSymbol) {
                    if (compilerOptions.target < 2) {
                        var defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
                        if (defaultSymbol) {
                            return {
                                "default": defaultSymbol
                            };
                        }
                    }
                    var result;
                    var visitedSymbols = [];
                    visit(moduleSymbol);
                    return result || moduleSymbol.exports;
                    function visit(symbol) {
                        if (!ts.contains(visitedSymbols, symbol)) {
                            visitedSymbols.push(symbol);
                            if (symbol !== moduleSymbol) {
                                if (!result) {
                                    result = cloneSymbolTable(moduleSymbol.exports);
                                }
                                extendExportSymbols(result, symbol.exports);
                            }
                            var exportStars = symbol.exports["__export"];
                            if (exportStars) {
                                ts.forEach(exportStars.declarations, function (node) {
                                    visit(resolveExternalModuleName(node, node.moduleSpecifier));
                                });
                            }
                        }
                    }
                }
                function getMergedSymbol(symbol) {
                    var merged;
                    return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
                }
                function getSymbolOfNode(node) {
                    return getMergedSymbol(node.symbol);
                }
                function getParentOfSymbol(symbol) {
                    return getMergedSymbol(symbol.parent);
                }
                function getExportSymbolOfValueSymbolIfExported(symbol) {
                    return symbol && (symbol.flags & 1048576) !== 0 ? getMergedSymbol(symbol.exportSymbol) : symbol;
                }
                function symbolIsValue(symbol) {
                    if (symbol.flags & 16777216) {
                        return symbolIsValue(getSymbolLinks(symbol).target);
                    }
                    if (symbol.flags & 107455) {
                        return true;
                    }
                    if (symbol.flags & 8388608) {
                        return (resolveAlias(symbol).flags & 107455) !== 0;
                    }
                    return false;
                }
                function findConstructorDeclaration(node) {
                    var members = node.members;
                    for (var i = 0; i < members.length; i++) {
                        var member = members[i];
                        if (member.kind === 133 && ts.nodeIsPresent(member.body)) {
                            return member;
                        }
                    }
                }
                function createType(flags) {
                    var result = new Type(checker, flags);
                    result.id = typeCount++;
                    return result;
                }
                function createIntrinsicType(kind, intrinsicName) {
                    var type = createType(kind);
                    type.intrinsicName = intrinsicName;
                    return type;
                }
                function createObjectType(kind, symbol) {
                    var type = createType(kind);
                    type.symbol = symbol;
                    return type;
                }
                function isReservedMemberName(name) {
                    return name.charCodeAt(0) === 95 && name.charCodeAt(1) === 95 && name.charCodeAt(2) !== 95 && name.charCodeAt(2) !== 64;
                }
                function getNamedMembers(members) {
                    var result;
                    for (var id in members) {
                        if (ts.hasProperty(members, id)) {
                            if (!isReservedMemberName(id)) {
                                if (!result)
                                    result = [];
                                var symbol = members[id];
                                if (symbolIsValue(symbol)) {
                                    result.push(symbol);
                                }
                            }
                        }
                    }
                    return result || emptyArray;
                }
                function setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
                    type.members = members;
                    type.properties = getNamedMembers(members);
                    type.callSignatures = callSignatures;
                    type.constructSignatures = constructSignatures;
                    if (stringIndexType)
                        type.stringIndexType = stringIndexType;
                    if (numberIndexType)
                        type.numberIndexType = numberIndexType;
                    return type;
                }
                function createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
                    return setObjectTypeMembers(createObjectType(32768, symbol), members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function forEachSymbolTableInScope(enclosingDeclaration, callback) {
                    var result;
                    for (var location = enclosingDeclaration; location; location = location.parent) {
                        if (location.locals && !isGlobalSourceFile(location)) {
                            if (result = callback(location.locals)) {
                                return result;
                            }
                        }
                        switch (location.kind) {
                            case 221:
                                if (!ts.isExternalModule(location)) {
                                    break;
                                }
                            case 200:
                                if (result = callback(getSymbolOfNode(location).exports)) {
                                    return result;
                                }
                                break;
                            case 196:
                            case 197:
                                if (result = callback(getSymbolOfNode(location).members)) {
                                    return result;
                                }
                                break;
                        }
                    }
                    return callback(globals);
                }
                function getQualifiedLeftMeaning(rightMeaning) {
                    return rightMeaning === 107455 ? 107455 : 1536;
                }
                function getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing) {
                    function getAccessibleSymbolChainFromSymbolTable(symbols) {
                        function canQualifySymbol(symbolFromSymbolTable, meaning) {
                            if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
                                return true;
                            }
                            var accessibleParent = getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
                            return !!accessibleParent;
                        }
                        function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) {
                            if (symbol === (resolvedAliasSymbol || symbolFromSymbolTable)) {
                                return !ts.forEach(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && canQualifySymbol(symbolFromSymbolTable, meaning);
                            }
                        }
                        if (isAccessible(ts.lookUp(symbols, symbol.name))) {
                            return [
                                symbol
                            ];
                        }
                        return ts.forEachValue(symbols, function (symbolFromSymbolTable) {
                            if (symbolFromSymbolTable.flags & 8388608) {
                                if (!useOnlyExternalAliasing || ts.forEach(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration)) {
                                    var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
                                    if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
                                        return [
                                            symbolFromSymbolTable
                                        ];
                                    }
                                    var accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
                                    if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
                                        return [
                                            symbolFromSymbolTable
                                        ].concat(accessibleSymbolsFromExports);
                                    }
                                }
                            }
                        });
                    }
                    if (symbol) {
                        return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
                    }
                }
                function needsQualification(symbol, enclosingDeclaration, meaning) {
                    var qualify = false;
                    forEachSymbolTableInScope(enclosingDeclaration, function (symbolTable) {
                        if (!ts.hasProperty(symbolTable, symbol.name)) {
                            return false;
                        }
                        var symbolFromSymbolTable = symbolTable[symbol.name];
                        if (symbolFromSymbolTable === symbol) {
                            return true;
                        }
                        symbolFromSymbolTable = (symbolFromSymbolTable.flags & 8388608) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable;
                        if (symbolFromSymbolTable.flags & meaning) {
                            qualify = true;
                            return true;
                        }
                        return false;
                    });
                    return qualify;
                }
                function isSymbolAccessible(symbol, enclosingDeclaration, meaning) {
                    if (symbol && enclosingDeclaration && !(symbol.flags & 262144)) {
                        var initialSymbol = symbol;
                        var meaningToLook = meaning;
                        while (symbol) {
                            var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, false);
                            if (accessibleSymbolChain) {
                                var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
                                if (!hasAccessibleDeclarations) {
                                    return {
                                        accessibility: 1,
                                        errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
                                        errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1536) : undefined
                                    };
                                }
                                return hasAccessibleDeclarations;
                            }
                            meaningToLook = getQualifiedLeftMeaning(meaning);
                            symbol = getParentOfSymbol(symbol);
                        }
                        var symbolExternalModule = ts.forEach(initialSymbol.declarations, getExternalModuleContainer);
                        if (symbolExternalModule) {
                            var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
                            if (symbolExternalModule !== enclosingExternalModule) {
                                return {
                                    accessibility: 2,
                                    errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
                                    errorModuleName: symbolToString(symbolExternalModule)
                                };
                            }
                        }
                        return {
                            accessibility: 1,
                            errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning)
                        };
                    }
                    return {
                        accessibility: 0
                    };
                    function getExternalModuleContainer(declaration) {
                        for (; declaration; declaration = declaration.parent) {
                            if (hasExternalModuleSymbol(declaration)) {
                                return getSymbolOfNode(declaration);
                            }
                        }
                    }
                }
                function hasExternalModuleSymbol(declaration) {
                    return (declaration.kind === 200 && declaration.name.kind === 8) || (declaration.kind === 221 && ts.isExternalModule(declaration));
                }
                function hasVisibleDeclarations(symbol) {
                    var aliasesToMakeVisible;
                    if (ts.forEach(symbol.declarations, function (declaration) {
                        return !getIsDeclarationVisible(declaration);
                    })) {
                        return undefined;
                    }
                    return {
                        accessibility: 0,
                        aliasesToMakeVisible: aliasesToMakeVisible
                    };
                    function getIsDeclarationVisible(declaration) {
                        if (!isDeclarationVisible(declaration)) {
                            if (declaration.kind === 203 && !(declaration.flags & 1) && isDeclarationVisible(declaration.parent)) {
                                getNodeLinks(declaration).isVisible = true;
                                if (aliasesToMakeVisible) {
                                    if (!ts.contains(aliasesToMakeVisible, declaration)) {
                                        aliasesToMakeVisible.push(declaration);
                                    }
                                }
                                else {
                                    aliasesToMakeVisible = [
                                        declaration
                                    ];
                                }
                                return true;
                            }
                            return false;
                        }
                        return true;
                    }
                }
                function isEntityNameVisible(entityName, enclosingDeclaration) {
                    var meaning;
                    if (entityName.parent.kind === 142) {
                        meaning = 107455 | 1048576;
                    }
                    else if (entityName.kind === 125 || entityName.parent.kind === 203) {
                        meaning = 1536;
                    }
                    else {
                        meaning = 793056;
                    }
                    var firstIdentifier = getFirstIdentifier(entityName);
                    var symbol = resolveName(enclosingDeclaration, firstIdentifier.text, meaning, undefined, undefined);
                    return (symbol && hasVisibleDeclarations(symbol)) || {
                        accessibility: 1,
                        errorSymbolName: ts.getTextOfNode(firstIdentifier),
                        errorNode: firstIdentifier
                    };
                }
                function writeKeyword(writer, kind) {
                    writer.writeKeyword(ts.tokenToString(kind));
                }
                function writePunctuation(writer, kind) {
                    writer.writePunctuation(ts.tokenToString(kind));
                }
                function writeSpace(writer) {
                    writer.writeSpace(" ");
                }
                function symbolToString(symbol, enclosingDeclaration, meaning) {
                    var writer = ts.getSingleLineStringWriter();
                    getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning);
                    var result = writer.string();
                    ts.releaseStringWriter(writer);
                    return result;
                }
                function typeToString(type, enclosingDeclaration, flags) {
                    var writer = ts.getSingleLineStringWriter();
                    getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                    var result = writer.string();
                    ts.releaseStringWriter(writer);
                    var maxLength = compilerOptions.noErrorTruncation || flags & 4 ? undefined : 100;
                    if (maxLength && result.length >= maxLength) {
                        result = result.substr(0, maxLength - "...".length) + "...";
                    }
                    return result;
                }
                function getTypeAliasForTypeLiteral(type) {
                    if (type.symbol && type.symbol.flags & 2048) {
                        var node = type.symbol.declarations[0].parent;
                        while (node.kind === 147) {
                            node = node.parent;
                        }
                        if (node.kind === 198) {
                            return getSymbolOfNode(node);
                        }
                    }
                    return undefined;
                }
                var _displayBuilder;
                function getSymbolDisplayBuilder() {
                    function appendSymbolNameOnly(symbol, writer) {
                        if (symbol.declarations && symbol.declarations.length > 0) {
                            var declaration = symbol.declarations[0];
                            if (declaration.name) {
                                writer.writeSymbol(ts.declarationNameToString(declaration.name), symbol);
                                return;
                            }
                        }
                        writer.writeSymbol(symbol.name, symbol);
                    }
                    function buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags, typeFlags) {
                        var parentSymbol;
                        function appendParentTypeArgumentsAndSymbolName(symbol) {
                            if (parentSymbol) {
                                if (flags & 1) {
                                    if (symbol.flags & 16777216) {
                                        buildDisplayForTypeArgumentsAndDelimiters(getTypeParametersOfClassOrInterface(parentSymbol), symbol.mapper, writer, enclosingDeclaration);
                                    }
                                    else {
                                        buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration);
                                    }
                                }
                                writePunctuation(writer, 20);
                            }
                            parentSymbol = symbol;
                            appendSymbolNameOnly(symbol, writer);
                        }
                        writer.trackSymbol(symbol, enclosingDeclaration, meaning);
                        function walkSymbol(symbol, meaning) {
                            if (symbol) {
                                var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2));
                                if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
                                    walkSymbol(getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), getQualifiedLeftMeaning(meaning));
                                }
                                if (accessibleSymbolChain) {
                                    for (var i = 0, n = accessibleSymbolChain.length; i < n; i++) {
                                        appendParentTypeArgumentsAndSymbolName(accessibleSymbolChain[i]);
                                    }
                                }
                                else {
                                    if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) {
                                        return;
                                    }
                                    if (symbol.flags & 2048 || symbol.flags & 4096) {
                                        return;
                                    }
                                    appendParentTypeArgumentsAndSymbolName(symbol);
                                }
                            }
                        }
                        var isTypeParameter = symbol.flags & 262144;
                        var typeFormatFlag = 128 & typeFlags;
                        if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) {
                            walkSymbol(symbol, meaning);
                            return;
                        }
                        return appendParentTypeArgumentsAndSymbolName(symbol);
                    }
                    function buildTypeDisplay(type, writer, enclosingDeclaration, globalFlags, typeStack) {
                        var globalFlagsToPass = globalFlags & 16;
                        return writeType(type, globalFlags);
                        function writeType(type, flags) {
                            if (type.flags & 1048703) {
                                writer.writeKeyword(!(globalFlags & 16) && (type.flags & 1) ? "any" : type.intrinsicName);
                            }
                            else if (type.flags & 4096) {
                                writeTypeReference(type, flags);
                            }
                            else if (type.flags & (1024 | 2048 | 128 | 512)) {
                                buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 793056, 0, flags);
                            }
                            else if (type.flags & 8192) {
                                writeTupleType(type);
                            }
                            else if (type.flags & 16384) {
                                writeUnionType(type, flags);
                            }
                            else if (type.flags & 32768) {
                                writeAnonymousType(type, flags);
                            }
                            else if (type.flags & 256) {
                                writer.writeStringLiteral(type.text);
                            }
                            else {
                                writePunctuation(writer, 14);
                                writeSpace(writer);
                                writePunctuation(writer, 21);
                                writeSpace(writer);
                                writePunctuation(writer, 15);
                            }
                        }
                        function writeTypeList(types, union) {
                            for (var i = 0; i < types.length; i++) {
                                if (i > 0) {
                                    if (union) {
                                        writeSpace(writer);
                                    }
                                    writePunctuation(writer, union ? 44 : 23);
                                    writeSpace(writer);
                                }
                                writeType(types[i], union ? 64 : 0);
                            }
                        }
                        function writeTypeReference(type, flags) {
                            if (type.target === globalArrayType && !(flags & 1)) {
                                writeType(type.typeArguments[0], 64);
                                writePunctuation(writer, 18);
                                writePunctuation(writer, 19);
                            }
                            else {
                                buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, 793056);
                                writePunctuation(writer, 24);
                                writeTypeList(type.typeArguments, false);
                                writePunctuation(writer, 25);
                            }
                        }
                        function writeTupleType(type) {
                            writePunctuation(writer, 18);
                            writeTypeList(type.elementTypes, false);
                            writePunctuation(writer, 19);
                        }
                        function writeUnionType(type, flags) {
                            if (flags & 64) {
                                writePunctuation(writer, 16);
                            }
                            writeTypeList(type.types, true);
                            if (flags & 64) {
                                writePunctuation(writer, 17);
                            }
                        }
                        function writeAnonymousType(type, flags) {
                            if (type.symbol && type.symbol.flags & (32 | 384 | 512)) {
                                writeTypeofSymbol(type, flags);
                            }
                            else if (shouldWriteTypeOfFunctionSymbol()) {
                                writeTypeofSymbol(type, flags);
                            }
                            else if (typeStack && ts.contains(typeStack, type)) {
                                var typeAlias = getTypeAliasForTypeLiteral(type);
                                if (typeAlias) {
                                    buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, 793056, 0, flags);
                                }
                                else {
                                    writeKeyword(writer, 111);
                                }
                            }
                            else {
                                if (!typeStack) {
                                    typeStack = [];
                                }
                                typeStack.push(type);
                                writeLiteralType(type, flags);
                                typeStack.pop();
                            }
                            function shouldWriteTypeOfFunctionSymbol() {
                                if (type.symbol) {
                                    var isStaticMethodSymbol = !!(type.symbol.flags & 8192 && ts.forEach(type.symbol.declarations, function (declaration) {
                                        return declaration.flags & 128;
                                    }));
                                    var isNonLocalFunctionSymbol = !!(type.symbol.flags & 16) && (type.symbol.parent || ts.forEach(type.symbol.declarations, function (declaration) {
                                        return declaration.parent.kind === 221 || declaration.parent.kind === 201;
                                    }));
                                    if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
                                        return !!(flags & 2) || (typeStack && ts.contains(typeStack, type));
                                    }
                                }
                            }
                        }
                        function writeTypeofSymbol(type, typeFormatFlags) {
                            writeKeyword(writer, 96);
                            writeSpace(writer);
                            buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 107455, 0, typeFormatFlags);
                        }
                        function getIndexerParameterName(type, indexKind, fallbackName) {
                            var declaration = getIndexDeclarationOfSymbol(type.symbol, indexKind);
                            if (!declaration) {
                                return fallbackName;
                            }
                            ts.Debug.assert(declaration.parameters.length !== 0);
                            return ts.declarationNameToString(declaration.parameters[0].name);
                        }
                        function writeLiteralType(type, flags) {
                            var resolved = resolveObjectOrUnionTypeMembers(type);
                            if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
                                if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
                                    writePunctuation(writer, 14);
                                    writePunctuation(writer, 15);
                                    return;
                                }
                                if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
                                    if (flags & 64) {
                                        writePunctuation(writer, 16);
                                    }
                                    buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8, typeStack);
                                    if (flags & 64) {
                                        writePunctuation(writer, 17);
                                    }
                                    return;
                                }
                                if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
                                    if (flags & 64) {
                                        writePunctuation(writer, 16);
                                    }
                                    writeKeyword(writer, 87);
                                    writeSpace(writer);
                                    buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8, typeStack);
                                    if (flags & 64) {
                                        writePunctuation(writer, 17);
                                    }
                                    return;
                                }
                            }
                            writePunctuation(writer, 14);
                            writer.writeLine();
                            writer.increaseIndent();
                            for (var i = 0; i < resolved.callSignatures.length; i++) {
                                buildSignatureDisplay(resolved.callSignatures[i], writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                writePunctuation(writer, 22);
                                writer.writeLine();
                            }
                            for (var i = 0; i < resolved.constructSignatures.length; i++) {
                                writeKeyword(writer, 87);
                                writeSpace(writer);
                                buildSignatureDisplay(resolved.constructSignatures[i], writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                writePunctuation(writer, 22);
                                writer.writeLine();
                            }
                            if (resolved.stringIndexType) {
                                writePunctuation(writer, 18);
                                writer.writeParameter(getIndexerParameterName(resolved, 0, "x"));
                                writePunctuation(writer, 51);
                                writeSpace(writer);
                                writeKeyword(writer, 120);
                                writePunctuation(writer, 19);
                                writePunctuation(writer, 51);
                                writeSpace(writer);
                                writeType(resolved.stringIndexType, 0);
                                writePunctuation(writer, 22);
                                writer.writeLine();
                            }
                            if (resolved.numberIndexType) {
                                writePunctuation(writer, 18);
                                writer.writeParameter(getIndexerParameterName(resolved, 1, "x"));
                                writePunctuation(writer, 51);
                                writeSpace(writer);
                                writeKeyword(writer, 118);
                                writePunctuation(writer, 19);
                                writePunctuation(writer, 51);
                                writeSpace(writer);
                                writeType(resolved.numberIndexType, 0);
                                writePunctuation(writer, 22);
                                writer.writeLine();
                            }
                            for (var i = 0; i < resolved.properties.length; i++) {
                                var p = resolved.properties[i];
                                var t = getTypeOfSymbol(p);
                                if (p.flags & (16 | 8192) && !getPropertiesOfObjectType(t).length) {
                                    var signatures = getSignaturesOfType(t, 0);
                                    for (var j = 0; j < signatures.length; j++) {
                                        buildSymbolDisplay(p, writer);
                                        if (p.flags & 536870912) {
                                            writePunctuation(writer, 50);
                                        }
                                        buildSignatureDisplay(signatures[j], writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                        writePunctuation(writer, 22);
                                        writer.writeLine();
                                    }
                                }
                                else {
                                    buildSymbolDisplay(p, writer);
                                    if (p.flags & 536870912) {
                                        writePunctuation(writer, 50);
                                    }
                                    writePunctuation(writer, 51);
                                    writeSpace(writer);
                                    writeType(t, 0);
                                    writePunctuation(writer, 22);
                                    writer.writeLine();
                                }
                            }
                            writer.decreaseIndent();
                            writePunctuation(writer, 15);
                        }
                    }
                    function buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaraiton, flags) {
                        var targetSymbol = getTargetSymbol(symbol);
                        if (targetSymbol.flags & 32 || targetSymbol.flags & 64) {
                            buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
                        }
                    }
                    function buildTypeParameterDisplay(tp, writer, enclosingDeclaration, flags, typeStack) {
                        appendSymbolNameOnly(tp.symbol, writer);
                        var constraint = getConstraintOfTypeParameter(tp);
                        if (constraint) {
                            writeSpace(writer);
                            writeKeyword(writer, 78);
                            writeSpace(writer);
                            buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
                        }
                    }
                    function buildParameterDisplay(p, writer, enclosingDeclaration, flags, typeStack) {
                        if (ts.hasDotDotDotToken(p.valueDeclaration)) {
                            writePunctuation(writer, 21);
                        }
                        appendSymbolNameOnly(p, writer);
                        if (ts.hasQuestionToken(p.valueDeclaration) || p.valueDeclaration.initializer) {
                            writePunctuation(writer, 50);
                        }
                        writePunctuation(writer, 51);
                        writeSpace(writer);
                        buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
                    }
                    function buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosingDeclaration, flags, typeStack) {
                        if (typeParameters && typeParameters.length) {
                            writePunctuation(writer, 24);
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (i > 0) {
                                    writePunctuation(writer, 23);
                                    writeSpace(writer);
                                }
                                buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
                            }
                            writePunctuation(writer, 25);
                        }
                    }
                    function buildDisplayForTypeArgumentsAndDelimiters(typeParameters, mapper, writer, enclosingDeclaration, flags, typeStack) {
                        if (typeParameters && typeParameters.length) {
                            writePunctuation(writer, 24);
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (i > 0) {
                                    writePunctuation(writer, 23);
                                    writeSpace(writer);
                                }
                                buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, 0);
                            }
                            writePunctuation(writer, 25);
                        }
                    }
                    function buildDisplayForParametersAndDelimiters(parameters, writer, enclosingDeclaration, flags, typeStack) {
                        writePunctuation(writer, 16);
                        for (var i = 0; i < parameters.length; i++) {
                            if (i > 0) {
                                writePunctuation(writer, 23);
                                writeSpace(writer);
                            }
                            buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
                        }
                        writePunctuation(writer, 17);
                    }
                    function buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
                        if (flags & 8) {
                            writeSpace(writer);
                            writePunctuation(writer, 32);
                        }
                        else {
                            writePunctuation(writer, 51);
                        }
                        writeSpace(writer);
                        buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
                    }
                    function buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
                        if (signature.target && (flags & 32)) {
                            buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
                        }
                        else {
                            buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
                        }
                        buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
                        buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
                    }
                    return _displayBuilder || (_displayBuilder = {
                        symbolToString: symbolToString,
                        typeToString: typeToString,
                        buildSymbolDisplay: buildSymbolDisplay,
                        buildTypeDisplay: buildTypeDisplay,
                        buildTypeParameterDisplay: buildTypeParameterDisplay,
                        buildParameterDisplay: buildParameterDisplay,
                        buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
                        buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
                        buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
                        buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
                        buildSignatureDisplay: buildSignatureDisplay,
                        buildReturnTypeDisplay: buildReturnTypeDisplay
                    });
                }
                function isDeclarationVisible(node) {
                    function getContainingExternalModule(node) {
                        for (; node; node = node.parent) {
                            if (node.kind === 200) {
                                if (node.name.kind === 8) {
                                    return node;
                                }
                            }
                            else if (node.kind === 221) {
                                return ts.isExternalModule(node) ? node : undefined;
                            }
                        }
                        ts.Debug.fail("getContainingModule cant reach here");
                    }
                    function isUsedInExportAssignment(node) {
                        var externalModule = getContainingExternalModule(node);
                        if (externalModule) {
                            var externalModuleSymbol = getSymbolOfNode(externalModule);
                            var exportAssignmentSymbol = getExportAssignmentSymbol(externalModuleSymbol);
                            var resolvedExportSymbol;
                            var symbolOfNode = getSymbolOfNode(node);
                            if (isSymbolUsedInExportAssignment(symbolOfNode)) {
                                return true;
                            }
                            if (symbolOfNode.flags & 8388608) {
                                return isSymbolUsedInExportAssignment(resolveAlias(symbolOfNode));
                            }
                        }
                        function isSymbolUsedInExportAssignment(symbol) {
                            if (exportAssignmentSymbol === symbol) {
                                return true;
                            }
                            if (exportAssignmentSymbol && !!(exportAssignmentSymbol.flags & 8388608)) {
                                resolvedExportSymbol = resolvedExportSymbol || resolveAlias(exportAssignmentSymbol);
                                if (resolvedExportSymbol === symbol) {
                                    return true;
                                }
                                return ts.forEach(resolvedExportSymbol.declarations, function (current) {
                                    while (current) {
                                        if (current === node) {
                                            return true;
                                        }
                                        current = current.parent;
                                    }
                                });
                            }
                        }
                    }
                    function determineIfDeclarationIsVisible() {
                        switch (node.kind) {
                            case 193:
                            case 150:
                            case 200:
                            case 196:
                            case 197:
                            case 198:
                            case 195:
                            case 199:
                            case 203:
                                var parent = getDeclarationContainer(node);
                                if (!(ts.getCombinedNodeFlags(node) & 1) && !(node.kind !== 203 && parent.kind !== 221 && ts.isInAmbientContext(parent))) {
                                    return isGlobalSourceFile(parent) || isUsedInExportAssignment(node);
                                }
                                return isDeclarationVisible(parent);
                            case 130:
                            case 129:
                            case 134:
                            case 135:
                            case 132:
                            case 131:
                                if (node.flags & (32 | 64)) {
                                    return false;
                                }
                            case 133:
                            case 137:
                            case 136:
                            case 138:
                            case 128:
                            case 201:
                            case 140:
                            case 141:
                            case 143:
                            case 139:
                            case 144:
                            case 145:
                            case 146:
                            case 147:
                                return isDeclarationVisible(node.parent);
                            case 127:
                            case 221:
                                return true;
                            default:
                                ts.Debug.fail("isDeclarationVisible unknown: SyntaxKind: " + node.kind);
                        }
                    }
                    if (node) {
                        var links = getNodeLinks(node);
                        if (links.isVisible === undefined) {
                            links.isVisible = !!determineIfDeclarationIsVisible();
                        }
                        return links.isVisible;
                    }
                }
                function getRootDeclaration(node) {
                    while (node.kind === 150) {
                        node = node.parent.parent;
                    }
                    return node;
                }
                function getDeclarationContainer(node) {
                    node = getRootDeclaration(node);
                    return node.kind === 193 ? node.parent.parent.parent : node.parent;
                }
                function getTypeOfPrototypeProperty(prototype) {
                    var classType = getDeclaredTypeOfSymbol(prototype.parent);
                    return classType.typeParameters ? createTypeReference(classType, ts.map(classType.typeParameters, function (_) {
                        return anyType;
                    })) : classType;
                }
                function getTypeOfPropertyOfType(type, name) {
                    var prop = getPropertyOfType(type, name);
                    return prop ? getTypeOfSymbol(prop) : undefined;
                }
                function getTypeForBindingElement(declaration) {
                    var pattern = declaration.parent;
                    var parentType = getTypeForVariableLikeDeclaration(pattern.parent);
                    if (parentType === unknownType) {
                        return unknownType;
                    }
                    if (!parentType || parentType === anyType) {
                        if (declaration.initializer) {
                            return checkExpressionCached(declaration.initializer);
                        }
                        return parentType;
                    }
                    if (pattern.kind === 148) {
                        var name = declaration.propertyName || declaration.name;
                        var type = getTypeOfPropertyOfType(parentType, name.text) || isNumericLiteralName(name.text) && getIndexTypeOfType(parentType, 1) || getIndexTypeOfType(parentType, 0);
                        if (!type) {
                            error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name));
                            return unknownType;
                        }
                    }
                    else {
                        if (!isArrayLikeType(parentType)) {
                            error(pattern, ts.Diagnostics.Type_0_is_not_an_array_type, typeToString(parentType));
                            return unknownType;
                        }
                        if (!declaration.dotDotDotToken) {
                            var propName = "" + ts.indexOf(pattern.elements, declaration);
                            var type = isTupleLikeType(parentType) ? getTypeOfPropertyOfType(parentType, propName) : getIndexTypeOfType(parentType, 1);
                            if (!type) {
                                if (isTupleType(parentType)) {
                                    error(declaration, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), parentType.elementTypes.length, pattern.elements.length);
                                }
                                else {
                                    error(declaration, ts.Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
                                }
                                return unknownType;
                            }
                        }
                        else {
                            var type = createArrayType(getIndexTypeOfType(parentType, 1));
                        }
                    }
                    return type;
                }
                function getTypeForVariableLikeDeclaration(declaration) {
                    if (declaration.parent.parent.kind === 182) {
                        return anyType;
                    }
                    if (declaration.parent.parent.kind === 183) {
                        return checkRightHandSideOfForOf(declaration.parent.parent.expression) || anyType;
                    }
                    if (ts.isBindingPattern(declaration.parent)) {
                        return getTypeForBindingElement(declaration);
                    }
                    if (declaration.type) {
                        return getTypeFromTypeNode(declaration.type);
                    }
                    if (declaration.kind === 128) {
                        var func = declaration.parent;
                        if (func.kind === 135 && !ts.hasDynamicName(func)) {
                            var getter = ts.getDeclarationOfKind(declaration.parent.symbol, 134);
                            if (getter) {
                                return getReturnTypeOfSignature(getSignatureFromDeclaration(getter));
                            }
                        }
                        var type = getContextuallyTypedParameterType(declaration);
                        if (type) {
                            return type;
                        }
                    }
                    if (declaration.initializer) {
                        return checkExpressionCached(declaration.initializer);
                    }
                    if (declaration.kind === 219) {
                        return checkIdentifier(declaration.name);
                    }
                    return undefined;
                }
                function getTypeFromBindingElement(element) {
                    if (element.initializer) {
                        return getWidenedType(checkExpressionCached(element.initializer));
                    }
                    if (ts.isBindingPattern(element.name)) {
                        return getTypeFromBindingPattern(element.name);
                    }
                    return anyType;
                }
                function getTypeFromObjectBindingPattern(pattern) {
                    var members = {};
                    ts.forEach(pattern.elements, function (e) {
                        var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0);
                        var name = e.propertyName || e.name;
                        var symbol = createSymbol(flags, name.text);
                        symbol.type = getTypeFromBindingElement(e);
                        members[symbol.name] = symbol;
                    });
                    return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
                }
                function getTypeFromArrayBindingPattern(pattern) {
                    var hasSpreadElement = false;
                    var elementTypes = [];
                    ts.forEach(pattern.elements, function (e) {
                        elementTypes.push(e.kind === 172 || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
                        if (e.dotDotDotToken) {
                            hasSpreadElement = true;
                        }
                    });
                    return !elementTypes.length ? anyArrayType : hasSpreadElement ? createArrayType(getUnionType(elementTypes)) : createTupleType(elementTypes);
                }
                function getTypeFromBindingPattern(pattern) {
                    return pattern.kind === 148 ? getTypeFromObjectBindingPattern(pattern) : getTypeFromArrayBindingPattern(pattern);
                }
                function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors) {
                    var type = getTypeForVariableLikeDeclaration(declaration);
                    if (type) {
                        if (reportErrors) {
                            reportErrorsFromWidening(declaration, type);
                        }
                        return declaration.kind !== 218 ? getWidenedType(type) : type;
                    }
                    if (ts.isBindingPattern(declaration.name)) {
                        return getTypeFromBindingPattern(declaration.name);
                    }
                    type = declaration.dotDotDotToken ? anyArrayType : anyType;
                    if (reportErrors && compilerOptions.noImplicitAny) {
                        var root = getRootDeclaration(declaration);
                        if (!isPrivateWithinAmbient(root) && !(root.kind === 128 && isPrivateWithinAmbient(root.parent))) {
                            reportImplicitAnyError(declaration, type);
                        }
                    }
                    return type;
                }
                function getTypeOfVariableOrParameterOrProperty(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        if (symbol.flags & 134217728) {
                            return links.type = getTypeOfPrototypeProperty(symbol);
                        }
                        var declaration = symbol.valueDeclaration;
                        if (declaration.parent.kind === 217) {
                            return links.type = anyType;
                        }
                        if (declaration.kind === 209) {
                            return links.type = checkExpression(declaration.expression);
                        }
                        links.type = resolvingType;
                        var type = getWidenedTypeForVariableLikeDeclaration(declaration, true);
                        if (links.type === resolvingType) {
                            links.type = type;
                        }
                    }
                    else if (links.type === resolvingType) {
                        links.type = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var diagnostic = symbol.valueDeclaration.type ? ts.Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation : ts.Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
                            error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
                        }
                    }
                    return links.type;
                }
                function getSetAccessorTypeAnnotationNode(accessor) {
                    return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
                }
                function getAnnotatedAccessorType(accessor) {
                    if (accessor) {
                        if (accessor.kind === 134) {
                            return accessor.type && getTypeFromTypeNode(accessor.type);
                        }
                        else {
                            var setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
                            return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
                        }
                    }
                    return undefined;
                }
                function getTypeOfAccessors(symbol) {
                    var links = getSymbolLinks(symbol);
                    checkAndStoreTypeOfAccessors(symbol, links);
                    return links.type;
                }
                function checkAndStoreTypeOfAccessors(symbol, links) {
                    links = links || getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = resolvingType;
                        var getter = ts.getDeclarationOfKind(symbol, 134);
                        var setter = ts.getDeclarationOfKind(symbol, 135);
                        var type;
                        var getterReturnType = getAnnotatedAccessorType(getter);
                        if (getterReturnType) {
                            type = getterReturnType;
                        }
                        else {
                            var setterParameterType = getAnnotatedAccessorType(setter);
                            if (setterParameterType) {
                                type = setterParameterType;
                            }
                            else {
                                if (getter && getter.body) {
                                    type = getReturnTypeFromBody(getter);
                                }
                                else {
                                    if (compilerOptions.noImplicitAny) {
                                        error(setter, ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
                                    }
                                    type = anyType;
                                }
                            }
                        }
                        if (links.type === resolvingType) {
                            links.type = type;
                        }
                    }
                    else if (links.type === resolvingType) {
                        links.type = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var getter = ts.getDeclarationOfKind(symbol, 134);
                            error(getter, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
                        }
                    }
                }
                function getTypeOfFuncClassEnumModule(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = createObjectType(32768, symbol);
                    }
                    return links.type;
                }
                function getTypeOfEnumMember(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol));
                    }
                    return links.type;
                }
                function getTypeOfAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = getTypeOfSymbol(resolveAlias(symbol));
                    }
                    return links.type;
                }
                function getTypeOfInstantiatedSymbol(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
                    }
                    return links.type;
                }
                function getTypeOfSymbol(symbol) {
                    if (symbol.flags & 16777216) {
                        return getTypeOfInstantiatedSymbol(symbol);
                    }
                    if (symbol.flags & (3 | 4)) {
                        return getTypeOfVariableOrParameterOrProperty(symbol);
                    }
                    if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) {
                        return getTypeOfFuncClassEnumModule(symbol);
                    }
                    if (symbol.flags & 8) {
                        return getTypeOfEnumMember(symbol);
                    }
                    if (symbol.flags & 98304) {
                        return getTypeOfAccessors(symbol);
                    }
                    if (symbol.flags & 8388608) {
                        return getTypeOfAlias(symbol);
                    }
                    return unknownType;
                }
                function getTargetType(type) {
                    return type.flags & 4096 ? type.target : type;
                }
                function hasBaseType(type, checkBase) {
                    return check(type);
                    function check(type) {
                        var target = getTargetType(type);
                        return target === checkBase || ts.forEach(target.baseTypes, check);
                    }
                }
                function getTypeParametersOfClassOrInterface(symbol) {
                    var result;
                    ts.forEach(symbol.declarations, function (node) {
                        if (node.kind === 197 || node.kind === 196) {
                            var declaration = node;
                            if (declaration.typeParameters && declaration.typeParameters.length) {
                                ts.forEach(declaration.typeParameters, function (node) {
                                    var tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
                                    if (!result) {
                                        result = [
                                            tp
                                        ];
                                    }
                                    else if (!ts.contains(result, tp)) {
                                        result.push(tp);
                                    }
                                });
                            }
                        }
                    });
                    return result;
                }
                function getDeclaredTypeOfClass(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = links.declaredType = createObjectType(1024, symbol);
                        var typeParameters = getTypeParametersOfClassOrInterface(symbol);
                        if (typeParameters) {
                            type.flags |= 4096;
                            type.typeParameters = typeParameters;
                            type.instantiations = {};
                            type.instantiations[getTypeListId(type.typeParameters)] = type;
                            type.target = type;
                            type.typeArguments = type.typeParameters;
                        }
                        type.baseTypes = [];
                        var declaration = ts.getDeclarationOfKind(symbol, 196);
                        var baseTypeNode = ts.getClassBaseTypeNode(declaration);
                        if (baseTypeNode) {
                            var baseType = getTypeFromTypeReferenceNode(baseTypeNode);
                            if (baseType !== unknownType) {
                                if (getTargetType(baseType).flags & 1024) {
                                    if (type !== baseType && !hasBaseType(baseType, type)) {
                                        type.baseTypes.push(baseType);
                                    }
                                    else {
                                        error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1));
                                    }
                                }
                                else {
                                    error(baseTypeNode, ts.Diagnostics.A_class_may_only_extend_another_class);
                                }
                            }
                        }
                        type.declaredProperties = getNamedMembers(symbol.members);
                        type.declaredCallSignatures = emptyArray;
                        type.declaredConstructSignatures = emptyArray;
                        type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, 0);
                        type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, 1);
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfInterface(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = links.declaredType = createObjectType(2048, symbol);
                        var typeParameters = getTypeParametersOfClassOrInterface(symbol);
                        if (typeParameters) {
                            type.flags |= 4096;
                            type.typeParameters = typeParameters;
                            type.instantiations = {};
                            type.instantiations[getTypeListId(type.typeParameters)] = type;
                            type.target = type;
                            type.typeArguments = type.typeParameters;
                        }
                        type.baseTypes = [];
                        ts.forEach(symbol.declarations, function (declaration) {
                            if (declaration.kind === 197 && ts.getInterfaceBaseTypeNodes(declaration)) {
                                ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), function (node) {
                                    var baseType = getTypeFromTypeReferenceNode(node);
                                    if (baseType !== unknownType) {
                                        if (getTargetType(baseType).flags & (1024 | 2048)) {
                                            if (type !== baseType && !hasBaseType(baseType, type)) {
                                                type.baseTypes.push(baseType);
                                            }
                                            else {
                                                error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1));
                                            }
                                        }
                                        else {
                                            error(node, ts.Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
                                        }
                                    }
                                });
                            }
                        });
                        type.declaredProperties = getNamedMembers(symbol.members);
                        type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]);
                        type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]);
                        type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, 0);
                        type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, 1);
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfTypeAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        links.declaredType = resolvingType;
                        var declaration = ts.getDeclarationOfKind(symbol, 198);
                        var type = getTypeFromTypeNode(declaration.type);
                        if (links.declaredType === resolvingType) {
                            links.declaredType = type;
                        }
                    }
                    else if (links.declaredType === resolvingType) {
                        links.declaredType = unknownType;
                        var declaration = ts.getDeclarationOfKind(symbol, 198);
                        error(declaration.name, ts.Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfEnum(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = createType(128);
                        type.symbol = symbol;
                        links.declaredType = type;
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfTypeParameter(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = createType(512);
                        type.symbol = symbol;
                        if (!ts.getDeclarationOfKind(symbol, 127).constraint) {
                            type.constraint = noConstraintType;
                        }
                        links.declaredType = type;
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol));
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfSymbol(symbol) {
                    ts.Debug.assert((symbol.flags & 16777216) === 0);
                    if (symbol.flags & 32) {
                        return getDeclaredTypeOfClass(symbol);
                    }
                    if (symbol.flags & 64) {
                        return getDeclaredTypeOfInterface(symbol);
                    }
                    if (symbol.flags & 524288) {
                        return getDeclaredTypeOfTypeAlias(symbol);
                    }
                    if (symbol.flags & 384) {
                        return getDeclaredTypeOfEnum(symbol);
                    }
                    if (symbol.flags & 262144) {
                        return getDeclaredTypeOfTypeParameter(symbol);
                    }
                    if (symbol.flags & 8388608) {
                        return getDeclaredTypeOfAlias(symbol);
                    }
                    return unknownType;
                }
                function createSymbolTable(symbols) {
                    var result = {};
                    for (var i = 0; i < symbols.length; i++) {
                        var symbol = symbols[i];
                        result[symbol.name] = symbol;
                    }
                    return result;
                }
                function createInstantiatedSymbolTable(symbols, mapper) {
                    var result = {};
                    for (var i = 0; i < symbols.length; i++) {
                        var symbol = symbols[i];
                        result[symbol.name] = instantiateSymbol(symbol, mapper);
                    }
                    return result;
                }
                function addInheritedMembers(symbols, baseSymbols) {
                    for (var i = 0; i < baseSymbols.length; i++) {
                        var s = baseSymbols[i];
                        if (!ts.hasProperty(symbols, s.name)) {
                            symbols[s.name] = s;
                        }
                    }
                }
                function addInheritedSignatures(signatures, baseSignatures) {
                    if (baseSignatures) {
                        for (var i = 0; i < baseSignatures.length; i++) {
                            signatures.push(baseSignatures[i]);
                        }
                    }
                }
                function resolveClassOrInterfaceMembers(type) {
                    var members = type.symbol.members;
                    var callSignatures = type.declaredCallSignatures;
                    var constructSignatures = type.declaredConstructSignatures;
                    var stringIndexType = type.declaredStringIndexType;
                    var numberIndexType = type.declaredNumberIndexType;
                    if (type.baseTypes.length) {
                        members = createSymbolTable(type.declaredProperties);
                        ts.forEach(type.baseTypes, function (baseType) {
                            addInheritedMembers(members, getPropertiesOfObjectType(baseType));
                            callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(baseType, 0));
                            constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(baseType, 1));
                            stringIndexType = stringIndexType || getIndexTypeOfType(baseType, 0);
                            numberIndexType = numberIndexType || getIndexTypeOfType(baseType, 1);
                        });
                    }
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveTypeReferenceMembers(type) {
                    var target = type.target;
                    var mapper = createTypeMapper(target.typeParameters, type.typeArguments);
                    var members = createInstantiatedSymbolTable(target.declaredProperties, mapper);
                    var callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature);
                    var constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
                    var stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
                    var numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
                    ts.forEach(target.baseTypes, function (baseType) {
                        var instantiatedBaseType = instantiateType(baseType, mapper);
                        addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
                        callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0));
                        constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1));
                        stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, 0);
                        numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, 1);
                    });
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function createSignature(declaration, typeParameters, parameters, resolvedReturnType, minArgumentCount, hasRestParameter, hasStringLiterals) {
                    var sig = new Signature(checker);
                    sig.declaration = declaration;
                    sig.typeParameters = typeParameters;
                    sig.parameters = parameters;
                    sig.resolvedReturnType = resolvedReturnType;
                    sig.minArgumentCount = minArgumentCount;
                    sig.hasRestParameter = hasRestParameter;
                    sig.hasStringLiterals = hasStringLiterals;
                    return sig;
                }
                function cloneSignature(sig) {
                    return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
                }
                function getDefaultConstructSignatures(classType) {
                    if (classType.baseTypes.length) {
                        var baseType = classType.baseTypes[0];
                        var baseSignatures = getSignaturesOfType(getTypeOfSymbol(baseType.symbol), 1);
                        return ts.map(baseSignatures, function (baseSignature) {
                            var signature = baseType.flags & 4096 ? getSignatureInstantiation(baseSignature, baseType.typeArguments) : cloneSignature(baseSignature);
                            signature.typeParameters = classType.typeParameters;
                            signature.resolvedReturnType = classType;
                            return signature;
                        });
                    }
                    return [
                        createSignature(undefined, classType.typeParameters, emptyArray, classType, 0, false, false)
                    ];
                }
                function createTupleTypeMemberSymbols(memberTypes) {
                    var members = {};
                    for (var i = 0; i < memberTypes.length; i++) {
                        var symbol = createSymbol(4 | 67108864, "" + i);
                        symbol.type = memberTypes[i];
                        members[i] = symbol;
                    }
                    return members;
                }
                function resolveTupleTypeMembers(type) {
                    var arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
                    var members = createTupleTypeMemberSymbols(type.elementTypes);
                    addInheritedMembers(members, arrayType.properties);
                    setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
                }
                function signatureListsIdentical(s, t) {
                    if (s.length !== t.length) {
                        return false;
                    }
                    for (var i = 0; i < s.length; i++) {
                        if (!compareSignatures(s[i], t[i], false, compareTypes)) {
                            return false;
                        }
                    }
                    return true;
                }
                function getUnionSignatures(types, kind) {
                    var signatureLists = ts.map(types, function (t) {
                        return getSignaturesOfType(t, kind);
                    });
                    var signatures = signatureLists[0];
                    for (var i = 0; i < signatures.length; i++) {
                        if (signatures[i].typeParameters) {
                            return emptyArray;
                        }
                    }
                    for (var i = 1; i < signatureLists.length; i++) {
                        if (!signatureListsIdentical(signatures, signatureLists[i])) {
                            return emptyArray;
                        }
                    }
                    var result = ts.map(signatures, cloneSignature);
                    for (var i = 0; i < result.length; i++) {
                        var s = result[i];
                        s.resolvedReturnType = undefined;
                        s.unionSignatures = ts.map(signatureLists, function (signatures) {
                            return signatures[i];
                        });
                    }
                    return result;
                }
                function getUnionIndexType(types, kind) {
                    var indexTypes = [];
                    for (var i = 0; i < types.length; i++) {
                        var indexType = getIndexTypeOfType(types[i], kind);
                        if (!indexType) {
                            return undefined;
                        }
                        indexTypes.push(indexType);
                    }
                    return getUnionType(indexTypes);
                }
                function resolveUnionTypeMembers(type) {
                    var callSignatures = getUnionSignatures(type.types, 0);
                    var constructSignatures = getUnionSignatures(type.types, 1);
                    var stringIndexType = getUnionIndexType(type.types, 0);
                    var numberIndexType = getUnionIndexType(type.types, 1);
                    setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveAnonymousTypeMembers(type) {
                    var symbol = type.symbol;
                    if (symbol.flags & 2048) {
                        var members = symbol.members;
                        var callSignatures = getSignaturesOfSymbol(members["__call"]);
                        var constructSignatures = getSignaturesOfSymbol(members["__new"]);
                        var stringIndexType = getIndexTypeOfSymbol(symbol, 0);
                        var numberIndexType = getIndexTypeOfSymbol(symbol, 1);
                    }
                    else {
                        var members = emptySymbols;
                        var callSignatures = emptyArray;
                        var constructSignatures = emptyArray;
                        if (symbol.flags & 1952) {
                            members = getExportsOfSymbol(symbol);
                        }
                        if (symbol.flags & (16 | 8192)) {
                            callSignatures = getSignaturesOfSymbol(symbol);
                        }
                        if (symbol.flags & 32) {
                            var classType = getDeclaredTypeOfClass(symbol);
                            constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
                            if (!constructSignatures.length) {
                                constructSignatures = getDefaultConstructSignatures(classType);
                            }
                            if (classType.baseTypes.length) {
                                members = createSymbolTable(getNamedMembers(members));
                                addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(classType.baseTypes[0].symbol)));
                            }
                        }
                        var stringIndexType = undefined;
                        var numberIndexType = (symbol.flags & 384) ? stringType : undefined;
                    }
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveObjectOrUnionTypeMembers(type) {
                    if (!type.members) {
                        if (type.flags & (1024 | 2048)) {
                            resolveClassOrInterfaceMembers(type);
                        }
                        else if (type.flags & 32768) {
                            resolveAnonymousTypeMembers(type);
                        }
                        else if (type.flags & 8192) {
                            resolveTupleTypeMembers(type);
                        }
                        else if (type.flags & 16384) {
                            resolveUnionTypeMembers(type);
                        }
                        else {
                            resolveTypeReferenceMembers(type);
                        }
                    }
                    return type;
                }
                function getPropertiesOfObjectType(type) {
                    if (type.flags & 48128) {
                        return resolveObjectOrUnionTypeMembers(type).properties;
                    }
                    return emptyArray;
                }
                function getPropertyOfObjectType(type, name) {
                    if (type.flags & 48128) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (ts.hasProperty(resolved.members, name)) {
                            var symbol = resolved.members[name];
                            if (symbolIsValue(symbol)) {
                                return symbol;
                            }
                        }
                    }
                }
                function getPropertiesOfUnionType(type) {
                    var result = [];
                    ts.forEach(getPropertiesOfType(type.types[0]), function (prop) {
                        var unionProp = getPropertyOfUnionType(type, prop.name);
                        if (unionProp) {
                            result.push(unionProp);
                        }
                    });
                    return result;
                }
                function getPropertiesOfType(type) {
                    if (type.flags & 16384) {
                        return getPropertiesOfUnionType(type);
                    }
                    return getPropertiesOfObjectType(getApparentType(type));
                }
                function getApparentType(type) {
                    if (type.flags & 512) {
                        do {
                            type = getConstraintOfTypeParameter(type);
                        } while (type && type.flags & 512);
                        if (!type) {
                            type = emptyObjectType;
                        }
                    }
                    if (type.flags & 258) {
                        type = globalStringType;
                    }
                    else if (type.flags & 132) {
                        type = globalNumberType;
                    }
                    else if (type.flags & 8) {
                        type = globalBooleanType;
                    }
                    else if (type.flags & 1048576) {
                        type = globalESSymbolType;
                    }
                    return type;
                }
                function createUnionProperty(unionType, name) {
                    var types = unionType.types;
                    var props;
                    for (var i = 0; i < types.length; i++) {
                        var type = getApparentType(types[i]);
                        if (type !== unknownType) {
                            var prop = getPropertyOfType(type, name);
                            if (!prop) {
                                return undefined;
                            }
                            if (!props) {
                                props = [
                                    prop
                                ];
                            }
                            else {
                                props.push(prop);
                            }
                        }
                    }
                    var propTypes = [];
                    var declarations = [];
                    for (var i = 0; i < props.length; i++) {
                        var prop = props[i];
                        if (prop.declarations) {
                            declarations.push.apply(declarations, prop.declarations);
                        }
                        propTypes.push(getTypeOfSymbol(prop));
                    }
                    var result = createSymbol(4 | 67108864 | 268435456, name);
                    result.unionType = unionType;
                    result.declarations = declarations;
                    result.type = getUnionType(propTypes);
                    return result;
                }
                function getPropertyOfUnionType(type, name) {
                    var properties = type.resolvedProperties || (type.resolvedProperties = {});
                    if (ts.hasProperty(properties, name)) {
                        return properties[name];
                    }
                    var property = createUnionProperty(type, name);
                    if (property) {
                        properties[name] = property;
                    }
                    return property;
                }
                function getPropertyOfType(type, name) {
                    if (type.flags & 16384) {
                        return getPropertyOfUnionType(type, name);
                    }
                    if (!(type.flags & 48128)) {
                        type = getApparentType(type);
                        if (!(type.flags & 48128)) {
                            return undefined;
                        }
                    }
                    var resolved = resolveObjectOrUnionTypeMembers(type);
                    if (ts.hasProperty(resolved.members, name)) {
                        var symbol = resolved.members[name];
                        if (symbolIsValue(symbol)) {
                            return symbol;
                        }
                    }
                    if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
                        var symbol = getPropertyOfObjectType(globalFunctionType, name);
                        if (symbol)
                            return symbol;
                    }
                    return getPropertyOfObjectType(globalObjectType, name);
                }
                function getSignaturesOfObjectOrUnionType(type, kind) {
                    if (type.flags & (48128 | 16384)) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        return kind === 0 ? resolved.callSignatures : resolved.constructSignatures;
                    }
                    return emptyArray;
                }
                function getSignaturesOfType(type, kind) {
                    return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
                }
                function getIndexTypeOfObjectOrUnionType(type, kind) {
                    if (type.flags & (48128 | 16384)) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        return kind === 0 ? resolved.stringIndexType : resolved.numberIndexType;
                    }
                }
                function getIndexTypeOfType(type, kind) {
                    return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
                }
                function getTypeParametersFromDeclaration(typeParameterDeclarations) {
                    var result = [];
                    ts.forEach(typeParameterDeclarations, function (node) {
                        var tp = getDeclaredTypeOfTypeParameter(node.symbol);
                        if (!ts.contains(result, tp)) {
                            result.push(tp);
                        }
                    });
                    return result;
                }
                function getExportsOfExternalModule(node) {
                    if (!node.moduleSpecifier) {
                        return emptyArray;
                    }
                    var module = resolveExternalModuleName(node, node.moduleSpecifier);
                    if (!module || !module.exports) {
                        return emptyArray;
                    }
                    return ts.mapToArray(getExportsOfModule(module));
                }
                function getSignatureFromDeclaration(declaration) {
                    var links = getNodeLinks(declaration);
                    if (!links.resolvedSignature) {
                        var classType = declaration.kind === 133 ? getDeclaredTypeOfClass(declaration.parent.symbol) : undefined;
                        var typeParameters = classType ? classType.typeParameters : declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
                        var parameters = [];
                        var hasStringLiterals = false;
                        var minArgumentCount = -1;
                        for (var i = 0, n = declaration.parameters.length; i < n; i++) {
                            var param = declaration.parameters[i];
                            parameters.push(param.symbol);
                            if (param.type && param.type.kind === 8) {
                                hasStringLiterals = true;
                            }
                            if (minArgumentCount < 0) {
                                if (param.initializer || param.questionToken || param.dotDotDotToken) {
                                    minArgumentCount = i;
                                }
                            }
                        }
                        if (minArgumentCount < 0) {
                            minArgumentCount = declaration.parameters.length;
                        }
                        var returnType;
                        if (classType) {
                            returnType = classType;
                        }
                        else if (declaration.type) {
                            returnType = getTypeFromTypeNode(declaration.type);
                        }
                        else {
                            if (declaration.kind === 134 && !ts.hasDynamicName(declaration)) {
                                var setter = ts.getDeclarationOfKind(declaration.symbol, 135);
                                returnType = getAnnotatedAccessorType(setter);
                            }
                            if (!returnType && ts.nodeIsMissing(declaration.body)) {
                                returnType = anyType;
                            }
                        }
                        links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, ts.hasRestParameters(declaration), hasStringLiterals);
                    }
                    return links.resolvedSignature;
                }
                function getSignaturesOfSymbol(symbol) {
                    if (!symbol)
                        return emptyArray;
                    var result = [];
                    for (var i = 0, len = symbol.declarations.length; i < len; i++) {
                        var node = symbol.declarations[i];
                        switch (node.kind) {
                            case 140:
                            case 141:
                            case 195:
                            case 132:
                            case 131:
                            case 133:
                            case 136:
                            case 137:
                            case 138:
                            case 134:
                            case 135:
                            case 160:
                            case 161:
                                if (i > 0 && node.body) {
                                    var previous = symbol.declarations[i - 1];
                                    if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) {
                                        break;
                                    }
                                }
                                result.push(getSignatureFromDeclaration(node));
                        }
                    }
                    return result;
                }
                function getReturnTypeOfSignature(signature) {
                    if (!signature.resolvedReturnType) {
                        signature.resolvedReturnType = resolvingType;
                        if (signature.target) {
                            var type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
                        }
                        else if (signature.unionSignatures) {
                            var type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature));
                        }
                        else {
                            var type = getReturnTypeFromBody(signature.declaration);
                        }
                        if (signature.resolvedReturnType === resolvingType) {
                            signature.resolvedReturnType = type;
                        }
                    }
                    else if (signature.resolvedReturnType === resolvingType) {
                        signature.resolvedReturnType = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var declaration = signature.declaration;
                            if (declaration.name) {
                                error(declaration.name, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, ts.declarationNameToString(declaration.name));
                            }
                            else {
                                error(declaration, ts.Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
                            }
                        }
                    }
                    return signature.resolvedReturnType;
                }
                function getRestTypeOfSignature(signature) {
                    if (signature.hasRestParameter) {
                        var type = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
                        if (type.flags & 4096 && type.target === globalArrayType) {
                            return type.typeArguments[0];
                        }
                    }
                    return anyType;
                }
                function getSignatureInstantiation(signature, typeArguments) {
                    return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true);
                }
                function getErasedSignature(signature) {
                    if (!signature.typeParameters)
                        return signature;
                    if (!signature.erasedSignatureCache) {
                        if (signature.target) {
                            signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper);
                        }
                        else {
                            signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true);
                        }
                    }
                    return signature.erasedSignatureCache;
                }
                function getOrCreateTypeFromSignature(signature) {
                    if (!signature.isolatedSignatureType) {
                        var isConstructor = signature.declaration.kind === 133 || signature.declaration.kind === 137;
                        var type = createObjectType(32768 | 65536);
                        type.members = emptySymbols;
                        type.properties = emptyArray;
                        type.callSignatures = !isConstructor ? [
                            signature
                        ] : emptyArray;
                        type.constructSignatures = isConstructor ? [
                            signature
                        ] : emptyArray;
                        signature.isolatedSignatureType = type;
                    }
                    return signature.isolatedSignatureType;
                }
                function getIndexSymbol(symbol) {
                    return symbol.members["__index"];
                }
                function getIndexDeclarationOfSymbol(symbol, kind) {
                    var syntaxKind = kind === 1 ? 118 : 120;
                    var indexSymbol = getIndexSymbol(symbol);
                    if (indexSymbol) {
                        var len = indexSymbol.declarations.length;
                        for (var i = 0; i < len; i++) {
                            var node = indexSymbol.declarations[i];
                            if (node.parameters.length === 1) {
                                var parameter = node.parameters[0];
                                if (parameter && parameter.type && parameter.type.kind === syntaxKind) {
                                    return node;
                                }
                            }
                        }
                    }
                    return undefined;
                }
                function getIndexTypeOfSymbol(symbol, kind) {
                    var declaration = getIndexDeclarationOfSymbol(symbol, kind);
                    return declaration ? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType : undefined;
                }
                function getConstraintOfTypeParameter(type) {
                    if (!type.constraint) {
                        if (type.target) {
                            var targetConstraint = getConstraintOfTypeParameter(type.target);
                            type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
                        }
                        else {
                            type.constraint = getTypeFromTypeNode(ts.getDeclarationOfKind(type.symbol, 127).constraint);
                        }
                    }
                    return type.constraint === noConstraintType ? undefined : type.constraint;
                }
                function getTypeListId(types) {
                    switch (types.length) {
                        case 1:
                            return "" + types[0].id;
                        case 2:
                            return types[0].id + "," + types[1].id;
                        default:
                            var result = "";
                            for (var i = 0; i < types.length; i++) {
                                if (i > 0)
                                    result += ",";
                                result += types[i].id;
                            }
                            return result;
                    }
                }
                function getWideningFlagsOfTypes(types) {
                    var result = 0;
                    for (var i = 0; i < types.length; i++) {
                        result |= types[i].flags;
                    }
                    return result & 786432;
                }
                function createTypeReference(target, typeArguments) {
                    var id = getTypeListId(typeArguments);
                    var type = target.instantiations[id];
                    if (!type) {
                        var flags = 4096 | getWideningFlagsOfTypes(typeArguments);
                        type = target.instantiations[id] = createObjectType(flags, target.symbol);
                        type.target = target;
                        type.typeArguments = typeArguments;
                    }
                    return type;
                }
                function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode, typeParameterSymbol) {
                    var links = getNodeLinks(typeReferenceNode);
                    if (links.isIllegalTypeReferenceInConstraint !== undefined) {
                        return links.isIllegalTypeReferenceInConstraint;
                    }
                    var currentNode = typeReferenceNode;
                    while (!ts.forEach(typeParameterSymbol.declarations, function (d) {
                        return d.parent === currentNode.parent;
                    })) {
                        currentNode = currentNode.parent;
                    }
                    links.isIllegalTypeReferenceInConstraint = currentNode.kind === 127;
                    return links.isIllegalTypeReferenceInConstraint;
                }
                function checkTypeParameterHasIllegalReferencesInConstraint(typeParameter) {
                    var typeParameterSymbol;
                    function check(n) {
                        if (n.kind === 139 && n.typeName.kind === 64) {
                            var links = getNodeLinks(n);
                            if (links.isIllegalTypeReferenceInConstraint === undefined) {
                                var symbol = resolveName(typeParameter, n.typeName.text, 793056, undefined, undefined);
                                if (symbol && (symbol.flags & 262144)) {
                                    links.isIllegalTypeReferenceInConstraint = ts.forEach(symbol.declarations, function (d) {
                                        return d.parent == typeParameter.parent;
                                    });
                                }
                            }
                            if (links.isIllegalTypeReferenceInConstraint) {
                                error(typeParameter, ts.Diagnostics.Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list);
                            }
                        }
                        ts.forEachChild(n, check);
                    }
                    if (typeParameter.constraint) {
                        typeParameterSymbol = getSymbolOfNode(typeParameter);
                        check(typeParameter.constraint);
                    }
                }
                function getTypeFromTypeReferenceNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        var symbol = resolveEntityName(node.typeName, 793056);
                        if (symbol) {
                            var type;
                            if ((symbol.flags & 262144) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
                                type = unknownType;
                            }
                            else {
                                type = getDeclaredTypeOfSymbol(symbol);
                                if (type.flags & (1024 | 2048) && type.flags & 4096) {
                                    var typeParameters = type.typeParameters;
                                    if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
                                        type = createTypeReference(type, ts.map(node.typeArguments, getTypeFromTypeNode));
                                    }
                                    else {
                                        error(node, ts.Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, undefined, 1), typeParameters.length);
                                        type = undefined;
                                    }
                                }
                                else {
                                    if (node.typeArguments) {
                                        error(node, ts.Diagnostics.Type_0_is_not_generic, typeToString(type));
                                        type = undefined;
                                    }
                                }
                            }
                        }
                        links.resolvedType = type || unknownType;
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeQueryNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = getWidenedType(checkExpressionOrQualifiedName(node.exprName));
                    }
                    return links.resolvedType;
                }
                function getTypeOfGlobalSymbol(symbol, arity) {
                    function getTypeDeclaration(symbol) {
                        var declarations = symbol.declarations;
                        for (var i = 0; i < declarations.length; i++) {
                            var declaration = declarations[i];
                            switch (declaration.kind) {
                                case 196:
                                case 197:
                                case 199:
                                    return declaration;
                            }
                        }
                    }
                    if (!symbol) {
                        return emptyObjectType;
                    }
                    var type = getDeclaredTypeOfSymbol(symbol);
                    if (!(type.flags & 48128)) {
                        error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name);
                        return emptyObjectType;
                    }
                    if ((type.typeParameters ? type.typeParameters.length : 0) !== arity) {
                        error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbol.name, arity);
                        return emptyObjectType;
                    }
                    return type;
                }
                function getGlobalValueSymbol(name) {
                    return getGlobalSymbol(name, 107455, ts.Diagnostics.Cannot_find_global_value_0);
                }
                function getGlobalTypeSymbol(name) {
                    return getGlobalSymbol(name, 793056, ts.Diagnostics.Cannot_find_global_type_0);
                }
                function getGlobalSymbol(name, meaning, diagnostic) {
                    return resolveName(undefined, name, meaning, diagnostic, name);
                }
                function getGlobalType(name, arity) {
                    if (arity === void 0) { arity = 0; }
                    return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
                }
                function getGlobalESSymbolConstructorSymbol() {
                    return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
                }
                function createArrayType(elementType) {
                    var arrayType = globalArrayType || getDeclaredTypeOfSymbol(globalArraySymbol);
                    return arrayType !== emptyObjectType ? createTypeReference(arrayType, [
                        elementType
                    ]) : emptyObjectType;
                }
                function getTypeFromArrayTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
                    }
                    return links.resolvedType;
                }
                function createTupleType(elementTypes) {
                    var id = getTypeListId(elementTypes);
                    var type = tupleTypes[id];
                    if (!type) {
                        type = tupleTypes[id] = createObjectType(8192);
                        type.elementTypes = elementTypes;
                    }
                    return type;
                }
                function getTypeFromTupleTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNode));
                    }
                    return links.resolvedType;
                }
                function addTypeToSortedSet(sortedSet, type) {
                    if (type.flags & 16384) {
                        addTypesToSortedSet(sortedSet, type.types);
                    }
                    else {
                        var i = 0;
                        var id = type.id;
                        while (i < sortedSet.length && sortedSet[i].id < id) {
                            i++;
                        }
                        if (i === sortedSet.length || sortedSet[i].id !== id) {
                            sortedSet.splice(i, 0, type);
                        }
                    }
                }
                function addTypesToSortedSet(sortedTypes, types) {
                    for (var i = 0, len = types.length; i < len; i++) {
                        addTypeToSortedSet(sortedTypes, types[i]);
                    }
                }
                function isSubtypeOfAny(candidate, types) {
                    for (var i = 0, len = types.length; i < len; i++) {
                        if (candidate !== types[i] && isTypeSubtypeOf(candidate, types[i])) {
                            return true;
                        }
                    }
                    return false;
                }
                function removeSubtypes(types) {
                    var i = types.length;
                    while (i > 0) {
                        i--;
                        if (isSubtypeOfAny(types[i], types)) {
                            types.splice(i, 1);
                        }
                    }
                }
                function containsAnyType(types) {
                    for (var i = 0; i < types.length; i++) {
                        if (types[i].flags & 1) {
                            return true;
                        }
                    }
                    return false;
                }
                function removeAllButLast(types, typeToRemove) {
                    var i = types.length;
                    while (i > 0 && types.length > 1) {
                        i--;
                        if (types[i] === typeToRemove) {
                            types.splice(i, 1);
                        }
                    }
                }
                function getUnionType(types, noSubtypeReduction) {
                    if (types.length === 0) {
                        return emptyObjectType;
                    }
                    var sortedTypes = [];
                    addTypesToSortedSet(sortedTypes, types);
                    if (noSubtypeReduction) {
                        if (containsAnyType(sortedTypes)) {
                            return anyType;
                        }
                        removeAllButLast(sortedTypes, undefinedType);
                        removeAllButLast(sortedTypes, nullType);
                    }
                    else {
                        removeSubtypes(sortedTypes);
                    }
                    if (sortedTypes.length === 1) {
                        return sortedTypes[0];
                    }
                    var id = getTypeListId(sortedTypes);
                    var type = unionTypes[id];
                    if (!type) {
                        type = unionTypes[id] = createObjectType(16384 | getWideningFlagsOfTypes(sortedTypes));
                        type.types = sortedTypes;
                    }
                    return type;
                }
                function getTypeFromUnionTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), true);
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = createObjectType(32768, node.symbol);
                    }
                    return links.resolvedType;
                }
                function getStringLiteralType(node) {
                    if (ts.hasProperty(stringLiteralTypes, node.text)) {
                        return stringLiteralTypes[node.text];
                    }
                    var type = stringLiteralTypes[node.text] = createType(256);
                    type.text = ts.getTextOfNode(node);
                    return type;
                }
                function getTypeFromStringLiteral(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = getStringLiteralType(node);
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeNode(node) {
                    switch (node.kind) {
                        case 111:
                            return anyType;
                        case 120:
                            return stringType;
                        case 118:
                            return numberType;
                        case 112:
                            return booleanType;
                        case 121:
                            return esSymbolType;
                        case 98:
                            return voidType;
                        case 8:
                            return getTypeFromStringLiteral(node);
                        case 139:
                            return getTypeFromTypeReferenceNode(node);
                        case 142:
                            return getTypeFromTypeQueryNode(node);
                        case 144:
                            return getTypeFromArrayTypeNode(node);
                        case 145:
                            return getTypeFromTupleTypeNode(node);
                        case 146:
                            return getTypeFromUnionTypeNode(node);
                        case 147:
                            return getTypeFromTypeNode(node.type);
                        case 140:
                        case 141:
                        case 143:
                            return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
                        case 64:
                        case 125:
                            var symbol = getSymbolInfo(node);
                            return symbol && getDeclaredTypeOfSymbol(symbol);
                        default:
                            return unknownType;
                    }
                }
                function instantiateList(items, mapper, instantiator) {
                    if (items && items.length) {
                        var result = [];
                        for (var i = 0; i < items.length; i++) {
                            result.push(instantiator(items[i], mapper));
                        }
                        return result;
                    }
                    return items;
                }
                function createUnaryTypeMapper(source, target) {
                    return function (t) {
                        return t === source ? target : t;
                    };
                }
                function createBinaryTypeMapper(source1, target1, source2, target2) {
                    return function (t) {
                        return t === source1 ? target1 : t === source2 ? target2 : t;
                    };
                }
                function createTypeMapper(sources, targets) {
                    switch (sources.length) {
                        case 1:
                            return createUnaryTypeMapper(sources[0], targets[0]);
                        case 2:
                            return createBinaryTypeMapper(sources[0], targets[0], sources[1], targets[1]);
                    }
                    return function (t) {
                        for (var i = 0; i < sources.length; i++) {
                            if (t === sources[i])
                                return targets[i];
                        }
                        return t;
                    };
                }
                function createUnaryTypeEraser(source) {
                    return function (t) {
                        return t === source ? anyType : t;
                    };
                }
                function createBinaryTypeEraser(source1, source2) {
                    return function (t) {
                        return t === source1 || t === source2 ? anyType : t;
                    };
                }
                function createTypeEraser(sources) {
                    switch (sources.length) {
                        case 1:
                            return createUnaryTypeEraser(sources[0]);
                        case 2:
                            return createBinaryTypeEraser(sources[0], sources[1]);
                    }
                    return function (t) {
                        for (var i = 0; i < sources.length; i++) {
                            if (t === sources[i])
                                return anyType;
                        }
                        return t;
                    };
                }
                function createInferenceMapper(context) {
                    return function (t) {
                        for (var i = 0; i < context.typeParameters.length; i++) {
                            if (t === context.typeParameters[i]) {
                                return getInferredType(context, i);
                            }
                        }
                        return t;
                    };
                }
                function identityMapper(type) {
                    return type;
                }
                function combineTypeMappers(mapper1, mapper2) {
                    return function (t) {
                        return mapper2(mapper1(t));
                    };
                }
                function instantiateTypeParameter(typeParameter, mapper) {
                    var result = createType(512);
                    result.symbol = typeParameter.symbol;
                    if (typeParameter.constraint) {
                        result.constraint = instantiateType(typeParameter.constraint, mapper);
                    }
                    else {
                        result.target = typeParameter;
                        result.mapper = mapper;
                    }
                    return result;
                }
                function instantiateSignature(signature, mapper, eraseTypeParameters) {
                    if (signature.typeParameters && !eraseTypeParameters) {
                        var freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
                        mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
                    }
                    var result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
                    result.target = signature;
                    result.mapper = mapper;
                    return result;
                }
                function instantiateSymbol(symbol, mapper) {
                    if (symbol.flags & 16777216) {
                        var links = getSymbolLinks(symbol);
                        symbol = links.target;
                        mapper = combineTypeMappers(links.mapper, mapper);
                    }
                    var result = createSymbol(16777216 | 67108864 | symbol.flags, symbol.name);
                    result.declarations = symbol.declarations;
                    result.parent = symbol.parent;
                    result.target = symbol;
                    result.mapper = mapper;
                    if (symbol.valueDeclaration) {
                        result.valueDeclaration = symbol.valueDeclaration;
                    }
                    return result;
                }
                function instantiateAnonymousType(type, mapper) {
                    var result = createObjectType(32768, type.symbol);
                    result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
                    result.members = createSymbolTable(result.properties);
                    result.callSignatures = instantiateList(getSignaturesOfType(type, 0), mapper, instantiateSignature);
                    result.constructSignatures = instantiateList(getSignaturesOfType(type, 1), mapper, instantiateSignature);
                    var stringIndexType = getIndexTypeOfType(type, 0);
                    var numberIndexType = getIndexTypeOfType(type, 1);
                    if (stringIndexType)
                        result.stringIndexType = instantiateType(stringIndexType, mapper);
                    if (numberIndexType)
                        result.numberIndexType = instantiateType(numberIndexType, mapper);
                    return result;
                }
                function instantiateType(type, mapper) {
                    if (mapper !== identityMapper) {
                        if (type.flags & 512) {
                            return mapper(type);
                        }
                        if (type.flags & 32768) {
                            return type.symbol && type.symbol.flags & (16 | 8192 | 2048 | 4096) ? instantiateAnonymousType(type, mapper) : type;
                        }
                        if (type.flags & 4096) {
                            return createTypeReference(type.target, instantiateList(type.typeArguments, mapper, instantiateType));
                        }
                        if (type.flags & 8192) {
                            return createTupleType(instantiateList(type.elementTypes, mapper, instantiateType));
                        }
                        if (type.flags & 16384) {
                            return getUnionType(instantiateList(type.types, mapper, instantiateType), true);
                        }
                    }
                    return type;
                }
                function isContextSensitive(node) {
                    ts.Debug.assert(node.kind !== 132 || ts.isObjectLiteralMethod(node));
                    switch (node.kind) {
                        case 160:
                        case 161:
                            return isContextSensitiveFunctionLikeDeclaration(node);
                        case 152:
                            return ts.forEach(node.properties, isContextSensitive);
                        case 151:
                            return ts.forEach(node.elements, isContextSensitive);
                        case 168:
                            return isContextSensitive(node.whenTrue) || isContextSensitive(node.whenFalse);
                        case 167:
                            return node.operatorToken.kind === 49 && (isContextSensitive(node.left) || isContextSensitive(node.right));
                        case 218:
                            return isContextSensitive(node.initializer);
                        case 132:
                        case 131:
                            return isContextSensitiveFunctionLikeDeclaration(node);
                        case 159:
                            return isContextSensitive(node.expression);
                    }
                    return false;
                }
                function isContextSensitiveFunctionLikeDeclaration(node) {
                    return !node.typeParameters && node.parameters.length && !ts.forEach(node.parameters, function (p) {
                        return p.type;
                    });
                }
                function getTypeWithoutConstructors(type) {
                    if (type.flags & 48128) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (resolved.constructSignatures.length) {
                            var result = createObjectType(32768, type.symbol);
                            result.members = resolved.members;
                            result.properties = resolved.properties;
                            result.callSignatures = resolved.callSignatures;
                            result.constructSignatures = emptyArray;
                            type = result;
                        }
                    }
                    return type;
                }
                var subtypeRelation = {};
                var assignableRelation = {};
                var identityRelation = {};
                function isTypeIdenticalTo(source, target) {
                    return checkTypeRelatedTo(source, target, identityRelation, undefined);
                }
                function compareTypes(source, target) {
                    return checkTypeRelatedTo(source, target, identityRelation, undefined) ? -1 : 0;
                }
                function isTypeSubtypeOf(source, target) {
                    return checkTypeSubtypeOf(source, target, undefined);
                }
                function isTypeAssignableTo(source, target) {
                    return checkTypeAssignableTo(source, target, undefined);
                }
                function checkTypeSubtypeOf(source, target, errorNode, headMessage, containingMessageChain) {
                    return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
                }
                function checkTypeAssignableTo(source, target, errorNode, headMessage) {
                    return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage);
                }
                function isSignatureAssignableTo(source, target) {
                    var sourceType = getOrCreateTypeFromSignature(source);
                    var targetType = getOrCreateTypeFromSignature(target);
                    return checkTypeRelatedTo(sourceType, targetType, assignableRelation, undefined);
                }
                function checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain) {
                    var errorInfo;
                    var sourceStack;
                    var targetStack;
                    var maybeStack;
                    var expandingFlags;
                    var depth = 0;
                    var overflow = false;
                    ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
                    var result = isRelatedTo(source, target, errorNode !== undefined, headMessage);
                    if (overflow) {
                        error(errorNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
                    }
                    else if (errorInfo) {
                        if (errorInfo.next === undefined) {
                            errorInfo = undefined;
                            isRelatedTo(source, target, errorNode !== undefined, headMessage, true);
                        }
                        if (containingMessageChain) {
                            errorInfo = ts.concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
                        }
                        diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
                    }
                    return result !== 0;
                    function reportError(message, arg0, arg1, arg2) {
                        errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
                    }
                    function isRelatedTo(source, target, reportErrors, headMessage, elaborateErrors) {
                        if (elaborateErrors === void 0) { elaborateErrors = false; }
                        var result;
                        if (source === target)
                            return -1;
                        if (relation !== identityRelation) {
                            if (target.flags & 1)
                                return -1;
                            if (source === undefinedType)
                                return -1;
                            if (source === nullType && target !== undefinedType)
                                return -1;
                            if (source.flags & 128 && target === numberType)
                                return -1;
                            if (source.flags & 256 && target === stringType)
                                return -1;
                            if (relation === assignableRelation) {
                                if (source.flags & 1)
                                    return -1;
                                if (source === numberType && target.flags & 128)
                                    return -1;
                            }
                        }
                        if (source.flags & 16384 || target.flags & 16384) {
                            if (relation === identityRelation) {
                                if (source.flags & 16384 && target.flags & 16384) {
                                    if (result = unionTypeRelatedToUnionType(source, target)) {
                                        if (result &= unionTypeRelatedToUnionType(target, source)) {
                                            return result;
                                        }
                                    }
                                }
                                else if (source.flags & 16384) {
                                    if (result = unionTypeRelatedToType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                                else {
                                    if (result = unionTypeRelatedToType(target, source, reportErrors)) {
                                        return result;
                                    }
                                }
                            }
                            else {
                                if (source.flags & 16384) {
                                    if (result = unionTypeRelatedToType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                                else {
                                    if (result = typeRelatedToUnionType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                            }
                        }
                        else if (source.flags & 512 && target.flags & 512) {
                            if (result = typeParameterRelatedTo(source, target, reportErrors)) {
                                return result;
                            }
                        }
                        else {
                            var saveErrorInfo = errorInfo;
                            if (source.flags & 4096 && target.flags & 4096 && source.target === target.target) {
                                if (result = typesRelatedTo(source.typeArguments, target.typeArguments, reportErrors)) {
                                    return result;
                                }
                            }
                            var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
                            var sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
                            if (sourceOrApparentType.flags & 48128 && target.flags & 48128 && (result = objectTypeRelatedTo(sourceOrApparentType, target, reportStructuralErrors, elaborateErrors))) {
                                errorInfo = saveErrorInfo;
                                return result;
                            }
                        }
                        if (reportErrors) {
                            headMessage = headMessage || ts.Diagnostics.Type_0_is_not_assignable_to_type_1;
                            var sourceType = typeToString(source);
                            var targetType = typeToString(target);
                            if (sourceType === targetType) {
                                sourceType = typeToString(source, undefined, 128);
                                targetType = typeToString(target, undefined, 128);
                            }
                            reportError(headMessage, sourceType, targetType);
                        }
                        return 0;
                    }
                    function unionTypeRelatedToUnionType(source, target) {
                        var result = -1;
                        var sourceTypes = source.types;
                        for (var i = 0, len = sourceTypes.length; i < len; i++) {
                            var related = typeRelatedToUnionType(sourceTypes[i], target, false);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typeRelatedToUnionType(source, target, reportErrors) {
                        var targetTypes = target.types;
                        for (var i = 0, len = targetTypes.length; i < len; i++) {
                            var related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
                            if (related) {
                                return related;
                            }
                        }
                        return 0;
                    }
                    function unionTypeRelatedToType(source, target, reportErrors) {
                        var result = -1;
                        var sourceTypes = source.types;
                        for (var i = 0, len = sourceTypes.length; i < len; i++) {
                            var related = isRelatedTo(sourceTypes[i], target, reportErrors);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typesRelatedTo(sources, targets, reportErrors) {
                        var result = -1;
                        for (var i = 0, len = sources.length; i < len; i++) {
                            var related = isRelatedTo(sources[i], targets[i], reportErrors);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typeParameterRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            if (source.symbol.name !== target.symbol.name) {
                                return 0;
                            }
                            if (source.constraint === target.constraint) {
                                return -1;
                            }
                            if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
                                return 0;
                            }
                            return isRelatedTo(source.constraint, target.constraint, reportErrors);
                        }
                        else {
                            while (true) {
                                var constraint = getConstraintOfTypeParameter(source);
                                if (constraint === target)
                                    return -1;
                                if (!(constraint && constraint.flags & 512))
                                    break;
                                source = constraint;
                            }
                            return 0;
                        }
                    }
                    function objectTypeRelatedTo(source, target, reportErrors, elaborateErrors) {
                        if (elaborateErrors === void 0) { elaborateErrors = false; }
                        if (overflow) {
                            return 0;
                        }
                        var id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
                        var related = relation[id];
                        if (related !== undefined) {
                            if (!elaborateErrors || (related === 3)) {
                                return related === 1 ? -1 : 0;
                            }
                        }
                        if (depth > 0) {
                            for (var i = 0; i < depth; i++) {
                                if (maybeStack[i][id]) {
                                    return 1;
                                }
                            }
                            if (depth === 100) {
                                overflow = true;
                                return 0;
                            }
                        }
                        else {
                            sourceStack = [];
                            targetStack = [];
                            maybeStack = [];
                            expandingFlags = 0;
                        }
                        sourceStack[depth] = source;
                        targetStack[depth] = target;
                        maybeStack[depth] = {};
                        maybeStack[depth][id] = 1;
                        depth++;
                        var saveExpandingFlags = expandingFlags;
                        if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack))
                            expandingFlags |= 1;
                        if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack))
                            expandingFlags |= 2;
                        if (expandingFlags === 3) {
                            var result = 1;
                        }
                        else {
                            var result = propertiesRelatedTo(source, target, reportErrors);
                            if (result) {
                                result &= signaturesRelatedTo(source, target, 0, reportErrors);
                                if (result) {
                                    result &= signaturesRelatedTo(source, target, 1, reportErrors);
                                    if (result) {
                                        result &= stringIndexTypesRelatedTo(source, target, reportErrors);
                                        if (result) {
                                            result &= numberIndexTypesRelatedTo(source, target, reportErrors);
                                        }
                                    }
                                }
                            }
                        }
                        expandingFlags = saveExpandingFlags;
                        depth--;
                        if (result) {
                            var maybeCache = maybeStack[depth];
                            var destinationCache = (result === -1 || depth === 0) ? relation : maybeStack[depth - 1];
                            ts.copyMap(maybeCache, destinationCache);
                        }
                        else {
                            relation[id] = reportErrors ? 3 : 2;
                        }
                        return result;
                    }
                    function isDeeplyNestedGeneric(type, stack) {
                        if (type.flags & 4096 && depth >= 10) {
                            var target = type.target;
                            var count = 0;
                            for (var i = 0; i < depth; i++) {
                                var t = stack[i];
                                if (t.flags & 4096 && t.target === target) {
                                    count++;
                                    if (count >= 10)
                                        return true;
                                }
                            }
                        }
                        return false;
                    }
                    function propertiesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return propertiesIdenticalTo(source, target);
                        }
                        var result = -1;
                        var properties = getPropertiesOfObjectType(target);
                        var requireOptionalProperties = relation === subtypeRelation && !(source.flags & 131072);
                        for (var i = 0; i < properties.length; i++) {
                            var targetProp = properties[i];
                            var sourceProp = getPropertyOfType(source, targetProp.name);
                            if (sourceProp !== targetProp) {
                                if (!sourceProp) {
                                    if (!(targetProp.flags & 536870912) || requireOptionalProperties) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_missing_in_type_1, symbolToString(targetProp), typeToString(source));
                                        }
                                        return 0;
                                    }
                                }
                                else if (!(targetProp.flags & 134217728)) {
                                    var sourceFlags = getDeclarationFlagsFromSymbol(sourceProp);
                                    var targetFlags = getDeclarationFlagsFromSymbol(targetProp);
                                    if (sourceFlags & 32 || targetFlags & 32) {
                                        if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
                                            if (reportErrors) {
                                                if (sourceFlags & 32 && targetFlags & 32) {
                                                    reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
                                                }
                                                else {
                                                    reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourceFlags & 32 ? source : target), typeToString(sourceFlags & 32 ? target : source));
                                                }
                                            }
                                            return 0;
                                        }
                                    }
                                    else if (targetFlags & 64) {
                                        var sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & 32;
                                        var sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(sourceProp.parent) : undefined;
                                        var targetClass = getDeclaredTypeOfSymbol(targetProp.parent);
                                        if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
                                            if (reportErrors) {
                                                reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(sourceClass || source), typeToString(targetClass));
                                            }
                                            return 0;
                                        }
                                    }
                                    else if (sourceFlags & 64) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
                                        }
                                        return 0;
                                    }
                                    var related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
                                    if (!related) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
                                        }
                                        return 0;
                                    }
                                    result &= related;
                                    if (sourceProp.flags & 536870912 && !(targetProp.flags & 536870912)) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
                                        }
                                        return 0;
                                    }
                                }
                            }
                        }
                        return result;
                    }
                    function propertiesIdenticalTo(source, target) {
                        var sourceProperties = getPropertiesOfObjectType(source);
                        var targetProperties = getPropertiesOfObjectType(target);
                        if (sourceProperties.length !== targetProperties.length) {
                            return 0;
                        }
                        var result = -1;
                        for (var i = 0, len = sourceProperties.length; i < len; ++i) {
                            var sourceProp = sourceProperties[i];
                            var targetProp = getPropertyOfObjectType(target, sourceProp.name);
                            if (!targetProp) {
                                return 0;
                            }
                            var related = compareProperties(sourceProp, targetProp, isRelatedTo);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function signaturesRelatedTo(source, target, kind, reportErrors) {
                        if (relation === identityRelation) {
                            return signaturesIdenticalTo(source, target, kind);
                        }
                        if (target === anyFunctionType || source === anyFunctionType) {
                            return -1;
                        }
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        var result = -1;
                        var saveErrorInfo = errorInfo;
                        outer: for (var i = 0; i < targetSignatures.length; i++) {
                            var t = targetSignatures[i];
                            if (!t.hasStringLiterals || target.flags & 65536) {
                                var localErrors = reportErrors;
                                for (var j = 0; j < sourceSignatures.length; j++) {
                                    var s = sourceSignatures[j];
                                    if (!s.hasStringLiterals || source.flags & 65536) {
                                        var related = signatureRelatedTo(s, t, localErrors);
                                        if (related) {
                                            result &= related;
                                            errorInfo = saveErrorInfo;
                                            continue outer;
                                        }
                                        localErrors = false;
                                    }
                                }
                                return 0;
                            }
                        }
                        return result;
                    }
                    function signatureRelatedTo(source, target, reportErrors) {
                        if (source === target) {
                            return -1;
                        }
                        if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
                            return 0;
                        }
                        var sourceMax = source.parameters.length;
                        var targetMax = target.parameters.length;
                        var checkCount;
                        if (source.hasRestParameter && target.hasRestParameter) {
                            checkCount = sourceMax > targetMax ? sourceMax : targetMax;
                            sourceMax--;
                            targetMax--;
                        }
                        else if (source.hasRestParameter) {
                            sourceMax--;
                            checkCount = targetMax;
                        }
                        else if (target.hasRestParameter) {
                            targetMax--;
                            checkCount = sourceMax;
                        }
                        else {
                            checkCount = sourceMax < targetMax ? sourceMax : targetMax;
                        }
                        source = getErasedSignature(source);
                        target = getErasedSignature(target);
                        var result = -1;
                        for (var i = 0; i < checkCount; i++) {
                            var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
                            var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
                            var saveErrorInfo = errorInfo;
                            var related = isRelatedTo(s, t, reportErrors);
                            if (!related) {
                                related = isRelatedTo(t, s, false);
                                if (!related) {
                                    if (reportErrors) {
                                        reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name);
                                    }
                                    return 0;
                                }
                                errorInfo = saveErrorInfo;
                            }
                            result &= related;
                        }
                        var t = getReturnTypeOfSignature(target);
                        if (t === voidType)
                            return result;
                        var s = getReturnTypeOfSignature(source);
                        return result & isRelatedTo(s, t, reportErrors);
                    }
                    function signaturesIdenticalTo(source, target, kind) {
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        if (sourceSignatures.length !== targetSignatures.length) {
                            return 0;
                        }
                        var result = -1;
                        for (var i = 0, len = sourceSignatures.length; i < len; ++i) {
                            var related = compareSignatures(sourceSignatures[i], targetSignatures[i], true, isRelatedTo);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function stringIndexTypesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return indexTypesIdenticalTo(0, source, target);
                        }
                        var targetType = getIndexTypeOfType(target, 0);
                        if (targetType) {
                            var sourceType = getIndexTypeOfType(source, 0);
                            if (!sourceType) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
                                }
                                return 0;
                            }
                            var related = isRelatedTo(sourceType, targetType, reportErrors);
                            if (!related) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signatures_are_incompatible);
                                }
                                return 0;
                            }
                            return related;
                        }
                        return -1;
                    }
                    function numberIndexTypesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return indexTypesIdenticalTo(1, source, target);
                        }
                        var targetType = getIndexTypeOfType(target, 1);
                        if (targetType) {
                            var sourceStringType = getIndexTypeOfType(source, 0);
                            var sourceNumberType = getIndexTypeOfType(source, 1);
                            if (!(sourceStringType || sourceNumberType)) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
                                }
                                return 0;
                            }
                            if (sourceStringType && sourceNumberType) {
                                var related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
                            }
                            else {
                                var related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
                            }
                            if (!related) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signatures_are_incompatible);
                                }
                                return 0;
                            }
                            return related;
                        }
                        return -1;
                    }
                    function indexTypesIdenticalTo(indexKind, source, target) {
                        var targetType = getIndexTypeOfType(target, indexKind);
                        var sourceType = getIndexTypeOfType(source, indexKind);
                        if (!sourceType && !targetType) {
                            return -1;
                        }
                        if (sourceType && targetType) {
                            return isRelatedTo(sourceType, targetType);
                        }
                        return 0;
                    }
                }
                function isPropertyIdenticalTo(sourceProp, targetProp) {
                    return compareProperties(sourceProp, targetProp, compareTypes) !== 0;
                }
                function compareProperties(sourceProp, targetProp, compareTypes) {
                    if (sourceProp === targetProp) {
                        return -1;
                    }
                    var sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (32 | 64);
                    var targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (32 | 64);
                    if (sourcePropAccessibility !== targetPropAccessibility) {
                        return 0;
                    }
                    if (sourcePropAccessibility) {
                        if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
                            return 0;
                        }
                    }
                    else {
                        if ((sourceProp.flags & 536870912) !== (targetProp.flags & 536870912)) {
                            return 0;
                        }
                    }
                    return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
                }
                function compareSignatures(source, target, compareReturnTypes, compareTypes) {
                    if (source === target) {
                        return -1;
                    }
                    if (source.parameters.length !== target.parameters.length || source.minArgumentCount !== target.minArgumentCount || source.hasRestParameter !== target.hasRestParameter) {
                        return 0;
                    }
                    var result = -1;
                    if (source.typeParameters && target.typeParameters) {
                        if (source.typeParameters.length !== target.typeParameters.length) {
                            return 0;
                        }
                        for (var i = 0, len = source.typeParameters.length; i < len; ++i) {
                            var related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
                            if (!related) {
                                return 0;
                            }
                            result &= related;
                        }
                    }
                    else if (source.typeParameters || target.typeParameters) {
                        return 0;
                    }
                    source = getErasedSignature(source);
                    target = getErasedSignature(target);
                    for (var i = 0, len = source.parameters.length; i < len; i++) {
                        var s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
                        var t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
                        var related = compareTypes(s, t);
                        if (!related) {
                            return 0;
                        }
                        result &= related;
                    }
                    if (compareReturnTypes) {
                        result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
                    }
                    return result;
                }
                function isSupertypeOfEach(candidate, types) {
                    for (var i = 0, len = types.length; i < len; i++) {
                        if (candidate !== types[i] && !isTypeSubtypeOf(types[i], candidate))
                            return false;
                    }
                    return true;
                }
                function getCommonSupertype(types) {
                    return ts.forEach(types, function (t) {
                        return isSupertypeOfEach(t, types) ? t : undefined;
                    });
                }
                function reportNoCommonSupertypeError(types, errorLocation, errorMessageChainHead) {
                    var bestSupertype;
                    var bestSupertypeDownfallType;
                    var bestSupertypeScore = 0;
                    for (var i = 0; i < types.length; i++) {
                        var score = 0;
                        var downfallType = undefined;
                        for (var j = 0; j < types.length; j++) {
                            if (isTypeSubtypeOf(types[j], types[i])) {
                                score++;
                            }
                            else if (!downfallType) {
                                downfallType = types[j];
                            }
                        }
                        if (score > bestSupertypeScore) {
                            bestSupertype = types[i];
                            bestSupertypeDownfallType = downfallType;
                            bestSupertypeScore = score;
                        }
                        if (bestSupertypeScore === types.length - 1) {
                            break;
                        }
                    }
                    checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation, ts.Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0, errorMessageChainHead);
                }
                function isArrayType(type) {
                    return type.flags & 4096 && type.target === globalArrayType;
                }
                function isArrayLikeType(type) {
                    return !(type.flags & (32 | 64)) && isTypeAssignableTo(type, anyArrayType);
                }
                function isTupleLikeType(type) {
                    return !!getPropertyOfType(type, "0");
                }
                function isTupleType(type) {
                    return (type.flags & 8192) && !!type.elementTypes;
                }
                function getWidenedTypeOfObjectLiteral(type) {
                    var properties = getPropertiesOfObjectType(type);
                    var members = {};
                    ts.forEach(properties, function (p) {
                        var propType = getTypeOfSymbol(p);
                        var widenedType = getWidenedType(propType);
                        if (propType !== widenedType) {
                            var symbol = createSymbol(p.flags | 67108864, p.name);
                            symbol.declarations = p.declarations;
                            symbol.parent = p.parent;
                            symbol.type = widenedType;
                            symbol.target = p;
                            if (p.valueDeclaration)
                                symbol.valueDeclaration = p.valueDeclaration;
                            p = symbol;
                        }
                        members[p.name] = p;
                    });
                    var stringIndexType = getIndexTypeOfType(type, 0);
                    var numberIndexType = getIndexTypeOfType(type, 1);
                    if (stringIndexType)
                        stringIndexType = getWidenedType(stringIndexType);
                    if (numberIndexType)
                        numberIndexType = getWidenedType(numberIndexType);
                    return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
                }
                function getWidenedType(type) {
                    if (type.flags & 786432) {
                        if (type.flags & (32 | 64)) {
                            return anyType;
                        }
                        if (type.flags & 131072) {
                            return getWidenedTypeOfObjectLiteral(type);
                        }
                        if (type.flags & 16384) {
                            return getUnionType(ts.map(type.types, getWidenedType));
                        }
                        if (isArrayType(type)) {
                            return createArrayType(getWidenedType(type.typeArguments[0]));
                        }
                    }
                    return type;
                }
                function reportWideningErrorsInType(type) {
                    if (type.flags & 16384) {
                        var errorReported = false;
                        ts.forEach(type.types, function (t) {
                            if (reportWideningErrorsInType(t)) {
                                errorReported = true;
                            }
                        });
                        return errorReported;
                    }
                    if (isArrayType(type)) {
                        return reportWideningErrorsInType(type.typeArguments[0]);
                    }
                    if (type.flags & 131072) {
                        var errorReported = false;
                        ts.forEach(getPropertiesOfObjectType(type), function (p) {
                            var t = getTypeOfSymbol(p);
                            if (t.flags & 262144) {
                                if (!reportWideningErrorsInType(t)) {
                                    error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
                                }
                                errorReported = true;
                            }
                        });
                        return errorReported;
                    }
                    return false;
                }
                function reportImplicitAnyError(declaration, type) {
                    var typeAsString = typeToString(getWidenedType(type));
                    switch (declaration.kind) {
                        case 130:
                        case 129:
                            var diagnostic = ts.Diagnostics.Member_0_implicitly_has_an_1_type;
                            break;
                        case 128:
                            var diagnostic = declaration.dotDotDotToken ? ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : ts.Diagnostics.Parameter_0_implicitly_has_an_1_type;
                            break;
                        case 195:
                        case 132:
                        case 131:
                        case 134:
                        case 135:
                        case 160:
                        case 161:
                            if (!declaration.name) {
                                error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
                                return;
                            }
                            var diagnostic = ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
                            break;
                        default:
                            var diagnostic = ts.Diagnostics.Variable_0_implicitly_has_an_1_type;
                    }
                    error(declaration, diagnostic, ts.declarationNameToString(declaration.name), typeAsString);
                }
                function reportErrorsFromWidening(declaration, type) {
                    if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & 262144) {
                        if (!reportWideningErrorsInType(type)) {
                            reportImplicitAnyError(declaration, type);
                        }
                    }
                }
                function forEachMatchingParameterType(source, target, callback) {
                    var sourceMax = source.parameters.length;
                    var targetMax = target.parameters.length;
                    var count;
                    if (source.hasRestParameter && target.hasRestParameter) {
                        count = sourceMax > targetMax ? sourceMax : targetMax;
                        sourceMax--;
                        targetMax--;
                    }
                    else if (source.hasRestParameter) {
                        sourceMax--;
                        count = targetMax;
                    }
                    else if (target.hasRestParameter) {
                        targetMax--;
                        count = sourceMax;
                    }
                    else {
                        count = sourceMax < targetMax ? sourceMax : targetMax;
                    }
                    for (var i = 0; i < count; i++) {
                        var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
                        var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
                        callback(s, t);
                    }
                }
                function createInferenceContext(typeParameters, inferUnionTypes) {
                    var inferences = [];
                    for (var i = 0; i < typeParameters.length; i++) {
                        inferences.push({
                            primary: undefined,
                            secondary: undefined
                        });
                    }
                    return {
                        typeParameters: typeParameters,
                        inferUnionTypes: inferUnionTypes,
                        inferenceCount: 0,
                        inferences: inferences,
                        inferredTypes: new Array(typeParameters.length)
                    };
                }
                function inferTypes(context, source, target) {
                    var sourceStack;
                    var targetStack;
                    var depth = 0;
                    var inferiority = 0;
                    inferFromTypes(source, target);
                    function isInProcess(source, target) {
                        for (var i = 0; i < depth; i++) {
                            if (source === sourceStack[i] && target === targetStack[i])
                                return true;
                        }
                        return false;
                    }
                    function isWithinDepthLimit(type, stack) {
                        if (depth >= 5) {
                            var target = type.target;
                            var count = 0;
                            for (var i = 0; i < depth; i++) {
                                var t = stack[i];
                                if (t.flags & 4096 && t.target === target)
                                    count++;
                            }
                            return count < 5;
                        }
                        return true;
                    }
                    function inferFromTypes(source, target) {
                        if (source === anyFunctionType) {
                            return;
                        }
                        if (target.flags & 512) {
                            var typeParameters = context.typeParameters;
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (target === typeParameters[i]) {
                                    var inferences = context.inferences[i];
                                    var candidates = inferiority ? inferences.secondary || (inferences.secondary = []) : inferences.primary || (inferences.primary = []);
                                    if (!ts.contains(candidates, source))
                                        candidates.push(source);
                                    break;
                                }
                            }
                        }
                        else if (source.flags & 4096 && target.flags & 4096 && source.target === target.target) {
                            var sourceTypes = source.typeArguments;
                            var targetTypes = target.typeArguments;
                            for (var i = 0; i < sourceTypes.length; i++) {
                                inferFromTypes(sourceTypes[i], targetTypes[i]);
                            }
                        }
                        else if (target.flags & 16384) {
                            var targetTypes = target.types;
                            var typeParameterCount = 0;
                            var typeParameter;
                            for (var i = 0; i < targetTypes.length; i++) {
                                var t = targetTypes[i];
                                if (t.flags & 512 && ts.contains(context.typeParameters, t)) {
                                    typeParameter = t;
                                    typeParameterCount++;
                                }
                                else {
                                    inferFromTypes(source, t);
                                }
                            }
                            if (typeParameterCount === 1) {
                                inferiority++;
                                inferFromTypes(source, typeParameter);
                                inferiority--;
                            }
                        }
                        else if (source.flags & 16384) {
                            var sourceTypes = source.types;
                            for (var i = 0; i < sourceTypes.length; i++) {
                                inferFromTypes(sourceTypes[i], target);
                            }
                        }
                        else if (source.flags & 48128 && (target.flags & (4096 | 8192) || (target.flags & 32768) && target.symbol && target.symbol.flags & (8192 | 2048))) {
                            if (!isInProcess(source, target) && isWithinDepthLimit(source, sourceStack) && isWithinDepthLimit(target, targetStack)) {
                                if (depth === 0) {
                                    sourceStack = [];
                                    targetStack = [];
                                }
                                sourceStack[depth] = source;
                                targetStack[depth] = target;
                                depth++;
                                inferFromProperties(source, target);
                                inferFromSignatures(source, target, 0);
                                inferFromSignatures(source, target, 1);
                                inferFromIndexTypes(source, target, 0, 0);
                                inferFromIndexTypes(source, target, 1, 1);
                                inferFromIndexTypes(source, target, 0, 1);
                                depth--;
                            }
                        }
                    }
                    function inferFromProperties(source, target) {
                        var properties = getPropertiesOfObjectType(target);
                        for (var i = 0; i < properties.length; i++) {
                            var targetProp = properties[i];
                            var sourceProp = getPropertyOfObjectType(source, targetProp.name);
                            if (sourceProp) {
                                inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
                            }
                        }
                    }
                    function inferFromSignatures(source, target, kind) {
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        var sourceLen = sourceSignatures.length;
                        var targetLen = targetSignatures.length;
                        var len = sourceLen < targetLen ? sourceLen : targetLen;
                        for (var i = 0; i < len; i++) {
                            inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
                        }
                    }
                    function inferFromSignature(source, target) {
                        forEachMatchingParameterType(source, target, inferFromTypes);
                        inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
                    }
                    function inferFromIndexTypes(source, target, sourceKind, targetKind) {
                        var targetIndexType = getIndexTypeOfType(target, targetKind);
                        if (targetIndexType) {
                            var sourceIndexType = getIndexTypeOfType(source, sourceKind);
                            if (sourceIndexType) {
                                inferFromTypes(sourceIndexType, targetIndexType);
                            }
                        }
                    }
                }
                function getInferenceCandidates(context, index) {
                    var inferences = context.inferences[index];
                    return inferences.primary || inferences.secondary || emptyArray;
                }
                function getInferredType(context, index) {
                    var inferredType = context.inferredTypes[index];
                    if (!inferredType) {
                        var inferences = getInferenceCandidates(context, index);
                        if (inferences.length) {
                            var unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
                            inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : inferenceFailureType;
                        }
                        else {
                            inferredType = emptyObjectType;
                        }
                        if (inferredType !== inferenceFailureType) {
                            var constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
                            inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
                        }
                        context.inferredTypes[index] = inferredType;
                    }
                    return inferredType;
                }
                function getInferredTypes(context) {
                    for (var i = 0; i < context.inferredTypes.length; i++) {
                        getInferredType(context, i);
                    }
                    return context.inferredTypes;
                }
                function hasAncestor(node, kind) {
                    return ts.getAncestor(node, kind) !== undefined;
                }
                function getResolvedSymbol(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedSymbol) {
                        links.resolvedSymbol = (ts.getFullWidth(node) > 0 && resolveName(node, node.text, 107455 | 1048576, ts.Diagnostics.Cannot_find_name_0, node)) || unknownSymbol;
                    }
                    return links.resolvedSymbol;
                }
                function isInTypeQuery(node) {
                    while (node) {
                        switch (node.kind) {
                            case 142:
                                return true;
                            case 64:
                            case 125:
                                node = node.parent;
                                continue;
                            default:
                                return false;
                        }
                    }
                    ts.Debug.fail("should not get here");
                }
                function removeTypesFromUnionType(type, typeKind, isOfTypeKind, allowEmptyUnionResult) {
                    if (type.flags & 16384) {
                        var types = type.types;
                        if (ts.forEach(types, function (t) {
                            return !!(t.flags & typeKind) === isOfTypeKind;
                        })) {
                            var narrowedType = getUnionType(ts.filter(types, function (t) {
                                return !(t.flags & typeKind) === isOfTypeKind;
                            }));
                            if (allowEmptyUnionResult || narrowedType !== emptyObjectType) {
                                return narrowedType;
                            }
                        }
                    }
                    else if (allowEmptyUnionResult && !!(type.flags & typeKind) === isOfTypeKind) {
                        return getUnionType(emptyArray);
                    }
                    return type;
                }
                function hasInitializer(node) {
                    return !!(node.initializer || ts.isBindingPattern(node.parent) && hasInitializer(node.parent.parent));
                }
                function isVariableAssignedWithin(symbol, node) {
                    var links = getNodeLinks(node);
                    if (links.assignmentChecks) {
                        var cachedResult = links.assignmentChecks[symbol.id];
                        if (cachedResult !== undefined) {
                            return cachedResult;
                        }
                    }
                    else {
                        links.assignmentChecks = {};
                    }
                    return links.assignmentChecks[symbol.id] = isAssignedIn(node);
                    function isAssignedInBinaryExpression(node) {
                        if (node.operatorToken.kind >= 52 && node.operatorToken.kind <= 63) {
                            var n = node.left;
                            while (n.kind === 159) {
                                n = n.expression;
                            }
                            if (n.kind === 64 && getResolvedSymbol(n) === symbol) {
                                return true;
                            }
                        }
                        return ts.forEachChild(node, isAssignedIn);
                    }
                    function isAssignedInVariableDeclaration(node) {
                        if (!ts.isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
                            return true;
                        }
                        return ts.forEachChild(node, isAssignedIn);
                    }
                    function isAssignedIn(node) {
                        switch (node.kind) {
                            case 167:
                                return isAssignedInBinaryExpression(node);
                            case 193:
                            case 150:
                                return isAssignedInVariableDeclaration(node);
                            case 148:
                            case 149:
                            case 151:
                            case 152:
                            case 153:
                            case 154:
                            case 155:
                            case 156:
                            case 158:
                            case 159:
                            case 165:
                            case 162:
                            case 163:
                            case 164:
                            case 166:
                            case 168:
                            case 171:
                            case 174:
                            case 175:
                            case 177:
                            case 178:
                            case 179:
                            case 180:
                            case 181:
                            case 182:
                            case 183:
                            case 186:
                            case 187:
                            case 188:
                            case 214:
                            case 215:
                            case 189:
                            case 190:
                            case 191:
                            case 217:
                                return ts.forEachChild(node, isAssignedIn);
                        }
                        return false;
                    }
                }
                function resolveLocation(node) {
                    var containerNodes = [];
                    for (var parent = node.parent; parent; parent = parent.parent) {
                        if ((ts.isExpression(parent) || ts.isObjectLiteralMethod(node)) && isContextSensitive(parent)) {
                            containerNodes.unshift(parent);
                        }
                    }
                    ts.forEach(containerNodes, function (node) {
                        getTypeOfNode(node);
                    });
                }
                function getSymbolAtLocation(node) {
                    resolveLocation(node);
                    return getSymbolInfo(node);
                }
                function getTypeAtLocation(node) {
                    resolveLocation(node);
                    return getTypeOfNode(node);
                }
                function getTypeOfSymbolAtLocation(symbol, node) {
                    resolveLocation(node);
                    return getNarrowedTypeOfSymbol(symbol, node);
                }
                function getNarrowedTypeOfSymbol(symbol, node) {
                    var type = getTypeOfSymbol(symbol);
                    if (node && symbol.flags & 3 && type.flags & (1 | 48128 | 16384 | 512)) {
                        loop: while (node.parent) {
                            var child = node;
                            node = node.parent;
                            var narrowedType = type;
                            switch (node.kind) {
                                case 178:
                                    if (child !== node.expression) {
                                        narrowedType = narrowType(type, node.expression, child === node.thenStatement);
                                    }
                                    break;
                                case 168:
                                    if (child !== node.condition) {
                                        narrowedType = narrowType(type, node.condition, child === node.whenTrue);
                                    }
                                    break;
                                case 167:
                                    if (child === node.right) {
                                        if (node.operatorToken.kind === 48) {
                                            narrowedType = narrowType(type, node.left, true);
                                        }
                                        else if (node.operatorToken.kind === 49) {
                                            narrowedType = narrowType(type, node.left, false);
                                        }
                                    }
                                    break;
                                case 221:
                                case 200:
                                case 195:
                                case 132:
                                case 131:
                                case 134:
                                case 135:
                                case 133:
                                    break loop;
                            }
                            if (narrowedType !== type) {
                                if (isVariableAssignedWithin(symbol, node)) {
                                    break;
                                }
                                type = narrowedType;
                            }
                        }
                    }
                    return type;
                    function narrowTypeByEquality(type, expr, assumeTrue) {
                        if (expr.left.kind !== 163 || expr.right.kind !== 8) {
                            return type;
                        }
                        var left = expr.left;
                        var right = expr.right;
                        if (left.expression.kind !== 64 || getResolvedSymbol(left.expression) !== symbol) {
                            return type;
                        }
                        var typeInfo = primitiveTypeInfo[right.text];
                        if (expr.operatorToken.kind === 31) {
                            assumeTrue = !assumeTrue;
                        }
                        if (assumeTrue) {
                            if (!typeInfo) {
                                return removeTypesFromUnionType(type, 258 | 132 | 8 | 1048576, true, false);
                            }
                            if (isTypeSubtypeOf(typeInfo.type, type)) {
                                return typeInfo.type;
                            }
                            return removeTypesFromUnionType(type, typeInfo.flags, false, false);
                        }
                        else {
                            if (typeInfo) {
                                return removeTypesFromUnionType(type, typeInfo.flags, true, false);
                            }
                            return type;
                        }
                    }
                    function narrowTypeByAnd(type, expr, assumeTrue) {
                        if (assumeTrue) {
                            return narrowType(narrowType(type, expr.left, true), expr.right, true);
                        }
                        else {
                            return getUnionType([
                                narrowType(type, expr.left, false),
                                narrowType(narrowType(type, expr.left, true), expr.right, false)
                            ]);
                        }
                    }
                    function narrowTypeByOr(type, expr, assumeTrue) {
                        if (assumeTrue) {
                            return getUnionType([
                                narrowType(type, expr.left, true),
                                narrowType(narrowType(type, expr.left, false), expr.right, true)
                            ]);
                        }
                        else {
                            return narrowType(narrowType(type, expr.left, false), expr.right, false);
                        }
                    }
                    function narrowTypeByInstanceof(type, expr, assumeTrue) {
                        if (type.flags & 1 || !assumeTrue || expr.left.kind !== 64 || getResolvedSymbol(expr.left) !== symbol) {
                            return type;
                        }
                        var rightType = checkExpression(expr.right);
                        if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
                            return type;
                        }
                        var prototypeProperty = getPropertyOfType(rightType, "prototype");
                        if (!prototypeProperty) {
                            return type;
                        }
                        var targetType = getTypeOfSymbol(prototypeProperty);
                        if (isTypeSubtypeOf(targetType, type)) {
                            return targetType;
                        }
                        if (type.flags & 16384) {
                            return getUnionType(ts.filter(type.types, function (t) {
                                return isTypeSubtypeOf(t, targetType);
                            }));
                        }
                        return type;
                    }
                    function narrowType(type, expr, assumeTrue) {
                        switch (expr.kind) {
                            case 159:
                                return narrowType(type, expr.expression, assumeTrue);
                            case 167:
                                var operator = expr.operatorToken.kind;
                                if (operator === 30 || operator === 31) {
                                    return narrowTypeByEquality(type, expr, assumeTrue);
                                }
                                else if (operator === 48) {
                                    return narrowTypeByAnd(type, expr, assumeTrue);
                                }
                                else if (operator === 49) {
                                    return narrowTypeByOr(type, expr, assumeTrue);
                                }
                                else if (operator === 86) {
                                    return narrowTypeByInstanceof(type, expr, assumeTrue);
                                }
                                break;
                            case 165:
                                if (expr.operator === 46) {
                                    return narrowType(type, expr.operand, !assumeTrue);
                                }
                                break;
                        }
                        return type;
                    }
                }
                function checkIdentifier(node) {
                    var symbol = getResolvedSymbol(node);
                    if (symbol === argumentsSymbol && ts.getContainingFunction(node).kind === 161) {
                        error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_Consider_using_a_standard_function_expression);
                    }
                    if (symbol.flags & 8388608 && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
                        markAliasSymbolAsReferenced(symbol);
                    }
                    checkCollisionWithCapturedSuperVariable(node, node);
                    checkCollisionWithCapturedThisVariable(node, node);
                    checkBlockScopedBindingCapturedInLoop(node, symbol);
                    return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
                }
                function isInsideFunction(node, threshold) {
                    var current = node;
                    while (current && current !== threshold) {
                        if (ts.isFunctionLike(current)) {
                            return true;
                        }
                        current = current.parent;
                    }
                    return false;
                }
                function checkBlockScopedBindingCapturedInLoop(node, symbol) {
                    if (languageVersion >= 2 || (symbol.flags & 2) === 0 || symbol.valueDeclaration.parent.kind === 217) {
                        return;
                    }
                    var container = symbol.valueDeclaration;
                    while (container.kind !== 194) {
                        container = container.parent;
                    }
                    container = container.parent;
                    if (container.kind === 175) {
                        container = container.parent;
                    }
                    var inFunction = isInsideFunction(node.parent, container);
                    var current = container;
                    while (current && !ts.nodeStartsNewLexicalEnvironment(current)) {
                        if (isIterationStatement(current, false)) {
                            if (inFunction) {
                                grammarErrorOnFirstToken(current, ts.Diagnostics.Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher, ts.declarationNameToString(node));
                            }
                            getNodeLinks(symbol.valueDeclaration).flags |= 256;
                            break;
                        }
                        current = current.parent;
                    }
                }
                function captureLexicalThis(node, container) {
                    var classNode = container.parent && container.parent.kind === 196 ? container.parent : undefined;
                    getNodeLinks(node).flags |= 2;
                    if (container.kind === 130 || container.kind === 133) {
                        getNodeLinks(classNode).flags |= 4;
                    }
                    else {
                        getNodeLinks(container).flags |= 4;
                    }
                }
                function checkThisExpression(node) {
                    var container = ts.getThisContainer(node, true);
                    var needToCaptureLexicalThis = false;
                    if (container.kind === 161) {
                        container = ts.getThisContainer(container, false);
                        needToCaptureLexicalThis = (languageVersion < 2);
                    }
                    switch (container.kind) {
                        case 200:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_body);
                            break;
                        case 199:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
                            break;
                        case 133:
                            if (isInConstructorArgumentInitializer(node, container)) {
                                error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments);
                            }
                            break;
                        case 130:
                        case 129:
                            if (container.flags & 128) {
                                error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
                            }
                            break;
                        case 126:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name);
                            break;
                    }
                    if (needToCaptureLexicalThis) {
                        captureLexicalThis(node, container);
                    }
                    var classNode = container.parent && container.parent.kind === 196 ? container.parent : undefined;
                    if (classNode) {
                        var symbol = getSymbolOfNode(classNode);
                        return container.flags & 128 ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol);
                    }
                    return anyType;
                }
                function isInConstructorArgumentInitializer(node, constructorDecl) {
                    for (var n = node; n && n !== constructorDecl; n = n.parent) {
                        if (n.kind === 128) {
                            return true;
                        }
                    }
                    return false;
                }
                function checkSuperExpression(node) {
                    var isCallExpression = node.parent.kind === 155 && node.parent.expression === node;
                    var enclosingClass = ts.getAncestor(node, 196);
                    var baseClass;
                    if (enclosingClass && ts.getClassBaseTypeNode(enclosingClass)) {
                        var classType = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClass));
                        baseClass = classType.baseTypes.length && classType.baseTypes[0];
                    }
                    if (!baseClass) {
                        error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class);
                        return unknownType;
                    }
                    var container = ts.getSuperContainer(node, true);
                    if (container) {
                        var canUseSuperExpression = false;
                        if (isCallExpression) {
                            canUseSuperExpression = container.kind === 133;
                        }
                        else {
                            var needToCaptureLexicalThis = false;
                            while (container && container.kind === 161) {
                                container = ts.getSuperContainer(container, true);
                                needToCaptureLexicalThis = true;
                            }
                            if (container && container.parent && container.parent.kind === 196) {
                                if (container.flags & 128) {
                                    canUseSuperExpression = container.kind === 132 || container.kind === 131 || container.kind === 134 || container.kind === 135;
                                }
                                else {
                                    canUseSuperExpression = container.kind === 132 || container.kind === 131 || container.kind === 134 || container.kind === 135 || container.kind === 130 || container.kind === 129 || container.kind === 133;
                                }
                            }
                        }
                        if (canUseSuperExpression) {
                            var returnType;
                            if ((container.flags & 128) || isCallExpression) {
                                getNodeLinks(node).flags |= 32;
                                returnType = getTypeOfSymbol(baseClass.symbol);
                            }
                            else {
                                getNodeLinks(node).flags |= 16;
                                returnType = baseClass;
                            }
                            if (container.kind === 133 && isInConstructorArgumentInitializer(node, container)) {
                                error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
                                returnType = unknownType;
                            }
                            if (!isCallExpression && needToCaptureLexicalThis) {
                                captureLexicalThis(node.parent, container);
                            }
                            return returnType;
                        }
                    }
                    if (container.kind === 126) {
                        error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
                    }
                    else if (isCallExpression) {
                        error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
                    }
                    else {
                        error(node, ts.Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
                    }
                    return unknownType;
                }
                function getContextuallyTypedParameterType(parameter) {
                    if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
                        var func = parameter.parent;
                        if (isContextSensitive(func)) {
                            var contextualSignature = getContextualSignature(func);
                            if (contextualSignature) {
                                var funcHasRestParameters = ts.hasRestParameters(func);
                                var len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
                                var indexOfParameter = ts.indexOf(func.parameters, parameter);
                                if (indexOfParameter < len) {
                                    return getTypeAtPosition(contextualSignature, indexOfParameter);
                                }
                                if (indexOfParameter === (func.parameters.length - 1) && funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
                                    return getTypeOfSymbol(contextualSignature.parameters[contextualSignature.parameters.length - 1]);
                                }
                            }
                        }
                    }
                    return undefined;
                }
                function getContextualTypeForInitializerExpression(node) {
                    var declaration = node.parent;
                    if (node === declaration.initializer) {
                        if (declaration.type) {
                            return getTypeFromTypeNode(declaration.type);
                        }
                        if (declaration.kind === 128) {
                            var type = getContextuallyTypedParameterType(declaration);
                            if (type) {
                                return type;
                            }
                        }
                        if (ts.isBindingPattern(declaration.name)) {
                            return getTypeFromBindingPattern(declaration.name);
                        }
                    }
                    return undefined;
                }
                function getContextualTypeForReturnExpression(node) {
                    var func = ts.getContainingFunction(node);
                    if (func) {
                        if (func.type || func.kind === 133 || func.kind === 134 && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(func.symbol, 135))) {
                            return getReturnTypeOfSignature(getSignatureFromDeclaration(func));
                        }
                        var signature = getContextualSignatureForFunctionLikeDeclaration(func);
                        if (signature) {
                            return getReturnTypeOfSignature(signature);
                        }
                    }
                    return undefined;
                }
                function getContextualTypeForArgument(callTarget, arg) {
                    var args = getEffectiveCallArguments(callTarget);
                    var argIndex = ts.indexOf(args, arg);
                    if (argIndex >= 0) {
                        var signature = getResolvedSignature(callTarget);
                        return getTypeAtPosition(signature, argIndex);
                    }
                    return undefined;
                }
                function getContextualTypeForSubstitutionExpression(template, substitutionExpression) {
                    if (template.parent.kind === 157) {
                        return getContextualTypeForArgument(template.parent, substitutionExpression);
                    }
                    return undefined;
                }
                function getContextualTypeForBinaryOperand(node) {
                    var binaryExpression = node.parent;
                    var operator = binaryExpression.operatorToken.kind;
                    if (operator >= 52 && operator <= 63) {
                        if (node === binaryExpression.right) {
                            return checkExpression(binaryExpression.left);
                        }
                    }
                    else if (operator === 49) {
                        var type = getContextualType(binaryExpression);
                        if (!type && node === binaryExpression.right) {
                            type = checkExpression(binaryExpression.left);
                        }
                        return type;
                    }
                    return undefined;
                }
                function applyToContextualType(type, mapper) {
                    if (!(type.flags & 16384)) {
                        return mapper(type);
                    }
                    var types = type.types;
                    var mappedType;
                    var mappedTypes;
                    for (var i = 0; i < types.length; i++) {
                        var t = mapper(types[i]);
                        if (t) {
                            if (!mappedType) {
                                mappedType = t;
                            }
                            else if (!mappedTypes) {
                                mappedTypes = [
                                    mappedType,
                                    t
                                ];
                            }
                            else {
                                mappedTypes.push(t);
                            }
                        }
                    }
                    return mappedTypes ? getUnionType(mappedTypes) : mappedType;
                }
                function getTypeOfPropertyOfContextualType(type, name) {
                    return applyToContextualType(type, function (t) {
                        var prop = getPropertyOfObjectType(t, name);
                        return prop ? getTypeOfSymbol(prop) : undefined;
                    });
                }
                function getIndexTypeOfContextualType(type, kind) {
                    return applyToContextualType(type, function (t) {
                        return getIndexTypeOfObjectOrUnionType(t, kind);
                    });
                }
                function contextualTypeIsTupleLikeType(type) {
                    return !!(type.flags & 16384 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type));
                }
                function contextualTypeHasIndexSignature(type, kind) {
                    return !!(type.flags & 16384 ? ts.forEach(type.types, function (t) {
                        return getIndexTypeOfObjectOrUnionType(t, kind);
                    }) : getIndexTypeOfObjectOrUnionType(type, kind));
                }
                function getContextualTypeForObjectLiteralMethod(node) {
                    ts.Debug.assert(ts.isObjectLiteralMethod(node));
                    if (isInsideWithStatementBody(node)) {
                        return undefined;
                    }
                    return getContextualTypeForObjectLiteralElement(node);
                }
                function getContextualTypeForObjectLiteralElement(element) {
                    var objectLiteral = element.parent;
                    var type = getContextualType(objectLiteral);
                    if (type) {
                        if (!ts.hasDynamicName(element)) {
                            var symbolName = getSymbolOfNode(element).name;
                            var propertyType = getTypeOfPropertyOfContextualType(type, symbolName);
                            if (propertyType) {
                                return propertyType;
                            }
                        }
                        return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1) || getIndexTypeOfContextualType(type, 0);
                    }
                    return undefined;
                }
                function getContextualTypeForElementExpression(node) {
                    var arrayLiteral = node.parent;
                    var type = getContextualType(arrayLiteral);
                    if (type) {
                        var index = ts.indexOf(arrayLiteral.elements, node);
                        return getTypeOfPropertyOfContextualType(type, "" + index) || getIndexTypeOfContextualType(type, 1) || (languageVersion >= 2 ? checkIteratedType(type, undefined) : undefined);
                    }
                    return undefined;
                }
                function getContextualTypeForConditionalOperand(node) {
                    var conditional = node.parent;
                    return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
                }
                function getContextualType(node) {
                    if (isInsideWithStatementBody(node)) {
                        return undefined;
                    }
                    if (node.contextualType) {
                        return node.contextualType;
                    }
                    var parent = node.parent;
                    switch (parent.kind) {
                        case 193:
                        case 128:
                        case 130:
                        case 129:
                        case 150:
                            return getContextualTypeForInitializerExpression(node);
                        case 161:
                        case 186:
                            return getContextualTypeForReturnExpression(node);
                        case 155:
                        case 156:
                            return getContextualTypeForArgument(parent, node);
                        case 158:
                            return getTypeFromTypeNode(parent.type);
                        case 167:
                            return getContextualTypeForBinaryOperand(node);
                        case 218:
                            return getContextualTypeForObjectLiteralElement(parent);
                        case 151:
                            return getContextualTypeForElementExpression(node);
                        case 168:
                            return getContextualTypeForConditionalOperand(node);
                        case 173:
                            ts.Debug.assert(parent.parent.kind === 169);
                            return getContextualTypeForSubstitutionExpression(parent.parent, node);
                        case 159:
                            return getContextualType(parent);
                    }
                    return undefined;
                }
                function getNonGenericSignature(type) {
                    var signatures = getSignaturesOfObjectOrUnionType(type, 0);
                    if (signatures.length === 1) {
                        var signature = signatures[0];
                        if (!signature.typeParameters) {
                            return signature;
                        }
                    }
                }
                function isFunctionExpressionOrArrowFunction(node) {
                    return node.kind === 160 || node.kind === 161;
                }
                function getContextualSignatureForFunctionLikeDeclaration(node) {
                    return isFunctionExpressionOrArrowFunction(node) ? getContextualSignature(node) : undefined;
                }
                function getContextualSignature(node) {
                    ts.Debug.assert(node.kind !== 132 || ts.isObjectLiteralMethod(node));
                    var type = ts.isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node) : getContextualType(node);
                    if (!type) {
                        return undefined;
                    }
                    if (!(type.flags & 16384)) {
                        return getNonGenericSignature(type);
                    }
                    var signatureList;
                    var types = type.types;
                    for (var i = 0; i < types.length; i++) {
                        if (signatureList && getSignaturesOfObjectOrUnionType(types[i], 0).length > 1) {
                            return undefined;
                        }
                        var signature = getNonGenericSignature(types[i]);
                        if (signature) {
                            if (!signatureList) {
                                signatureList = [
                                    signature
                                ];
                            }
                            else if (!compareSignatures(signatureList[0], signature, false, compareTypes)) {
                                return undefined;
                            }
                            else {
                                signatureList.push(signature);
                            }
                        }
                    }
                    var result;
                    if (signatureList) {
                        result = cloneSignature(signatureList[0]);
                        result.resolvedReturnType = undefined;
                        result.unionSignatures = signatureList;
                    }
                    return result;
                }
                function isInferentialContext(mapper) {
                    return mapper && mapper !== identityMapper;
                }
                function isAssignmentTarget(node) {
                    var parent = node.parent;
                    if (parent.kind === 167 && parent.operatorToken.kind === 52 && parent.left === node) {
                        return true;
                    }
                    if (parent.kind === 218) {
                        return isAssignmentTarget(parent.parent);
                    }
                    if (parent.kind === 151) {
                        return isAssignmentTarget(parent);
                    }
                    return false;
                }
                function checkSpreadElementExpression(node, contextualMapper) {
                    var type = checkExpressionCached(node.expression, contextualMapper);
                    if (!isArrayLikeType(type)) {
                        error(node.expression, ts.Diagnostics.Type_0_is_not_an_array_type, typeToString(type));
                        return unknownType;
                    }
                    return type;
                }
                function checkArrayLiteral(node, contextualMapper) {
                    var elements = node.elements;
                    if (!elements.length) {
                        return createArrayType(undefinedType);
                    }
                    var hasSpreadElement = false;
                    var elementTypes = [];
                    ts.forEach(elements, function (e) {
                        var type = checkExpression(e, contextualMapper);
                        if (e.kind === 171) {
                            elementTypes.push(getIndexTypeOfType(type, 1) || anyType);
                            hasSpreadElement = true;
                        }
                        else {
                            elementTypes.push(type);
                        }
                    });
                    if (!hasSpreadElement) {
                        var contextualType = getContextualType(node);
                        if (contextualType && contextualTypeIsTupleLikeType(contextualType) || isAssignmentTarget(node)) {
                            return createTupleType(elementTypes);
                        }
                    }
                    return createArrayType(getUnionType(elementTypes));
                }
                function isNumericName(name) {
                    return name.kind === 126 ? isNumericComputedName(name) : isNumericLiteralName(name.text);
                }
                function isNumericComputedName(name) {
                    return allConstituentTypesHaveKind(checkComputedPropertyName(name), 1 | 132);
                }
                function isNumericLiteralName(name) {
                    return (+name).toString() === name;
                }
                function checkComputedPropertyName(node) {
                    var links = getNodeLinks(node.expression);
                    if (!links.resolvedType) {
                        links.resolvedType = checkExpression(node.expression);
                        if (!allConstituentTypesHaveKind(links.resolvedType, 1 | 132 | 258 | 1048576)) {
                            error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
                        }
                        else {
                            checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, true);
                        }
                    }
                    return links.resolvedType;
                }
                function checkObjectLiteral(node, contextualMapper) {
                    checkGrammarObjectLiteralExpression(node);
                    var propertiesTable = {};
                    var propertiesArray = [];
                    var contextualType = getContextualType(node);
                    var typeFlags;
                    for (var i = 0; i < node.properties.length; i++) {
                        var memberDecl = node.properties[i];
                        var member = memberDecl.symbol;
                        if (memberDecl.kind === 218 || memberDecl.kind === 219 || ts.isObjectLiteralMethod(memberDecl)) {
                            if (memberDecl.kind === 218) {
                                var type = checkPropertyAssignment(memberDecl, contextualMapper);
                            }
                            else if (memberDecl.kind === 132) {
                                var type = checkObjectLiteralMethod(memberDecl, contextualMapper);
                            }
                            else {
                                ts.Debug.assert(memberDecl.kind === 219);
                                var type = memberDecl.name.kind === 126 ? unknownType : checkExpression(memberDecl.name, contextualMapper);
                            }
                            typeFlags |= type.flags;
                            var prop = createSymbol(4 | 67108864 | member.flags, member.name);
                            prop.declarations = member.declarations;
                            prop.parent = member.parent;
                            if (member.valueDeclaration) {
                                prop.valueDeclaration = member.valueDeclaration;
                            }
                            prop.type = type;
                            prop.target = member;
                            member = prop;
                        }
                        else {
                            ts.Debug.assert(memberDecl.kind === 134 || memberDecl.kind === 135);
                            checkAccessorDeclaration(memberDecl);
                        }
                        if (!ts.hasDynamicName(memberDecl)) {
                            propertiesTable[member.name] = member;
                        }
                        propertiesArray.push(member);
                    }
                    var stringIndexType = getIndexType(0);
                    var numberIndexType = getIndexType(1);
                    var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
                    result.flags |= 131072 | 524288 | (typeFlags & 262144);
                    return result;
                    function getIndexType(kind) {
                        if (contextualType && contextualTypeHasIndexSignature(contextualType, kind)) {
                            var propTypes = [];
                            for (var i = 0; i < propertiesArray.length; i++) {
                                var propertyDecl = node.properties[i];
                                if (kind === 0 || isNumericName(propertyDecl.name)) {
                                    var type = getTypeOfSymbol(propertiesArray[i]);
                                    if (!ts.contains(propTypes, type)) {
                                        propTypes.push(type);
                                    }
                                }
                            }
                            var result = propTypes.length ? getUnionType(propTypes) : undefinedType;
                            typeFlags |= result.flags;
                            return result;
                        }
                        return undefined;
                    }
                }
                function getDeclarationKindFromSymbol(s) {
                    return s.valueDeclaration ? s.valueDeclaration.kind : 130;
                }
                function getDeclarationFlagsFromSymbol(s) {
                    return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : s.flags & 134217728 ? 16 | 128 : 0;
                }
                function checkClassPropertyAccess(node, left, type, prop) {
                    var flags = getDeclarationFlagsFromSymbol(prop);
                    if (!(flags & (32 | 64))) {
                        return;
                    }
                    var enclosingClassDeclaration = ts.getAncestor(node, 196);
                    var enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
                    var declaringClass = getDeclaredTypeOfSymbol(prop.parent);
                    if (flags & 32) {
                        if (declaringClass !== enclosingClass) {
                            error(node, ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
                        }
                        return;
                    }
                    if (left.kind === 90) {
                        return;
                    }
                    if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) {
                        error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
                        return;
                    }
                    if (flags & 128) {
                        return;
                    }
                    if (!(getTargetType(type).flags & (1024 | 2048) && hasBaseType(type, enclosingClass))) {
                        error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
                    }
                }
                function checkPropertyAccessExpression(node) {
                    return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
                }
                function checkQualifiedName(node) {
                    return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
                }
                function checkPropertyAccessExpressionOrQualifiedName(node, left, right) {
                    var type = checkExpressionOrQualifiedName(left);
                    if (type === unknownType)
                        return type;
                    if (type !== anyType) {
                        var apparentType = getApparentType(getWidenedType(type));
                        if (apparentType === unknownType) {
                            return unknownType;
                        }
                        var prop = getPropertyOfType(apparentType, right.text);
                        if (!prop) {
                            if (right.text) {
                                error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(right), typeToString(type));
                            }
                            return unknownType;
                        }
                        getNodeLinks(node).resolvedSymbol = prop;
                        if (prop.parent && prop.parent.flags & 32) {
                            if (left.kind === 90 && getDeclarationKindFromSymbol(prop) !== 132) {
                                error(right, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
                            }
                            else {
                                checkClassPropertyAccess(node, left, type, prop);
                            }
                        }
                        return getTypeOfSymbol(prop);
                    }
                    return anyType;
                }
                function isValidPropertyAccess(node, propertyName) {
                    var left = node.kind === 153 ? node.expression : node.left;
                    var type = checkExpressionOrQualifiedName(left);
                    if (type !== unknownType && type !== anyType) {
                        var prop = getPropertyOfType(getWidenedType(type), propertyName);
                        if (prop && prop.parent && prop.parent.flags & 32) {
                            if (left.kind === 90 && getDeclarationKindFromSymbol(prop) !== 132) {
                                return false;
                            }
                            else {
                                var modificationCount = diagnostics.getModificationCount();
                                checkClassPropertyAccess(node, left, type, prop);
                                return diagnostics.getModificationCount() === modificationCount;
                            }
                        }
                    }
                    return true;
                }
                function checkIndexedAccess(node) {
                    if (!node.argumentExpression) {
                        var sourceFile = getSourceFile(node);
                        if (node.parent.kind === 156 && node.parent.expression === node) {
                            var start = ts.skipTrivia(sourceFile.text, node.expression.end);
                            var end = node.end;
                            grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
                        }
                        else {
                            var start = node.end - "]".length;
                            var end = node.end;
                            grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Expression_expected);
                        }
                    }
                    var objectType = getApparentType(checkExpression(node.expression));
                    var indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType;
                    if (objectType === unknownType) {
                        return unknownType;
                    }
                    var isConstEnum = isConstEnumObjectType(objectType);
                    if (isConstEnum && (!node.argumentExpression || node.argumentExpression.kind !== 8)) {
                        error(node.argumentExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
                        return unknownType;
                    }
                    if (node.argumentExpression) {
                        var name = getPropertyNameForIndexedAccess(node.argumentExpression, indexType);
                        if (name !== undefined) {
                            var prop = getPropertyOfType(objectType, name);
                            if (prop) {
                                getNodeLinks(node).resolvedSymbol = prop;
                                return getTypeOfSymbol(prop);
                            }
                            else if (isConstEnum) {
                                error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name, symbolToString(objectType.symbol));
                                return unknownType;
                            }
                        }
                    }
                    if (allConstituentTypesHaveKind(indexType, 1 | 258 | 132 | 1048576)) {
                        if (allConstituentTypesHaveKind(indexType, 1 | 132)) {
                            var numberIndexType = getIndexTypeOfType(objectType, 1);
                            if (numberIndexType) {
                                return numberIndexType;
                            }
                        }
                        var stringIndexType = getIndexTypeOfType(objectType, 0);
                        if (stringIndexType) {
                            return stringIndexType;
                        }
                        if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) {
                            error(node, ts.Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
                        }
                        return anyType;
                    }
                    error(node, ts.Diagnostics.An_index_expression_argument_must_be_of_type_string_number_symbol_or_any);
                    return unknownType;
                }
                function getPropertyNameForIndexedAccess(indexArgumentExpression, indexArgumentType) {
                    if (indexArgumentExpression.kind === 8 || indexArgumentExpression.kind === 7) {
                        return indexArgumentExpression.text;
                    }
                    if (checkThatExpressionIsProperSymbolReference(indexArgumentExpression, indexArgumentType, false)) {
                        var rightHandSideName = indexArgumentExpression.name.text;
                        return ts.getPropertyNameForKnownSymbolName(rightHandSideName);
                    }
                    return undefined;
                }
                function checkThatExpressionIsProperSymbolReference(expression, expressionType, reportError) {
                    if (expressionType === unknownType) {
                        return false;
                    }
                    if (!ts.isWellKnownSymbolSyntactically(expression)) {
                        return false;
                    }
                    if ((expressionType.flags & 1048576) === 0) {
                        if (reportError) {
                            error(expression, ts.Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, ts.getTextOfNode(expression));
                        }
                        return false;
                    }
                    var leftHandSide = expression.expression;
                    var leftHandSideSymbol = getResolvedSymbol(leftHandSide);
                    if (!leftHandSideSymbol) {
                        return false;
                    }
                    var globalESSymbol = getGlobalESSymbolConstructorSymbol();
                    if (!globalESSymbol) {
                        return false;
                    }
                    if (leftHandSideSymbol !== globalESSymbol) {
                        if (reportError) {
                            error(leftHandSide, ts.Diagnostics.Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object);
                        }
                        return false;
                    }
                    return true;
                }
                function resolveUntypedCall(node) {
                    if (node.kind === 157) {
                        checkExpression(node.template);
                    }
                    else {
                        ts.forEach(node.arguments, function (argument) {
                            checkExpression(argument);
                        });
                    }
                    return anySignature;
                }
                function resolveErrorCall(node) {
                    resolveUntypedCall(node);
                    return unknownSignature;
                }
                function reorderCandidates(signatures, result) {
                    var lastParent;
                    var lastSymbol;
                    var cutoffIndex = 0;
                    var index;
                    var specializedIndex = -1;
                    var spliceIndex;
                    ts.Debug.assert(!result.length);
                    for (var i = 0; i < signatures.length; i++) {
                        var signature = signatures[i];
                        var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
                        var parent = signature.declaration && signature.declaration.parent;
                        if (!lastSymbol || symbol === lastSymbol) {
                            if (lastParent && parent === lastParent) {
                                index++;
                            }
                            else {
                                lastParent = parent;
                                index = cutoffIndex;
                            }
                        }
                        else {
                            index = cutoffIndex = result.length;
                            lastParent = parent;
                        }
                        lastSymbol = symbol;
                        if (signature.hasStringLiterals) {
                            specializedIndex++;
                            spliceIndex = specializedIndex;
                            cutoffIndex++;
                        }
                        else {
                            spliceIndex = index;
                        }
                        result.splice(spliceIndex, 0, signature);
                    }
                }
                function getSpreadArgumentIndex(args) {
                    for (var i = 0; i < args.length; i++) {
                        if (args[i].kind === 171) {
                            return i;
                        }
                    }
                    return -1;
                }
                function hasCorrectArity(node, args, signature) {
                    var adjustedArgCount;
                    var typeArguments;
                    var callIsIncomplete;
                    if (node.kind === 157) {
                        var tagExpression = node;
                        adjustedArgCount = args.length;
                        typeArguments = undefined;
                        if (tagExpression.template.kind === 169) {
                            var templateExpression = tagExpression.template;
                            var lastSpan = ts.lastOrUndefined(templateExpression.templateSpans);
                            ts.Debug.assert(lastSpan !== undefined);
                            callIsIncomplete = ts.getFullWidth(lastSpan.literal) === 0 || !!lastSpan.literal.isUnterminated;
                        }
                        else {
                            var templateLiteral = tagExpression.template;
                            ts.Debug.assert(templateLiteral.kind === 10);
                            callIsIncomplete = !!templateLiteral.isUnterminated;
                        }
                    }
                    else {
                        var callExpression = node;
                        if (!callExpression.arguments) {
                            ts.Debug.assert(callExpression.kind === 156);
                            return signature.minArgumentCount === 0;
                        }
                        adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
                        callIsIncomplete = callExpression.arguments.end === callExpression.end;
                        typeArguments = callExpression.typeArguments;
                    }
                    var hasRightNumberOfTypeArgs = !typeArguments || (signature.typeParameters && typeArguments.length === signature.typeParameters.length);
                    if (!hasRightNumberOfTypeArgs) {
                        return false;
                    }
                    var spreadArgIndex = getSpreadArgumentIndex(args);
                    if (spreadArgIndex >= 0) {
                        return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
                    }
                    if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
                        return false;
                    }
                    var hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
                    return callIsIncomplete || hasEnoughArguments;
                }
                function getSingleCallSignature(type) {
                    if (type.flags & 48128) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
                            return resolved.callSignatures[0];
                        }
                    }
                    return undefined;
                }
                function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper) {
                    var context = createInferenceContext(signature.typeParameters, true);
                    forEachMatchingParameterType(contextualSignature, signature, function (source, target) {
                        inferTypes(context, instantiateType(source, contextualMapper), target);
                    });
                    return getSignatureInstantiation(signature, getInferredTypes(context));
                }
                function inferTypeArguments(signature, args, excludeArgument) {
                    var typeParameters = signature.typeParameters;
                    var context = createInferenceContext(typeParameters, false);
                    var inferenceMapper = createInferenceMapper(context);
                    for (var i = 0; i < args.length; i++) {
                        var arg = args[i];
                        if (arg.kind !== 172) {
                            var paramType = getTypeAtPosition(signature, arg.kind === 171 ? -1 : i);
                            if (i === 0 && args[i].parent.kind === 157) {
                                var argType = globalTemplateStringsArrayType;
                            }
                            else {
                                var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper;
                                var argType = checkExpressionWithContextualType(arg, paramType, mapper);
                            }
                            inferTypes(context, argType, paramType);
                        }
                    }
                    if (excludeArgument) {
                        for (var i = 0; i < args.length; i++) {
                            if (excludeArgument[i] === false) {
                                var arg = args[i];
                                var paramType = getTypeAtPosition(signature, arg.kind === 171 ? -1 : i);
                                inferTypes(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
                            }
                        }
                    }
                    var inferredTypes = getInferredTypes(context);
                    context.failedTypeParameterIndex = ts.indexOf(inferredTypes, inferenceFailureType);
                    for (var i = 0; i < inferredTypes.length; i++) {
                        if (inferredTypes[i] === inferenceFailureType) {
                            inferredTypes[i] = unknownType;
                        }
                    }
                    return context;
                }
                function checkTypeArguments(signature, typeArguments, typeArgumentResultTypes, reportErrors) {
                    var typeParameters = signature.typeParameters;
                    var typeArgumentsAreAssignable = true;
                    for (var i = 0; i < typeParameters.length; i++) {
                        var typeArgNode = typeArguments[i];
                        var typeArgument = getTypeFromTypeNode(typeArgNode);
                        typeArgumentResultTypes[i] = typeArgument;
                        if (typeArgumentsAreAssignable) {
                            var constraint = getConstraintOfTypeParameter(typeParameters[i]);
                            if (constraint) {
                                typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
                            }
                        }
                    }
                    return typeArgumentsAreAssignable;
                }
                function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) {
                    for (var i = 0; i < args.length; i++) {
                        var arg = args[i];
                        if (arg.kind !== 172) {
                            var paramType = getTypeAtPosition(signature, arg.kind === 171 ? -1 : i);
                            var argType = i === 0 && node.kind === 157 ? globalTemplateStringsArrayType : arg.kind === 8 && !reportErrors ? getStringLiteralType(arg) : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
                            if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined, ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                function getEffectiveCallArguments(node) {
                    var args;
                    if (node.kind === 157) {
                        var template = node.template;
                        args = [
                            template
                        ];
                        if (template.kind === 169) {
                            ts.forEach(template.templateSpans, function (span) {
                                args.push(span.expression);
                            });
                        }
                    }
                    else {
                        args = node.arguments || emptyArray;
                    }
                    return args;
                }
                function getEffectiveTypeArguments(callExpression) {
                    if (callExpression.expression.kind === 90) {
                        var containingClass = ts.getAncestor(callExpression, 196);
                        var baseClassTypeNode = containingClass && ts.getClassBaseTypeNode(containingClass);
                        return baseClassTypeNode && baseClassTypeNode.typeArguments;
                    }
                    else {
                        return callExpression.typeArguments;
                    }
                }
                function resolveCall(node, signatures, candidatesOutArray) {
                    var isTaggedTemplate = node.kind === 157;
                    var typeArguments;
                    if (!isTaggedTemplate) {
                        typeArguments = getEffectiveTypeArguments(node);
                        if (node.expression.kind !== 90) {
                            ts.forEach(typeArguments, checkSourceElement);
                        }
                    }
                    var candidates = candidatesOutArray || [];
                    reorderCandidates(signatures, candidates);
                    if (!candidates.length) {
                        error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
                        return resolveErrorCall(node);
                    }
                    var args = getEffectiveCallArguments(node);
                    var excludeArgument;
                    for (var i = isTaggedTemplate ? 1 : 0; i < args.length; i++) {
                        if (isContextSensitive(args[i])) {
                            if (!excludeArgument) {
                                excludeArgument = new Array(args.length);
                            }
                            excludeArgument[i] = true;
                        }
                    }
                    var candidateForArgumentError;
                    var candidateForTypeArgumentError;
                    var resultOfFailedInference;
                    var result;
                    if (candidates.length > 1) {
                        result = chooseOverload(candidates, subtypeRelation);
                    }
                    if (!result) {
                        candidateForArgumentError = undefined;
                        candidateForTypeArgumentError = undefined;
                        resultOfFailedInference = undefined;
                        result = chooseOverload(candidates, assignableRelation);
                    }
                    if (result) {
                        return result;
                    }
                    if (candidateForArgumentError) {
                        checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true);
                    }
                    else if (candidateForTypeArgumentError) {
                        if (!isTaggedTemplate && node.typeArguments) {
                            checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, [], true);
                        }
                        else {
                            ts.Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
                            var failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
                            var inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
                            var diagnosticChainHead = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, typeToString(failedTypeParameter));
                            reportNoCommonSupertypeError(inferenceCandidates, node.expression || node.tag, diagnosticChainHead);
                        }
                    }
                    else {
                        error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
                    }
                    if (!produceDiagnostics) {
                        for (var i = 0, n = candidates.length; i < n; i++) {
                            if (hasCorrectArity(node, args, candidates[i])) {
                                return candidates[i];
                            }
                        }
                    }
                    return resolveErrorCall(node);
                    function chooseOverload(candidates, relation) {
                        for (var i = 0; i < candidates.length; i++) {
                            if (!hasCorrectArity(node, args, candidates[i])) {
                                continue;
                            }
                            var originalCandidate = candidates[i];
                            var inferenceResult;
                            while (true) {
                                var candidate = originalCandidate;
                                if (candidate.typeParameters) {
                                    var typeArgumentTypes;
                                    var typeArgumentsAreValid;
                                    if (typeArguments) {
                                        typeArgumentTypes = new Array(candidate.typeParameters.length);
                                        typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, false);
                                    }
                                    else {
                                        inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
                                        typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0;
                                        typeArgumentTypes = inferenceResult.inferredTypes;
                                    }
                                    if (!typeArgumentsAreValid) {
                                        break;
                                    }
                                    candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
                                }
                                if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) {
                                    break;
                                }
                                var index = excludeArgument ? ts.indexOf(excludeArgument, true) : -1;
                                if (index < 0) {
                                    return candidate;
                                }
                                excludeArgument[index] = false;
                            }
                            if (originalCandidate.typeParameters) {
                                var instantiatedCandidate = candidate;
                                if (typeArgumentsAreValid) {
                                    candidateForArgumentError = instantiatedCandidate;
                                }
                                else {
                                    candidateForTypeArgumentError = originalCandidate;
                                    if (!typeArguments) {
                                        resultOfFailedInference = inferenceResult;
                                    }
                                }
                            }
                            else {
                                ts.Debug.assert(originalCandidate === candidate);
                                candidateForArgumentError = originalCandidate;
                            }
                        }
                        return undefined;
                    }
                }
                function resolveCallExpression(node, candidatesOutArray) {
                    if (node.expression.kind === 90) {
                        var superType = checkSuperExpression(node.expression);
                        if (superType !== unknownType) {
                            return resolveCall(node, getSignaturesOfType(superType, 1), candidatesOutArray);
                        }
                        return resolveUntypedCall(node);
                    }
                    var funcType = checkExpression(node.expression);
                    var apparentType = getApparentType(funcType);
                    if (apparentType === unknownType) {
                        return resolveErrorCall(node);
                    }
                    var callSignatures = getSignaturesOfType(apparentType, 0);
                    var constructSignatures = getSignaturesOfType(apparentType, 1);
                    if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & 16384) && isTypeAssignableTo(funcType, globalFunctionType))) {
                        if (node.typeArguments) {
                            error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
                        }
                        return resolveUntypedCall(node);
                    }
                    if (!callSignatures.length) {
                        if (constructSignatures.length) {
                            error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
                        }
                        else {
                            error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
                        }
                        return resolveErrorCall(node);
                    }
                    return resolveCall(node, callSignatures, candidatesOutArray);
                }
                function resolveNewExpression(node, candidatesOutArray) {
                    if (node.arguments && languageVersion < 2) {
                        var spreadIndex = getSpreadArgumentIndex(node.arguments);
                        if (spreadIndex >= 0) {
                            error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher);
                        }
                    }
                    var expressionType = checkExpression(node.expression);
                    if (expressionType === anyType) {
                        if (node.typeArguments) {
                            error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
                        }
                        return resolveUntypedCall(node);
                    }
                    expressionType = getApparentType(expressionType);
                    if (expressionType === unknownType) {
                        return resolveErrorCall(node);
                    }
                    var constructSignatures = getSignaturesOfType(expressionType, 1);
                    if (constructSignatures.length) {
                        return resolveCall(node, constructSignatures, candidatesOutArray);
                    }
                    var callSignatures = getSignaturesOfType(expressionType, 0);
                    if (callSignatures.length) {
                        var signature = resolveCall(node, callSignatures, candidatesOutArray);
                        if (getReturnTypeOfSignature(signature) !== voidType) {
                            error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
                        }
                        return signature;
                    }
                    error(node, ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
                    return resolveErrorCall(node);
                }
                function resolveTaggedTemplateExpression(node, candidatesOutArray) {
                    var tagType = checkExpression(node.tag);
                    var apparentType = getApparentType(tagType);
                    if (apparentType === unknownType) {
                        return resolveErrorCall(node);
                    }
                    var callSignatures = getSignaturesOfType(apparentType, 0);
                    if (tagType === anyType || (!callSignatures.length && !(tagType.flags & 16384) && isTypeAssignableTo(tagType, globalFunctionType))) {
                        return resolveUntypedCall(node);
                    }
                    if (!callSignatures.length) {
                        error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
                        return resolveErrorCall(node);
                    }
                    return resolveCall(node, callSignatures, candidatesOutArray);
                }
                function getResolvedSignature(node, candidatesOutArray) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedSignature || candidatesOutArray) {
                        links.resolvedSignature = anySignature;
                        if (node.kind === 155) {
                            links.resolvedSignature = resolveCallExpression(node, candidatesOutArray);
                        }
                        else if (node.kind === 156) {
                            links.resolvedSignature = resolveNewExpression(node, candidatesOutArray);
                        }
                        else if (node.kind === 157) {
                            links.resolvedSignature = resolveTaggedTemplateExpression(node, candidatesOutArray);
                        }
                        else {
                            ts.Debug.fail("Branch in 'getResolvedSignature' should be unreachable.");
                        }
                    }
                    return links.resolvedSignature;
                }
                function checkCallExpression(node) {
                    checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
                    var signature = getResolvedSignature(node);
                    if (node.expression.kind === 90) {
                        return voidType;
                    }
                    if (node.kind === 156) {
                        var declaration = signature.declaration;
                        if (declaration && declaration.kind !== 133 && declaration.kind !== 137 && declaration.kind !== 141) {
                            if (compilerOptions.noImplicitAny) {
                                error(node, ts.Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
                            }
                            return anyType;
                        }
                    }
                    return getReturnTypeOfSignature(signature);
                }
                function checkTaggedTemplateExpression(node) {
                    return getReturnTypeOfSignature(getResolvedSignature(node));
                }
                function checkTypeAssertion(node) {
                    var exprType = checkExpression(node.expression);
                    var targetType = getTypeFromTypeNode(node.type);
                    if (produceDiagnostics && targetType !== unknownType) {
                        var widenedType = getWidenedType(exprType);
                        if (!(isTypeAssignableTo(targetType, widenedType))) {
                            checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
                        }
                    }
                    return targetType;
                }
                function getTypeAtPosition(signature, pos) {
                    if (pos >= 0) {
                        return signature.hasRestParameter ? pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType;
                    }
                    return signature.hasRestParameter ? getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]) : anyArrayType;
                }
                function assignContextualParameterTypes(signature, context, mapper) {
                    var len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
                    for (var i = 0; i < len; i++) {
                        var parameter = signature.parameters[i];
                        var links = getSymbolLinks(parameter);
                        links.type = instantiateType(getTypeAtPosition(context, i), mapper);
                    }
                    if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
                        var parameter = signature.parameters[signature.parameters.length - 1];
                        var links = getSymbolLinks(parameter);
                        links.type = instantiateType(getTypeOfSymbol(context.parameters[context.parameters.length - 1]), mapper);
                    }
                }
                function getReturnTypeFromBody(func, contextualMapper) {
                    var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
                    if (!func.body) {
                        return unknownType;
                    }
                    if (func.body.kind !== 174) {
                        var type = checkExpressionCached(func.body, contextualMapper);
                    }
                    else {
                        var types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper);
                        if (types.length === 0) {
                            return voidType;
                        }
                        var type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
                        if (!type) {
                            error(func, ts.Diagnostics.No_best_common_type_exists_among_return_expressions);
                            return unknownType;
                        }
                    }
                    if (!contextualSignature) {
                        reportErrorsFromWidening(func, type);
                    }
                    return getWidenedType(type);
                }
                function checkAndAggregateReturnExpressionTypes(body, contextualMapper) {
                    var aggregatedTypes = [];
                    ts.forEachReturnStatement(body, function (returnStatement) {
                        var expr = returnStatement.expression;
                        if (expr) {
                            var type = checkExpressionCached(expr, contextualMapper);
                            if (!ts.contains(aggregatedTypes, type)) {
                                aggregatedTypes.push(type);
                            }
                        }
                    });
                    return aggregatedTypes;
                }
                function bodyContainsAReturnStatement(funcBody) {
                    return ts.forEachReturnStatement(funcBody, function (returnStatement) {
                        return true;
                    });
                }
                function bodyContainsSingleThrowStatement(body) {
                    return (body.statements.length === 1) && (body.statements[0].kind === 190);
                }
                function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func, returnType) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    if (returnType === voidType || returnType === anyType) {
                        return;
                    }
                    if (ts.nodeIsMissing(func.body) || func.body.kind !== 174) {
                        return;
                    }
                    var bodyBlock = func.body;
                    if (bodyContainsAReturnStatement(bodyBlock)) {
                        return;
                    }
                    if (bodyContainsSingleThrowStatement(bodyBlock)) {
                        return;
                    }
                    error(func.type, ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement);
                }
                function checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper) {
                    ts.Debug.assert(node.kind !== 132 || ts.isObjectLiteralMethod(node));
                    var hasGrammarError = checkGrammarFunctionLikeDeclaration(node);
                    if (!hasGrammarError && node.kind === 160) {
                        checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
                    }
                    if (contextualMapper === identityMapper && isContextSensitive(node)) {
                        return anyFunctionType;
                    }
                    var links = getNodeLinks(node);
                    var type = getTypeOfSymbol(node.symbol);
                    if (!(links.flags & 64)) {
                        var contextualSignature = getContextualSignature(node);
                        if (!(links.flags & 64)) {
                            links.flags |= 64;
                            if (contextualSignature) {
                                var signature = getSignaturesOfType(type, 0)[0];
                                if (isContextSensitive(node)) {
                                    assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
                                }
                                if (!node.type) {
                                    signature.resolvedReturnType = resolvingType;
                                    var returnType = getReturnTypeFromBody(node, contextualMapper);
                                    if (signature.resolvedReturnType === resolvingType) {
                                        signature.resolvedReturnType = returnType;
                                    }
                                }
                            }
                            checkSignatureDeclaration(node);
                        }
                    }
                    if (produceDiagnostics && node.kind !== 132 && node.kind !== 131) {
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                    }
                    return type;
                }
                function checkFunctionExpressionOrObjectLiteralMethodBody(node) {
                    ts.Debug.assert(node.kind !== 132 || ts.isObjectLiteralMethod(node));
                    if (node.type) {
                        checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
                    }
                    if (node.body) {
                        if (node.body.kind === 174) {
                            checkSourceElement(node.body);
                        }
                        else {
                            var exprType = checkExpression(node.body);
                            if (node.type) {
                                checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined);
                            }
                            checkFunctionExpressionBodies(node.body);
                        }
                    }
                }
                function checkArithmeticOperandType(operand, type, diagnostic) {
                    if (!allConstituentTypesHaveKind(type, 1 | 132)) {
                        error(operand, diagnostic);
                        return false;
                    }
                    return true;
                }
                function checkReferenceExpression(n, invalidReferenceMessage, constantVariableMessage) {
                    function findSymbol(n) {
                        var symbol = getNodeLinks(n).resolvedSymbol;
                        return symbol && getExportSymbolOfValueSymbolIfExported(symbol);
                    }
                    function isReferenceOrErrorExpression(n) {
                        switch (n.kind) {
                            case 64:
                                var symbol = findSymbol(n);
                                return !symbol || symbol === unknownSymbol || symbol === argumentsSymbol || (symbol.flags & 3) !== 0;
                            case 153:
                                var symbol = findSymbol(n);
                                return !symbol || symbol === unknownSymbol || (symbol.flags & ~8) !== 0;
                            case 154:
                                return true;
                            case 159:
                                return isReferenceOrErrorExpression(n.expression);
                            default:
                                return false;
                        }
                    }
                    function isConstVariableReference(n) {
                        switch (n.kind) {
                            case 64:
                            case 153:
                                var symbol = findSymbol(n);
                                return symbol && (symbol.flags & 3) !== 0 && (getDeclarationFlagsFromSymbol(symbol) & 8192) !== 0;
                            case 154:
                                var index = n.argumentExpression;
                                var symbol = findSymbol(n.expression);
                                if (symbol && index && index.kind === 8) {
                                    var name = index.text;
                                    var prop = getPropertyOfType(getTypeOfSymbol(symbol), name);
                                    return prop && (prop.flags & 3) !== 0 && (getDeclarationFlagsFromSymbol(prop) & 8192) !== 0;
                                }
                                return false;
                            case 159:
                                return isConstVariableReference(n.expression);
                            default:
                                return false;
                        }
                    }
                    if (!isReferenceOrErrorExpression(n)) {
                        error(n, invalidReferenceMessage);
                        return false;
                    }
                    if (isConstVariableReference(n)) {
                        error(n, constantVariableMessage);
                        return false;
                    }
                    return true;
                }
                function checkDeleteExpression(node) {
                    if (node.parserContextFlags & 1 && node.expression.kind === 64) {
                        grammarErrorOnNode(node.expression, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
                    }
                    var operandType = checkExpression(node.expression);
                    return booleanType;
                }
                function checkTypeOfExpression(node) {
                    var operandType = checkExpression(node.expression);
                    return stringType;
                }
                function checkVoidExpression(node) {
                    var operandType = checkExpression(node.expression);
                    return undefinedType;
                }
                function checkPrefixUnaryExpression(node) {
                    if ((node.operator === 38 || node.operator === 39)) {
                        checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
                    }
                    var operandType = checkExpression(node.operand);
                    switch (node.operator) {
                        case 33:
                        case 34:
                        case 47:
                            if (someConstituentTypeHasKind(operandType, 1048576)) {
                                error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator));
                            }
                            return numberType;
                        case 46:
                            return booleanType;
                        case 38:
                        case 39:
                            var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
                            if (ok) {
                                checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
                            }
                            return numberType;
                    }
                    return unknownType;
                }
                function checkPostfixUnaryExpression(node) {
                    checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
                    var operandType = checkExpression(node.operand);
                    var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
                    if (ok) {
                        checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
                    }
                    return numberType;
                }
                function someConstituentTypeHasKind(type, kind) {
                    if (type.flags & kind) {
                        return true;
                    }
                    if (type.flags & 16384) {
                        var types = type.types;
                        for (var i = 0; i < types.length; i++) {
                            if (types[i].flags & kind) {
                                return true;
                            }
                        }
                        return false;
                    }
                    return false;
                }
                function allConstituentTypesHaveKind(type, kind) {
                    if (type.flags & kind) {
                        return true;
                    }
                    if (type.flags & 16384) {
                        var types = type.types;
                        for (var i = 0; i < types.length; i++) {
                            if (!(types[i].flags & kind)) {
                                return false;
                            }
                        }
                        return true;
                    }
                    return false;
                }
                function isConstEnumObjectType(type) {
                    return type.flags & (48128 | 32768) && type.symbol && isConstEnumSymbol(type.symbol);
                }
                function isConstEnumSymbol(symbol) {
                    return (symbol.flags & 128) !== 0;
                }
                function checkInstanceOfExpression(node, leftType, rightType) {
                    if (allConstituentTypesHaveKind(leftType, 1049086)) {
                        error(node.left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    if (!(rightType.flags & 1 || isTypeSubtypeOf(rightType, globalFunctionType))) {
                        error(node.right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
                    }
                    return booleanType;
                }
                function checkInExpression(node, leftType, rightType) {
                    if (!allConstituentTypesHaveKind(leftType, 1 | 258 | 132 | 1048576)) {
                        error(node.left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
                    }
                    if (!allConstituentTypesHaveKind(rightType, 1 | 48128 | 512)) {
                        error(node.right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    return booleanType;
                }
                function checkObjectLiteralAssignment(node, sourceType, contextualMapper) {
                    var properties = node.properties;
                    for (var i = 0; i < properties.length; i++) {
                        var p = properties[i];
                        if (p.kind === 218 || p.kind === 219) {
                            var name = p.name;
                            var type = sourceType.flags & 1 ? sourceType : getTypeOfPropertyOfType(sourceType, name.text) || isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, 1) || getIndexTypeOfType(sourceType, 0);
                            if (type) {
                                checkDestructuringAssignment(p.initializer || name, type);
                            }
                            else {
                                error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), ts.declarationNameToString(name));
                            }
                        }
                        else {
                            error(p, ts.Diagnostics.Property_assignment_expected);
                        }
                    }
                    return sourceType;
                }
                function checkArrayLiteralAssignment(node, sourceType, contextualMapper) {
                    if (!isArrayLikeType(sourceType)) {
                        error(node, ts.Diagnostics.Type_0_is_not_an_array_type, typeToString(sourceType));
                        return sourceType;
                    }
                    var elements = node.elements;
                    for (var i = 0; i < elements.length; i++) {
                        var e = elements[i];
                        if (e.kind !== 172) {
                            if (e.kind !== 171) {
                                var propName = "" + i;
                                var type = sourceType.flags & 1 ? sourceType : isTupleLikeType(sourceType) ? getTypeOfPropertyOfType(sourceType, propName) : getIndexTypeOfType(sourceType, 1);
                                if (type) {
                                    checkDestructuringAssignment(e, type, contextualMapper);
                                }
                                else {
                                    if (isTupleType(sourceType)) {
                                        error(e, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), sourceType.elementTypes.length, elements.length);
                                    }
                                    else {
                                        error(e, ts.Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
                                    }
                                }
                            }
                            else {
                                if (i === elements.length - 1) {
                                    checkReferenceAssignment(e.expression, sourceType, contextualMapper);
                                }
                                else {
                                    error(e, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
                                }
                            }
                        }
                    }
                    return sourceType;
                }
                function checkDestructuringAssignment(target, sourceType, contextualMapper) {
                    if (target.kind === 167 && target.operatorToken.kind === 52) {
                        checkBinaryExpression(target, contextualMapper);
                        target = target.left;
                    }
                    if (target.kind === 152) {
                        return checkObjectLiteralAssignment(target, sourceType, contextualMapper);
                    }
                    if (target.kind === 151) {
                        return checkArrayLiteralAssignment(target, sourceType, contextualMapper);
                    }
                    return checkReferenceAssignment(target, sourceType, contextualMapper);
                }
                function checkReferenceAssignment(target, sourceType, contextualMapper) {
                    var targetType = checkExpression(target, contextualMapper);
                    if (checkReferenceExpression(target, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
                        checkTypeAssignableTo(sourceType, targetType, target, undefined);
                    }
                    return sourceType;
                }
                function checkBinaryExpression(node, contextualMapper) {
                    if (ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) {
                        checkGrammarEvalOrArgumentsInStrictMode(node, node.left);
                    }
                    var operator = node.operatorToken.kind;
                    if (operator === 52 && (node.left.kind === 152 || node.left.kind === 151)) {
                        return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper);
                    }
                    var leftType = checkExpression(node.left, contextualMapper);
                    var rightType = checkExpression(node.right, contextualMapper);
                    switch (operator) {
                        case 35:
                        case 55:
                        case 36:
                        case 56:
                        case 37:
                        case 57:
                        case 34:
                        case 54:
                        case 40:
                        case 58:
                        case 41:
                        case 59:
                        case 42:
                        case 60:
                        case 44:
                        case 62:
                        case 45:
                        case 63:
                        case 43:
                        case 61:
                            if (leftType.flags & (32 | 64))
                                leftType = rightType;
                            if (rightType.flags & (32 | 64))
                                rightType = leftType;
                            var suggestedOperator;
                            if ((leftType.flags & 8) && (rightType.flags & 8) && (suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) {
                                error(node, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(node.operatorToken.kind), ts.tokenToString(suggestedOperator));
                            }
                            else {
                                var leftOk = checkArithmeticOperandType(node.left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
                                var rightOk = checkArithmeticOperandType(node.right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
                                if (leftOk && rightOk) {
                                    checkAssignmentOperator(numberType);
                                }
                            }
                            return numberType;
                        case 33:
                        case 53:
                            if (leftType.flags & (32 | 64))
                                leftType = rightType;
                            if (rightType.flags & (32 | 64))
                                rightType = leftType;
                            var resultType;
                            if (allConstituentTypesHaveKind(leftType, 132) && allConstituentTypesHaveKind(rightType, 132)) {
                                resultType = numberType;
                            }
                            else {
                                if (allConstituentTypesHaveKind(leftType, 258) || allConstituentTypesHaveKind(rightType, 258)) {
                                    resultType = stringType;
                                }
                                else if (leftType.flags & 1 || rightType.flags & 1) {
                                    resultType = anyType;
                                }
                                if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
                                    return resultType;
                                }
                            }
                            if (!resultType) {
                                reportOperatorError();
                                return anyType;
                            }
                            if (operator === 53) {
                                checkAssignmentOperator(resultType);
                            }
                            return resultType;
                        case 24:
                        case 25:
                        case 26:
                        case 27:
                            if (!checkForDisallowedESSymbolOperand(operator)) {
                                return booleanType;
                            }
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                            if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) {
                                reportOperatorError();
                            }
                            return booleanType;
                        case 86:
                            return checkInstanceOfExpression(node, leftType, rightType);
                        case 85:
                            return checkInExpression(node, leftType, rightType);
                        case 48:
                            return rightType;
                        case 49:
                            return getUnionType([
                                leftType,
                                rightType
                            ]);
                        case 52:
                            checkAssignmentOperator(rightType);
                            return rightType;
                        case 23:
                            return rightType;
                    }
                    function checkForDisallowedESSymbolOperand(operator) {
                        var offendingSymbolOperand = someConstituentTypeHasKind(leftType, 1048576) ? node.left : someConstituentTypeHasKind(rightType, 1048576) ? node.right : undefined;
                        if (offendingSymbolOperand) {
                            error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator));
                            return false;
                        }
                        return true;
                    }
                    function getSuggestedBooleanOperator(operator) {
                        switch (operator) {
                            case 44:
                            case 62:
                                return 49;
                            case 45:
                            case 63:
                                return 31;
                            case 43:
                            case 61:
                                return 48;
                            default:
                                return undefined;
                        }
                    }
                    function checkAssignmentOperator(valueType) {
                        if (produceDiagnostics && operator >= 52 && operator <= 63) {
                            var ok = checkReferenceExpression(node.left, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
                            if (ok) {
                                checkTypeAssignableTo(valueType, leftType, node.left, undefined);
                            }
                        }
                    }
                    function reportOperatorError() {
                        error(node, ts.Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, ts.tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType));
                    }
                }
                function checkYieldExpression(node) {
                    if (!(node.parserContextFlags & 4)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
                    }
                    else {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expressions_are_not_currently_supported);
                    }
                }
                function checkConditionalExpression(node, contextualMapper) {
                    checkExpression(node.condition);
                    var type1 = checkExpression(node.whenTrue, contextualMapper);
                    var type2 = checkExpression(node.whenFalse, contextualMapper);
                    return getUnionType([
                        type1,
                        type2
                    ]);
                }
                function checkTemplateExpression(node) {
                    ts.forEach(node.templateSpans, function (templateSpan) {
                        checkExpression(templateSpan.expression);
                    });
                    return stringType;
                }
                function checkExpressionWithContextualType(node, contextualType, contextualMapper) {
                    var saveContextualType = node.contextualType;
                    node.contextualType = contextualType;
                    var result = checkExpression(node, contextualMapper);
                    node.contextualType = saveContextualType;
                    return result;
                }
                function checkExpressionCached(node, contextualMapper) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = checkExpression(node, contextualMapper);
                    }
                    return links.resolvedType;
                }
                function checkPropertyAssignment(node, contextualMapper) {
                    if (node.name.kind === 126) {
                        checkComputedPropertyName(node.name);
                    }
                    return checkExpression(node.initializer, contextualMapper);
                }
                function checkObjectLiteralMethod(node, contextualMapper) {
                    checkGrammarMethod(node);
                    if (node.name.kind === 126) {
                        checkComputedPropertyName(node.name);
                    }
                    var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
                    return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
                }
                function instantiateTypeWithSingleGenericCallSignature(node, type, contextualMapper) {
                    if (contextualMapper && contextualMapper !== identityMapper) {
                        var signature = getSingleCallSignature(type);
                        if (signature && signature.typeParameters) {
                            var contextualType = getContextualType(node);
                            if (contextualType) {
                                var contextualSignature = getSingleCallSignature(contextualType);
                                if (contextualSignature && !contextualSignature.typeParameters) {
                                    return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
                                }
                            }
                        }
                    }
                    return type;
                }
                function checkExpression(node, contextualMapper) {
                    return checkExpressionOrQualifiedName(node, contextualMapper);
                }
                function checkExpressionOrQualifiedName(node, contextualMapper) {
                    var type;
                    if (node.kind == 125) {
                        type = checkQualifiedName(node);
                    }
                    else {
                        var uninstantiatedType = checkExpressionWorker(node, contextualMapper);
                        type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
                    }
                    if (isConstEnumObjectType(type)) {
                        var ok = (node.parent.kind === 153 && node.parent.expression === node) || (node.parent.kind === 154 && node.parent.expression === node) || ((node.kind === 64 || node.kind === 125) && isInRightSideOfImportOrExportAssignment(node));
                        if (!ok) {
                            error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
                        }
                    }
                    return type;
                }
                function checkNumericLiteral(node) {
                    checkGrammarNumbericLiteral(node);
                    return numberType;
                }
                function checkExpressionWorker(node, contextualMapper) {
                    switch (node.kind) {
                        case 64:
                            return checkIdentifier(node);
                        case 92:
                            return checkThisExpression(node);
                        case 90:
                            return checkSuperExpression(node);
                        case 88:
                            return nullType;
                        case 94:
                        case 79:
                            return booleanType;
                        case 7:
                            return checkNumericLiteral(node);
                        case 169:
                            return checkTemplateExpression(node);
                        case 8:
                        case 10:
                            return stringType;
                        case 9:
                            return globalRegExpType;
                        case 151:
                            return checkArrayLiteral(node, contextualMapper);
                        case 152:
                            return checkObjectLiteral(node, contextualMapper);
                        case 153:
                            return checkPropertyAccessExpression(node);
                        case 154:
                            return checkIndexedAccess(node);
                        case 155:
                        case 156:
                            return checkCallExpression(node);
                        case 157:
                            return checkTaggedTemplateExpression(node);
                        case 158:
                            return checkTypeAssertion(node);
                        case 159:
                            return checkExpression(node.expression, contextualMapper);
                        case 160:
                        case 161:
                            return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
                        case 163:
                            return checkTypeOfExpression(node);
                        case 162:
                            return checkDeleteExpression(node);
                        case 164:
                            return checkVoidExpression(node);
                        case 165:
                            return checkPrefixUnaryExpression(node);
                        case 166:
                            return checkPostfixUnaryExpression(node);
                        case 167:
                            return checkBinaryExpression(node, contextualMapper);
                        case 168:
                            return checkConditionalExpression(node, contextualMapper);
                        case 171:
                            return checkSpreadElementExpression(node, contextualMapper);
                        case 172:
                            return undefinedType;
                        case 170:
                            checkYieldExpression(node);
                            return unknownType;
                    }
                    return unknownType;
                }
                function checkTypeParameter(node) {
                    if (node.expression) {
                        grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected);
                    }
                    checkSourceElement(node.constraint);
                    if (produceDiagnostics) {
                        checkTypeParameterHasIllegalReferencesInConstraint(node);
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_parameter_name_cannot_be_0);
                    }
                }
                function checkParameter(node) {
                    checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                    checkVariableLikeDeclaration(node);
                    var func = ts.getContainingFunction(node);
                    if (node.flags & 112) {
                        func = ts.getContainingFunction(node);
                        if (!(func.kind === 133 && ts.nodeIsPresent(func.body))) {
                            error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
                        }
                    }
                    if (node.questionToken && ts.isBindingPattern(node.name) && func.body) {
                        error(node, ts.Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
                    }
                    if (node.dotDotDotToken) {
                        if (!isArrayType(getTypeOfSymbol(node.symbol))) {
                            error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type);
                        }
                    }
                }
                function checkSignatureDeclaration(node) {
                    if (node.kind === 138) {
                        checkGrammarIndexSignature(node);
                    }
                    else if (node.kind === 140 || node.kind === 195 || node.kind === 141 || node.kind === 136 || node.kind === 133 || node.kind === 137) {
                        checkGrammarFunctionLikeDeclaration(node);
                    }
                    checkTypeParameters(node.typeParameters);
                    ts.forEach(node.parameters, checkParameter);
                    if (node.type) {
                        checkSourceElement(node.type);
                    }
                    if (produceDiagnostics) {
                        checkCollisionWithArgumentsInGeneratedCode(node);
                        if (compilerOptions.noImplicitAny && !node.type) {
                            switch (node.kind) {
                                case 137:
                                    error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
                                    break;
                                case 136:
                                    error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
                                    break;
                            }
                        }
                    }
                    checkSpecializedSignatureDeclaration(node);
                }
                function checkTypeForDuplicateIndexSignatures(node) {
                    if (node.kind === 197) {
                        var nodeSymbol = getSymbolOfNode(node);
                        if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) {
                            return;
                        }
                    }
                    var indexSymbol = getIndexSymbol(getSymbolOfNode(node));
                    if (indexSymbol) {
                        var seenNumericIndexer = false;
                        var seenStringIndexer = false;
                        for (var i = 0, len = indexSymbol.declarations.length; i < len; ++i) {
                            var declaration = indexSymbol.declarations[i];
                            if (declaration.parameters.length === 1 && declaration.parameters[0].type) {
                                switch (declaration.parameters[0].type.kind) {
                                    case 120:
                                        if (!seenStringIndexer) {
                                            seenStringIndexer = true;
                                        }
                                        else {
                                            error(declaration, ts.Diagnostics.Duplicate_string_index_signature);
                                        }
                                        break;
                                    case 118:
                                        if (!seenNumericIndexer) {
                                            seenNumericIndexer = true;
                                        }
                                        else {
                                            error(declaration, ts.Diagnostics.Duplicate_number_index_signature);
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
                function checkPropertyDeclaration(node) {
                    checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
                    checkVariableLikeDeclaration(node);
                }
                function checkMethodDeclaration(node) {
                    checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
                    checkFunctionLikeDeclaration(node);
                }
                function checkConstructorDeclaration(node) {
                    checkSignatureDeclaration(node);
                    checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
                    checkSourceElement(node.body);
                    var symbol = getSymbolOfNode(node);
                    var firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind);
                    if (node === firstDeclaration) {
                        checkFunctionOrConstructorSymbol(symbol);
                    }
                    if (ts.nodeIsMissing(node.body)) {
                        return;
                    }
                    if (!produceDiagnostics) {
                        return;
                    }
                    function isSuperCallExpression(n) {
                        return n.kind === 155 && n.expression.kind === 90;
                    }
                    function containsSuperCall(n) {
                        if (isSuperCallExpression(n)) {
                            return true;
                        }
                        switch (n.kind) {
                            case 160:
                            case 195:
                            case 161:
                            case 152:
                                return false;
                            default:
                                return ts.forEachChild(n, containsSuperCall);
                        }
                    }
                    function markThisReferencesAsErrors(n) {
                        if (n.kind === 92) {
                            error(n, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
                        }
                        else if (n.kind !== 160 && n.kind !== 195) {
                            ts.forEachChild(n, markThisReferencesAsErrors);
                        }
                    }
                    function isInstancePropertyWithInitializer(n) {
                        return n.kind === 130 && !(n.flags & 128) && !!n.initializer;
                    }
                    if (ts.getClassBaseTypeNode(node.parent)) {
                        if (containsSuperCall(node.body)) {
                            var superCallShouldBeFirst = ts.forEach(node.parent.members, isInstancePropertyWithInitializer) || ts.forEach(node.parameters, function (p) {
                                return p.flags & (16 | 32 | 64);
                            });
                            if (superCallShouldBeFirst) {
                                var statements = node.body.statements;
                                if (!statements.length || statements[0].kind !== 177 || !isSuperCallExpression(statements[0].expression)) {
                                    error(node, ts.Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties);
                                }
                                else {
                                    markThisReferencesAsErrors(statements[0].expression);
                                }
                            }
                        }
                        else {
                            error(node, ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
                        }
                    }
                }
                function checkAccessorDeclaration(node) {
                    if (produceDiagnostics) {
                        checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
                        if (node.kind === 134) {
                            if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) {
                                error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
                            }
                        }
                        if (!ts.hasDynamicName(node)) {
                            var otherKind = node.kind === 134 ? 135 : 134;
                            var otherAccessor = ts.getDeclarationOfKind(node.symbol, otherKind);
                            if (otherAccessor) {
                                if (((node.flags & 112) !== (otherAccessor.flags & 112))) {
                                    error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
                                }
                                var currentAccessorType = getAnnotatedAccessorType(node);
                                var otherAccessorType = getAnnotatedAccessorType(otherAccessor);
                                if (currentAccessorType && otherAccessorType) {
                                    if (!isTypeIdenticalTo(currentAccessorType, otherAccessorType)) {
                                        error(node, ts.Diagnostics.get_and_set_accessor_must_have_the_same_type);
                                    }
                                }
                            }
                        }
                        checkAndStoreTypeOfAccessors(getSymbolOfNode(node));
                    }
                    checkFunctionLikeDeclaration(node);
                }
                function checkTypeReference(node) {
                    checkGrammarTypeArguments(node, node.typeArguments);
                    var type = getTypeFromTypeReferenceNode(node);
                    if (type !== unknownType && node.typeArguments) {
                        var len = node.typeArguments.length;
                        for (var i = 0; i < len; i++) {
                            checkSourceElement(node.typeArguments[i]);
                            var constraint = getConstraintOfTypeParameter(type.target.typeParameters[i]);
                            if (produceDiagnostics && constraint) {
                                var typeArgument = type.typeArguments[i];
                                checkTypeAssignableTo(typeArgument, constraint, node, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
                            }
                        }
                    }
                }
                function checkTypeQuery(node) {
                    getTypeFromTypeQueryNode(node);
                }
                function checkTypeLiteral(node) {
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
                        checkIndexConstraints(type);
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function checkArrayType(node) {
                    checkSourceElement(node.elementType);
                }
                function checkTupleType(node) {
                    var hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes);
                    if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) {
                        grammarErrorOnNode(node, ts.Diagnostics.A_tuple_type_element_list_cannot_be_empty);
                    }
                    ts.forEach(node.elementTypes, checkSourceElement);
                }
                function checkUnionType(node) {
                    ts.forEach(node.types, checkSourceElement);
                }
                function isPrivateWithinAmbient(node) {
                    return (node.flags & 32) && ts.isInAmbientContext(node);
                }
                function checkSpecializedSignatureDeclaration(signatureDeclarationNode) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    var signature = getSignatureFromDeclaration(signatureDeclarationNode);
                    if (!signature.hasStringLiterals) {
                        return;
                    }
                    if (ts.nodeIsPresent(signatureDeclarationNode.body)) {
                        error(signatureDeclarationNode, ts.Diagnostics.A_signature_with_an_implementation_cannot_use_a_string_literal_type);
                        return;
                    }
                    var signaturesToCheck;
                    if (!signatureDeclarationNode.name && signatureDeclarationNode.parent && signatureDeclarationNode.parent.kind === 197) {
                        ts.Debug.assert(signatureDeclarationNode.kind === 136 || signatureDeclarationNode.kind === 137);
                        var signatureKind = signatureDeclarationNode.kind === 136 ? 0 : 1;
                        var containingSymbol = getSymbolOfNode(signatureDeclarationNode.parent);
                        var containingType = getDeclaredTypeOfSymbol(containingSymbol);
                        signaturesToCheck = getSignaturesOfType(containingType, signatureKind);
                    }
                    else {
                        signaturesToCheck = getSignaturesOfSymbol(getSymbolOfNode(signatureDeclarationNode));
                    }
                    for (var i = 0; i < signaturesToCheck.length; i++) {
                        var otherSignature = signaturesToCheck[i];
                        if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
                            return;
                        }
                    }
                    error(signatureDeclarationNode, ts.Diagnostics.Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature);
                }
                function getEffectiveDeclarationFlags(n, flagsToCheck) {
                    var flags = ts.getCombinedNodeFlags(n);
                    if (n.parent.kind !== 197 && ts.isInAmbientContext(n)) {
                        if (!(flags & 2)) {
                            flags |= 1;
                        }
                        flags |= 2;
                    }
                    return flags & flagsToCheck;
                }
                function checkFunctionOrConstructorSymbol(symbol) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    function getCanonicalOverload(overloads, implementation) {
                        var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
                        return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
                    }
                    function checkFlagAgreementBetweenOverloads(overloads, implementation, flagsToCheck, someOverloadFlags, allOverloadFlags) {
                        var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
                        if (someButNotAllOverloadFlags !== 0) {
                            var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
                            ts.forEach(overloads, function (o) {
                                var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
                                if (deviation & 1) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported);
                                }
                                else if (deviation & 2) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
                                }
                                else if (deviation & (32 | 64)) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
                                }
                            });
                        }
                    }
                    function checkQuestionTokenAgreementBetweenOverloads(overloads, implementation, someHaveQuestionToken, allHaveQuestionToken) {
                        if (someHaveQuestionToken !== allHaveQuestionToken) {
                            var canonicalHasQuestionToken = ts.hasQuestionToken(getCanonicalOverload(overloads, implementation));
                            ts.forEach(overloads, function (o) {
                                var deviation = ts.hasQuestionToken(o) !== canonicalHasQuestionToken;
                                if (deviation) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_optional_or_required);
                                }
                            });
                        }
                    }
                    var flagsToCheck = 1 | 2 | 32 | 64;
                    var someNodeFlags = 0;
                    var allNodeFlags = flagsToCheck;
                    var someHaveQuestionToken = false;
                    var allHaveQuestionToken = true;
                    var hasOverloads = false;
                    var bodyDeclaration;
                    var lastSeenNonAmbientDeclaration;
                    var previousDeclaration;
                    var declarations = symbol.declarations;
                    var isConstructor = (symbol.flags & 16384) !== 0;
                    function reportImplementationExpectedError(node) {
                        if (node.name && ts.getFullWidth(node.name) === 0) {
                            return;
                        }
                        var seen = false;
                        var subsequentNode = ts.forEachChild(node.parent, function (c) {
                            if (seen) {
                                return c;
                            }
                            else {
                                seen = c === node;
                            }
                        });
                        if (subsequentNode) {
                            if (subsequentNode.kind === node.kind) {
                                var errorNode = subsequentNode.name || subsequentNode;
                                if (node.name && subsequentNode.name && node.name.text === subsequentNode.name.text) {
                                    ts.Debug.assert(node.kind === 132 || node.kind === 131);
                                    ts.Debug.assert((node.flags & 128) !== (subsequentNode.flags & 128));
                                    var diagnostic = node.flags & 128 ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static;
                                    error(errorNode, diagnostic);
                                    return;
                                }
                                else if (ts.nodeIsPresent(subsequentNode.body)) {
                                    error(errorNode, ts.Diagnostics.Function_implementation_name_must_be_0, ts.declarationNameToString(node.name));
                                    return;
                                }
                            }
                        }
                        var errorNode = node.name || node;
                        if (isConstructor) {
                            error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing);
                        }
                        else {
                            error(errorNode, ts.Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration);
                        }
                    }
                    var isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & 1536;
                    var duplicateFunctionDeclaration = false;
                    var multipleConstructorImplementation = false;
                    for (var i = 0; i < declarations.length; i++) {
                        var node = declarations[i];
                        var inAmbientContext = ts.isInAmbientContext(node);
                        var inAmbientContextOrInterface = node.parent.kind === 197 || node.parent.kind === 143 || inAmbientContext;
                        if (inAmbientContextOrInterface) {
                            previousDeclaration = undefined;
                        }
                        if (node.kind === 195 || node.kind === 132 || node.kind === 131 || node.kind === 133) {
                            var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
                            someNodeFlags |= currentNodeFlags;
                            allNodeFlags &= currentNodeFlags;
                            someHaveQuestionToken = someHaveQuestionToken || ts.hasQuestionToken(node);
                            allHaveQuestionToken = allHaveQuestionToken && ts.hasQuestionToken(node);
                            if (ts.nodeIsPresent(node.body) && bodyDeclaration) {
                                if (isConstructor) {
                                    multipleConstructorImplementation = true;
                                }
                                else {
                                    duplicateFunctionDeclaration = true;
                                }
                            }
                            else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
                                reportImplementationExpectedError(previousDeclaration);
                            }
                            if (ts.nodeIsPresent(node.body)) {
                                if (!bodyDeclaration) {
                                    bodyDeclaration = node;
                                }
                            }
                            else {
                                hasOverloads = true;
                            }
                            previousDeclaration = node;
                            if (!inAmbientContextOrInterface) {
                                lastSeenNonAmbientDeclaration = node;
                            }
                        }
                    }
                    if (multipleConstructorImplementation) {
                        ts.forEach(declarations, function (declaration) {
                            error(declaration, ts.Diagnostics.Multiple_constructor_implementations_are_not_allowed);
                        });
                    }
                    if (duplicateFunctionDeclaration) {
                        ts.forEach(declarations, function (declaration) {
                            error(declaration.name, ts.Diagnostics.Duplicate_function_implementation);
                        });
                    }
                    if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) {
                        reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
                    }
                    if (hasOverloads) {
                        checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
                        checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);
                        if (bodyDeclaration) {
                            var signatures = getSignaturesOfSymbol(symbol);
                            var bodySignature = getSignatureFromDeclaration(bodyDeclaration);
                            if (!bodySignature.hasStringLiterals) {
                                for (var i = 0, len = signatures.length; i < len; ++i) {
                                    if (!signatures[i].hasStringLiterals && !isSignatureAssignableTo(bodySignature, signatures[i])) {
                                        error(signatures[i].declaration, ts.Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                function checkExportsOnMergedDeclarations(node) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    var symbol;
                    var symbol = node.localSymbol;
                    if (!symbol) {
                        symbol = getSymbolOfNode(node);
                        if (!(symbol.flags & 7340032)) {
                            return;
                        }
                    }
                    if (ts.getDeclarationOfKind(symbol, node.kind) !== node) {
                        return;
                    }
                    var exportedDeclarationSpaces = 0;
                    var nonExportedDeclarationSpaces = 0;
                    ts.forEach(symbol.declarations, function (d) {
                        var declarationSpaces = getDeclarationSpaces(d);
                        if (getEffectiveDeclarationFlags(d, 1)) {
                            exportedDeclarationSpaces |= declarationSpaces;
                        }
                        else {
                            nonExportedDeclarationSpaces |= declarationSpaces;
                        }
                    });
                    var commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
                    if (commonDeclarationSpace) {
                        ts.forEach(symbol.declarations, function (d) {
                            if (getDeclarationSpaces(d) & commonDeclarationSpace) {
                                error(d.name, ts.Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, ts.declarationNameToString(d.name));
                            }
                        });
                    }
                    function getDeclarationSpaces(d) {
                        switch (d.kind) {
                            case 197:
                                return 2097152;
                            case 200:
                                return d.name.kind === 8 || ts.getModuleInstanceState(d) !== 0 ? 4194304 | 1048576 : 4194304;
                            case 196:
                            case 199:
                                return 2097152 | 1048576;
                            case 203:
                                var result = 0;
                                var target = resolveAlias(getSymbolOfNode(d));
                                ts.forEach(target.declarations, function (d) {
                                    result |= getDeclarationSpaces(d);
                                });
                                return result;
                            default:
                                return 1048576;
                        }
                    }
                }
                function checkFunctionDeclaration(node) {
                    if (produceDiagnostics) {
                        checkFunctionLikeDeclaration(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                }
                function checkFunctionLikeDeclaration(node) {
                    checkSignatureDeclaration(node);
                    if (node.name && node.name.kind === 126) {
                        checkComputedPropertyName(node.name);
                    }
                    if (!ts.hasDynamicName(node)) {
                        var symbol = getSymbolOfNode(node);
                        var localSymbol = node.localSymbol || symbol;
                        var firstDeclaration = ts.getDeclarationOfKind(localSymbol, node.kind);
                        if (node === firstDeclaration) {
                            checkFunctionOrConstructorSymbol(localSymbol);
                        }
                        if (symbol.parent) {
                            if (ts.getDeclarationOfKind(symbol, node.kind) === node) {
                                checkFunctionOrConstructorSymbol(symbol);
                            }
                        }
                    }
                    checkSourceElement(node.body);
                    if (node.type && !isAccessor(node.kind)) {
                        checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
                    }
                    if (compilerOptions.noImplicitAny && ts.nodeIsMissing(node.body) && !node.type && !isPrivateWithinAmbient(node)) {
                        reportImplicitAnyError(node, anyType);
                    }
                }
                function checkBlock(node) {
                    if (node.kind === 174) {
                        checkGrammarStatementInAmbientContext(node);
                    }
                    ts.forEach(node.statements, checkSourceElement);
                    if (ts.isFunctionBlock(node) || node.kind === 201) {
                        checkFunctionExpressionBodies(node);
                    }
                }
                function checkCollisionWithArgumentsInGeneratedCode(node) {
                    if (!ts.hasRestParameters(node) || ts.isInAmbientContext(node) || ts.nodeIsMissing(node.body)) {
                        return;
                    }
                    ts.forEach(node.parameters, function (p) {
                        if (p.name && !ts.isBindingPattern(p.name) && p.name.text === argumentsSymbol.name) {
                            error(p, ts.Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters);
                        }
                    });
                }
                function needCollisionCheckForIdentifier(node, identifier, name) {
                    if (!(identifier && identifier.text === name)) {
                        return false;
                    }
                    if (node.kind === 130 || node.kind === 129 || node.kind === 132 || node.kind === 131 || node.kind === 134 || node.kind === 135) {
                        return false;
                    }
                    if (ts.isInAmbientContext(node)) {
                        return false;
                    }
                    var root = getRootDeclaration(node);
                    if (root.kind === 128 && ts.nodeIsMissing(root.parent.body)) {
                        return false;
                    }
                    return true;
                }
                function checkCollisionWithCapturedThisVariable(node, name) {
                    if (needCollisionCheckForIdentifier(node, name, "_this")) {
                        potentialThisCollisions.push(node);
                    }
                }
                function checkIfThisIsCapturedInEnclosingScope(node) {
                    var current = node;
                    while (current) {
                        if (getNodeCheckFlags(current) & 4) {
                            var isDeclaration = node.kind !== 64;
                            if (isDeclaration) {
                                error(node.name, ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
                            }
                            else {
                                error(node, ts.Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
                            }
                            return;
                        }
                        current = current.parent;
                    }
                }
                function checkCollisionWithCapturedSuperVariable(node, name) {
                    if (!needCollisionCheckForIdentifier(node, name, "_super")) {
                        return;
                    }
                    var enclosingClass = ts.getAncestor(node, 196);
                    if (!enclosingClass || ts.isInAmbientContext(enclosingClass)) {
                        return;
                    }
                    if (ts.getClassBaseTypeNode(enclosingClass)) {
                        var isDeclaration = node.kind !== 64;
                        if (isDeclaration) {
                            error(node, ts.Diagnostics.Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference);
                        }
                        else {
                            error(node, ts.Diagnostics.Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference);
                        }
                    }
                }
                function checkCollisionWithRequireExportsInGeneratedCode(node, name) {
                    if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
                        return;
                    }
                    if (node.kind === 200 && ts.getModuleInstanceState(node) !== 1) {
                        return;
                    }
                    var parent = getDeclarationContainer(node);
                    if (parent.kind === 221 && ts.isExternalModule(parent)) {
                        error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, ts.declarationNameToString(name), ts.declarationNameToString(name));
                    }
                }
                function checkVarDeclaredNamesNotShadowed(node) {
                    if (node.initializer && (ts.getCombinedNodeFlags(node) & 12288) === 0) {
                        var symbol = getSymbolOfNode(node);
                        if (symbol.flags & 1) {
                            var localDeclarationSymbol = resolveName(node, node.name.text, 3, undefined, undefined);
                            if (localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & 2) {
                                if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & 12288) {
                                    var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 194);
                                    var container = varDeclList.parent.kind === 175 && varDeclList.parent.parent;
                                    var namesShareScope = container && (container.kind === 174 && ts.isFunctionLike(container.parent) || (container.kind === 201 && container.kind === 200) || container.kind === 221);
                                    if (!namesShareScope) {
                                        var name = symbolToString(localDeclarationSymbol);
                                        error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
                                    }
                                }
                            }
                        }
                    }
                }
                function isParameterDeclaration(node) {
                    while (node.kind === 150) {
                        node = node.parent.parent;
                    }
                    return node.kind === 128;
                }
                function checkParameterInitializer(node) {
                    if (getRootDeclaration(node).kind === 128) {
                        var func = ts.getContainingFunction(node);
                        visit(node.initializer);
                    }
                    function visit(n) {
                        if (n.kind === 64) {
                            var referencedSymbol = getNodeLinks(n).resolvedSymbol;
                            if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, 107455) === referencedSymbol) {
                                if (referencedSymbol.valueDeclaration.kind === 128) {
                                    if (referencedSymbol.valueDeclaration === node) {
                                        error(n, ts.Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, ts.declarationNameToString(node.name));
                                        return;
                                    }
                                    if (referencedSymbol.valueDeclaration.pos < node.pos) {
                                        return;
                                    }
                                }
                                error(n, ts.Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(node.name), ts.declarationNameToString(n));
                            }
                        }
                        else {
                            ts.forEachChild(n, visit);
                        }
                    }
                }
                function checkVariableLikeDeclaration(node) {
                    checkSourceElement(node.type);
                    if (node.name.kind === 126) {
                        checkComputedPropertyName(node.name);
                        if (node.initializer) {
                            checkExpressionCached(node.initializer);
                        }
                    }
                    if (ts.isBindingPattern(node.name)) {
                        ts.forEach(node.name.elements, checkSourceElement);
                    }
                    if (node.initializer && getRootDeclaration(node).kind === 128 && ts.nodeIsMissing(ts.getContainingFunction(node).body)) {
                        error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
                        return;
                    }
                    if (ts.isBindingPattern(node.name)) {
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, undefined);
                            checkParameterInitializer(node);
                        }
                        return;
                    }
                    var symbol = getSymbolOfNode(node);
                    var type = getTypeOfVariableOrParameterOrProperty(symbol);
                    if (node === symbol.valueDeclaration) {
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, undefined);
                            checkParameterInitializer(node);
                        }
                    }
                    else {
                        var declarationType = getWidenedTypeForVariableLikeDeclaration(node);
                        if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
                            error(node.name, ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, ts.declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
                        }
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, undefined);
                        }
                    }
                    if (node.kind !== 130 && node.kind !== 129) {
                        checkExportsOnMergedDeclarations(node);
                        if (node.kind === 193 || node.kind === 150) {
                            checkVarDeclaredNamesNotShadowed(node);
                        }
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                }
                function checkVariableDeclaration(node) {
                    checkGrammarVariableDeclaration(node);
                    return checkVariableLikeDeclaration(node);
                }
                function checkBindingElement(node) {
                    checkGrammarBindingElement(node);
                    return checkVariableLikeDeclaration(node);
                }
                function checkVariableStatement(node) {
                    checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
                    ts.forEach(node.declarationList.declarations, checkSourceElement);
                }
                function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) {
                    if (node.modifiers) {
                        if (inBlockOrObjectLiteralExpression(node)) {
                            return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here);
                        }
                    }
                }
                function inBlockOrObjectLiteralExpression(node) {
                    while (node) {
                        if (node.kind === 174 || node.kind === 152) {
                            return true;
                        }
                        node = node.parent;
                    }
                }
                function checkExpressionStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                }
                function checkIfStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                    checkSourceElement(node.thenStatement);
                    checkSourceElement(node.elseStatement);
                }
                function checkDoStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    checkSourceElement(node.statement);
                    checkExpression(node.expression);
                }
                function checkWhileStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                    checkSourceElement(node.statement);
                }
                function checkForStatement(node) {
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.initializer && node.initializer.kind == 194) {
                            checkGrammarVariableDeclarationList(node.initializer);
                        }
                    }
                    if (node.initializer) {
                        if (node.initializer.kind === 194) {
                            ts.forEach(node.initializer.declarations, checkVariableDeclaration);
                        }
                        else {
                            checkExpression(node.initializer);
                        }
                    }
                    if (node.condition)
                        checkExpression(node.condition);
                    if (node.iterator)
                        checkExpression(node.iterator);
                    checkSourceElement(node.statement);
                }
                function checkForOfStatement(node) {
                    checkGrammarForInOrForOfStatement(node);
                    if (node.initializer.kind === 194) {
                        checkForInOrForOfVariableDeclaration(node);
                    }
                    else {
                        var varExpr = node.initializer;
                        var iteratedType = checkRightHandSideOfForOf(node.expression);
                        if (varExpr.kind === 151 || varExpr.kind === 152) {
                            checkDestructuringAssignment(varExpr, iteratedType || unknownType);
                        }
                        else {
                            var leftType = checkExpression(varExpr);
                            checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_of_statement, ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
                            if (iteratedType) {
                                checkTypeAssignableTo(iteratedType, leftType, varExpr, undefined);
                            }
                        }
                    }
                    checkSourceElement(node.statement);
                }
                function checkForInStatement(node) {
                    checkGrammarForInOrForOfStatement(node);
                    if (node.initializer.kind === 194) {
                        var variable = node.initializer.declarations[0];
                        if (variable && ts.isBindingPattern(variable.name)) {
                            error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
                        }
                        checkForInOrForOfVariableDeclaration(node);
                    }
                    else {
                        var varExpr = node.initializer;
                        var leftType = checkExpression(varExpr);
                        if (varExpr.kind === 151 || varExpr.kind === 152) {
                            error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
                        }
                        else if (!allConstituentTypesHaveKind(leftType, 1 | 258)) {
                            error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
                        }
                        else {
                            checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_in_statement, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant);
                        }
                    }
                    var rightType = checkExpression(node.expression);
                    if (!allConstituentTypesHaveKind(rightType, 1 | 48128 | 512)) {
                        error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    checkSourceElement(node.statement);
                }
                function checkForInOrForOfVariableDeclaration(iterationStatement) {
                    var variableDeclarationList = iterationStatement.initializer;
                    if (variableDeclarationList.declarations.length >= 1) {
                        var decl = variableDeclarationList.declarations[0];
                        checkVariableDeclaration(decl);
                    }
                }
                function checkRightHandSideOfForOf(rhsExpression) {
                    var expressionType = getTypeOfExpression(rhsExpression);
                    return languageVersion >= 2 ? checkIteratedType(expressionType, rhsExpression) : checkElementTypeOfArrayOrString(expressionType, rhsExpression);
                }
                function checkIteratedType(iterable, expressionForError) {
                    ts.Debug.assert(languageVersion >= 2);
                    var iteratedType = getIteratedType(iterable, expressionForError);
                    if (expressionForError && iteratedType) {
                        var completeIterableType = globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [
                            iteratedType
                        ]) : emptyObjectType;
                        checkTypeAssignableTo(iterable, completeIterableType, expressionForError);
                    }
                    return iteratedType;
                    function getIteratedType(iterable, expressionForError) {
                        if (allConstituentTypesHaveKind(iterable, 1)) {
                            return undefined;
                        }
                        var iteratorFunction = getTypeOfPropertyOfType(iterable, ts.getPropertyNameForKnownSymbolName("iterator"));
                        if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, 1)) {
                            return undefined;
                        }
                        var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, 0) : emptyArray;
                        if (iteratorFunctionSignatures.length === 0) {
                            if (expressionForError) {
                                error(expressionForError, ts.Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
                            }
                            return undefined;
                        }
                        var iterator = getUnionType(ts.map(iteratorFunctionSignatures, getReturnTypeOfSignature));
                        if (allConstituentTypesHaveKind(iterator, 1)) {
                            return undefined;
                        }
                        var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next");
                        if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, 1)) {
                            return undefined;
                        }
                        var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, 0) : emptyArray;
                        if (iteratorNextFunctionSignatures.length === 0) {
                            if (expressionForError) {
                                error(expressionForError, ts.Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method);
                            }
                            return undefined;
                        }
                        var iteratorNextResult = getUnionType(ts.map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
                        if (allConstituentTypesHaveKind(iteratorNextResult, 1)) {
                            return undefined;
                        }
                        var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value");
                        if (!iteratorNextValue) {
                            if (expressionForError) {
                                error(expressionForError, ts.Diagnostics.The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property);
                            }
                            return undefined;
                        }
                        return iteratorNextValue;
                    }
                }
                function checkElementTypeOfArrayOrString(arrayOrStringType, expressionForError) {
                    ts.Debug.assert(languageVersion < 2);
                    var arrayType = removeTypesFromUnionType(arrayOrStringType, 258, true, true);
                    var hasStringConstituent = arrayOrStringType !== arrayType;
                    var reportedError = false;
                    if (hasStringConstituent) {
                        if (languageVersion < 1) {
                            error(expressionForError, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher);
                            reportedError = true;
                        }
                        if (arrayType === emptyObjectType) {
                            return stringType;
                        }
                    }
                    if (!isArrayLikeType(arrayType)) {
                        if (!reportedError) {
                            var diagnostic = hasStringConstituent ? ts.Diagnostics.Type_0_is_not_an_array_type : ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type;
                            error(expressionForError, diagnostic, typeToString(arrayType));
                        }
                        return hasStringConstituent ? stringType : unknownType;
                    }
                    var arrayElementType = getIndexTypeOfType(arrayType, 1) || unknownType;
                    if (hasStringConstituent) {
                        if (arrayElementType.flags & 258) {
                            return stringType;
                        }
                        return getUnionType([
                            arrayElementType,
                            stringType
                        ]);
                    }
                    return arrayElementType;
                }
                function checkBreakOrContinueStatement(node) {
                    checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node);
                }
                function isGetAccessorWithAnnotatatedSetAccessor(node) {
                    return !!(node.kind === 134 && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 135)));
                }
                function checkReturnStatement(node) {
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        var functionBlock = ts.getContainingFunction(node);
                        if (!functionBlock) {
                            grammarErrorOnFirstToken(node, ts.Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
                        }
                    }
                    if (node.expression) {
                        var func = ts.getContainingFunction(node);
                        if (func) {
                            var returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
                            var exprType = checkExpressionCached(node.expression);
                            if (func.kind === 135) {
                                error(node.expression, ts.Diagnostics.Setters_cannot_return_a_value);
                            }
                            else {
                                if (func.kind === 133) {
                                    if (!isTypeAssignableTo(exprType, returnType)) {
                                        error(node.expression, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
                                    }
                                }
                                else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
                                    checkTypeAssignableTo(exprType, returnType, node.expression, undefined);
                                }
                            }
                        }
                    }
                }
                function checkWithStatement(node) {
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.parserContextFlags & 1) {
                            grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode);
                        }
                    }
                    checkExpression(node.expression);
                    error(node.expression, ts.Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any);
                }
                function checkSwitchStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    var firstDefaultClause;
                    var hasDuplicateDefaultClause = false;
                    var expressionType = checkExpression(node.expression);
                    ts.forEach(node.caseBlock.clauses, function (clause) {
                        if (clause.kind === 215 && !hasDuplicateDefaultClause) {
                            if (firstDefaultClause === undefined) {
                                firstDefaultClause = clause;
                            }
                            else {
                                var sourceFile = ts.getSourceFileOfNode(node);
                                var start = ts.skipTrivia(sourceFile.text, clause.pos);
                                var end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end;
                                grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
                                hasDuplicateDefaultClause = true;
                            }
                        }
                        if (produceDiagnostics && clause.kind === 214) {
                            var caseClause = clause;
                            var caseType = checkExpression(caseClause.expression);
                            if (!isTypeAssignableTo(expressionType, caseType)) {
                                checkTypeAssignableTo(caseType, expressionType, caseClause.expression, undefined);
                            }
                        }
                        ts.forEach(clause.statements, checkSourceElement);
                    });
                }
                function checkLabeledStatement(node) {
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        var current = node.parent;
                        while (current) {
                            if (ts.isFunctionLike(current)) {
                                break;
                            }
                            if (current.kind === 189 && current.label.text === node.label.text) {
                                var sourceFile = ts.getSourceFileOfNode(node);
                                grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNodeFromSourceText(sourceFile.text, node.label));
                                break;
                            }
                            current = current.parent;
                        }
                    }
                    checkSourceElement(node.statement);
                }
                function checkThrowStatement(node) {
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.expression === undefined) {
                            grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here);
                        }
                    }
                    if (node.expression) {
                        checkExpression(node.expression);
                    }
                }
                function checkTryStatement(node) {
                    checkGrammarStatementInAmbientContext(node);
                    checkBlock(node.tryBlock);
                    var catchClause = node.catchClause;
                    if (catchClause) {
                        if (catchClause.variableDeclaration) {
                            if (catchClause.variableDeclaration.name.kind !== 64) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.name, ts.Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
                            }
                            else if (catchClause.variableDeclaration.type) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.type, ts.Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
                            }
                            else if (catchClause.variableDeclaration.initializer) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, ts.Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
                            }
                            else {
                                var identifierName = catchClause.variableDeclaration.name.text;
                                var locals = catchClause.block.locals;
                                if (locals && ts.hasProperty(locals, identifierName)) {
                                    var localSymbol = locals[identifierName];
                                    if (localSymbol && (localSymbol.flags & 2) !== 0) {
                                        grammarErrorOnNode(localSymbol.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, identifierName);
                                    }
                                }
                                checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.variableDeclaration.name);
                            }
                        }
                        checkBlock(catchClause.block);
                    }
                    if (node.finallyBlock) {
                        checkBlock(node.finallyBlock);
                    }
                }
                function checkIndexConstraints(type) {
                    var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1);
                    var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0);
                    var stringIndexType = getIndexTypeOfType(type, 0);
                    var numberIndexType = getIndexTypeOfType(type, 1);
                    if (stringIndexType || numberIndexType) {
                        ts.forEach(getPropertiesOfObjectType(type), function (prop) {
                            var propType = getTypeOfSymbol(prop);
                            checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0);
                            checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1);
                        });
                        if (type.flags & 1024 && type.symbol.valueDeclaration.kind === 196) {
                            var classDeclaration = type.symbol.valueDeclaration;
                            for (var i = 0; i < classDeclaration.members.length; i++) {
                                var member = classDeclaration.members[i];
                                if (!(member.flags & 128) && ts.hasDynamicName(member)) {
                                    var propType = getTypeOfSymbol(member.symbol);
                                    checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, 0);
                                    checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, 1);
                                }
                            }
                        }
                    }
                    var errorNode;
                    if (stringIndexType && numberIndexType) {
                        errorNode = declaredNumberIndexer || declaredStringIndexer;
                        if (!errorNode && (type.flags & 2048)) {
                            var someBaseTypeHasBothIndexers = ts.forEach(type.baseTypes, function (base) {
                                return getIndexTypeOfType(base, 0) && getIndexTypeOfType(base, 1);
                            });
                            errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
                        }
                    }
                    if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) {
                        error(errorNode, ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, typeToString(numberIndexType), typeToString(stringIndexType));
                    }
                    function checkIndexConstraintForProperty(prop, propertyType, containingType, indexDeclaration, indexType, indexKind) {
                        if (!indexType) {
                            return;
                        }
                        if (indexKind === 1 && !isNumericName(prop.valueDeclaration.name)) {
                            return;
                        }
                        var errorNode;
                        if (prop.valueDeclaration.name.kind === 126 || prop.parent === containingType.symbol) {
                            errorNode = prop.valueDeclaration;
                        }
                        else if (indexDeclaration) {
                            errorNode = indexDeclaration;
                        }
                        else if (containingType.flags & 2048) {
                            var someBaseClassHasBothPropertyAndIndexer = ts.forEach(containingType.baseTypes, function (base) {
                                return getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind);
                            });
                            errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0];
                        }
                        if (errorNode && !isTypeAssignableTo(propertyType, indexType)) {
                            var errorMessage = indexKind === 0 ? ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2 : ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2;
                            error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType));
                        }
                    }
                }
                function checkTypeNameIsReserved(name, message) {
                    switch (name.text) {
                        case "any":
                        case "number":
                        case "boolean":
                        case "string":
                        case "symbol":
                        case "void":
                            error(name, message, name.text);
                    }
                }
                function checkTypeParameters(typeParameterDeclarations) {
                    if (typeParameterDeclarations) {
                        for (var i = 0; i < typeParameterDeclarations.length; i++) {
                            var node = typeParameterDeclarations[i];
                            checkTypeParameter(node);
                            if (produceDiagnostics) {
                                for (var j = 0; j < i; j++) {
                                    if (typeParameterDeclarations[j].symbol === node.symbol) {
                                        error(node.name, ts.Diagnostics.Duplicate_identifier_0, ts.declarationNameToString(node.name));
                                    }
                                }
                            }
                        }
                    }
                }
                function checkClassDeclaration(node) {
                    checkGrammarClassDeclarationHeritageClauses(node);
                    if (node.name) {
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Class_name_cannot_be_0);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                    checkTypeParameters(node.typeParameters);
                    checkExportsOnMergedDeclarations(node);
                    var symbol = getSymbolOfNode(node);
                    var type = getDeclaredTypeOfSymbol(symbol);
                    var staticType = getTypeOfSymbol(symbol);
                    var baseTypeNode = ts.getClassBaseTypeNode(node);
                    if (baseTypeNode) {
                        emitExtends = emitExtends || !ts.isInAmbientContext(node);
                        checkTypeReference(baseTypeNode);
                    }
                    if (type.baseTypes.length) {
                        if (produceDiagnostics) {
                            var baseType = type.baseTypes[0];
                            checkTypeAssignableTo(type, baseType, node.name || node, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1);
                            var staticBaseType = getTypeOfSymbol(baseType.symbol);
                            checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node, ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
                            if (baseType.symbol !== resolveEntityName(baseTypeNode.typeName, 107455)) {
                                error(baseTypeNode, ts.Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
                            }
                            checkKindsOfPropertyMemberOverrides(type, baseType);
                        }
                        checkExpressionOrQualifiedName(baseTypeNode.typeName);
                    }
                    var implementedTypeNodes = ts.getClassImplementedTypeNodes(node);
                    if (implementedTypeNodes) {
                        ts.forEach(implementedTypeNodes, function (typeRefNode) {
                            checkTypeReference(typeRefNode);
                            if (produceDiagnostics) {
                                var t = getTypeFromTypeReferenceNode(typeRefNode);
                                if (t !== unknownType) {
                                    var declaredType = (t.flags & 4096) ? t.target : t;
                                    if (declaredType.flags & (1024 | 2048)) {
                                        checkTypeAssignableTo(type, t, node.name || node, ts.Diagnostics.Class_0_incorrectly_implements_interface_1);
                                    }
                                    else {
                                        error(typeRefNode, ts.Diagnostics.A_class_may_only_implement_another_class_or_interface);
                                    }
                                }
                            }
                        });
                    }
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        checkIndexConstraints(type);
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function getTargetSymbol(s) {
                    return s.flags & 16777216 ? getSymbolLinks(s).target : s;
                }
                function checkKindsOfPropertyMemberOverrides(type, baseType) {
                    var baseProperties = getPropertiesOfObjectType(baseType);
                    for (var i = 0, len = baseProperties.length; i < len; ++i) {
                        var base = getTargetSymbol(baseProperties[i]);
                        if (base.flags & 134217728) {
                            continue;
                        }
                        var derived = getTargetSymbol(getPropertyOfObjectType(type, base.name));
                        if (derived) {
                            var baseDeclarationFlags = getDeclarationFlagsFromSymbol(base);
                            var derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
                            if ((baseDeclarationFlags & 32) || (derivedDeclarationFlags & 32)) {
                                continue;
                            }
                            if ((baseDeclarationFlags & 128) !== (derivedDeclarationFlags & 128)) {
                                continue;
                            }
                            if ((base.flags & derived.flags & 8192) || ((base.flags & 98308) && (derived.flags & 98308))) {
                                continue;
                            }
                            var errorMessage;
                            if (base.flags & 8192) {
                                if (derived.flags & 98304) {
                                    errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
                                }
                                else {
                                    ts.Debug.assert((derived.flags & 4) !== 0);
                                    errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
                                }
                            }
                            else if (base.flags & 4) {
                                ts.Debug.assert((derived.flags & 8192) !== 0);
                                errorMessage = ts.Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
                            }
                            else {
                                ts.Debug.assert((base.flags & 98304) !== 0);
                                ts.Debug.assert((derived.flags & 8192) !== 0);
                                errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
                            }
                            error(derived.valueDeclaration.name, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
                        }
                    }
                }
                function isAccessor(kind) {
                    return kind === 134 || kind === 135;
                }
                function areTypeParametersIdentical(list1, list2) {
                    if (!list1 && !list2) {
                        return true;
                    }
                    if (!list1 || !list2 || list1.length !== list2.length) {
                        return false;
                    }
                    for (var i = 0, len = list1.length; i < len; i++) {
                        var tp1 = list1[i];
                        var tp2 = list2[i];
                        if (tp1.name.text !== tp2.name.text) {
                            return false;
                        }
                        if (!tp1.constraint && !tp2.constraint) {
                            continue;
                        }
                        if (!tp1.constraint || !tp2.constraint) {
                            return false;
                        }
                        if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
                            return false;
                        }
                    }
                    return true;
                }
                function checkInheritedPropertiesAreIdentical(type, typeNode) {
                    if (!type.baseTypes.length || type.baseTypes.length === 1) {
                        return true;
                    }
                    var seen = {};
                    ts.forEach(type.declaredProperties, function (p) {
                        seen[p.name] = {
                            prop: p,
                            containingType: type
                        };
                    });
                    var ok = true;
                    for (var i = 0, len = type.baseTypes.length; i < len; ++i) {
                        var base = type.baseTypes[i];
                        var properties = getPropertiesOfObjectType(base);
                        for (var j = 0, proplen = properties.length; j < proplen; ++j) {
                            var prop = properties[j];
                            if (!ts.hasProperty(seen, prop.name)) {
                                seen[prop.name] = {
                                    prop: prop,
                                    containingType: base
                                };
                            }
                            else {
                                var existing = seen[prop.name];
                                var isInheritedProperty = existing.containingType !== type;
                                if (isInheritedProperty && !isPropertyIdenticalTo(existing.prop, prop)) {
                                    ok = false;
                                    var typeName1 = typeToString(existing.containingType);
                                    var typeName2 = typeToString(base);
                                    var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2);
                                    errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
                                    diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
                                }
                            }
                        }
                    }
                    return ok;
                }
                function checkInterfaceDeclaration(node) {
                    checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
                    checkTypeParameters(node.typeParameters);
                    if (produceDiagnostics) {
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Interface_name_cannot_be_0);
                        checkExportsOnMergedDeclarations(node);
                        var symbol = getSymbolOfNode(node);
                        var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 197);
                        if (symbol.declarations.length > 1) {
                            if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
                                error(node.name, ts.Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
                            }
                        }
                        if (node === firstInterfaceDecl) {
                            var type = getDeclaredTypeOfSymbol(symbol);
                            if (checkInheritedPropertiesAreIdentical(type, node.name)) {
                                ts.forEach(type.baseTypes, function (baseType) {
                                    checkTypeAssignableTo(type, baseType, node.name, ts.Diagnostics.Interface_0_incorrectly_extends_interface_1);
                                });
                                checkIndexConstraints(type);
                            }
                        }
                    }
                    ts.forEach(ts.getInterfaceBaseTypeNodes(node), checkTypeReference);
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function checkTypeAliasDeclaration(node) {
                    checkGrammarModifiers(node);
                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0);
                    checkSourceElement(node.type);
                }
                function computeEnumMemberValues(node) {
                    var nodeLinks = getNodeLinks(node);
                    if (!(nodeLinks.flags & 128)) {
                        var enumSymbol = getSymbolOfNode(node);
                        var enumType = getDeclaredTypeOfSymbol(enumSymbol);
                        var autoValue = 0;
                        var ambient = ts.isInAmbientContext(node);
                        var enumIsConst = ts.isConst(node);
                        ts.forEach(node.members, function (member) {
                            if (member.name.kind !== 126 && isNumericLiteralName(member.name.text)) {
                                error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name);
                            }
                            var initializer = member.initializer;
                            if (initializer) {
                                autoValue = getConstantValueForEnumMemberInitializer(initializer, enumIsConst);
                                if (autoValue === undefined) {
                                    if (enumIsConst) {
                                        error(initializer, ts.Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
                                    }
                                    else if (!ambient) {
                                        checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, undefined);
                                    }
                                }
                                else if (enumIsConst) {
                                    if (isNaN(autoValue)) {
                                        error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN);
                                    }
                                    else if (!isFinite(autoValue)) {
                                        error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value);
                                    }
                                }
                            }
                            else if (ambient && !enumIsConst) {
                                autoValue = undefined;
                            }
                            if (autoValue !== undefined) {
                                getNodeLinks(member).enumMemberValue = autoValue++;
                            }
                        });
                        nodeLinks.flags |= 128;
                    }
                    function getConstantValueForEnumMemberInitializer(initializer, enumIsConst) {
                        return evalConstant(initializer);
                        function evalConstant(e) {
                            switch (e.kind) {
                                case 165:
                                    var value = evalConstant(e.operand);
                                    if (value === undefined) {
                                        return undefined;
                                    }
                                    switch (e.operator) {
                                        case 33:
                                            return value;
                                        case 34:
                                            return -value;
                                        case 47:
                                            return enumIsConst ? ~value : undefined;
                                    }
                                    return undefined;
                                case 167:
                                    if (!enumIsConst) {
                                        return undefined;
                                    }
                                    var left = evalConstant(e.left);
                                    if (left === undefined) {
                                        return undefined;
                                    }
                                    var right = evalConstant(e.right);
                                    if (right === undefined) {
                                        return undefined;
                                    }
                                    switch (e.operatorToken.kind) {
                                        case 44:
                                            return left | right;
                                        case 43:
                                            return left & right;
                                        case 41:
                                            return left >> right;
                                        case 42:
                                            return left >>> right;
                                        case 40:
                                            return left << right;
                                        case 45:
                                            return left ^ right;
                                        case 35:
                                            return left * right;
                                        case 36:
                                            return left / right;
                                        case 33:
                                            return left + right;
                                        case 34:
                                            return left - right;
                                        case 37:
                                            return left % right;
                                    }
                                    return undefined;
                                case 7:
                                    return +e.text;
                                case 159:
                                    return enumIsConst ? evalConstant(e.expression) : undefined;
                                case 64:
                                case 154:
                                case 153:
                                    if (!enumIsConst) {
                                        return undefined;
                                    }
                                    var member = initializer.parent;
                                    var currentType = getTypeOfSymbol(getSymbolOfNode(member.parent));
                                    var enumType;
                                    var propertyName;
                                    if (e.kind === 64) {
                                        enumType = currentType;
                                        propertyName = e.text;
                                    }
                                    else {
                                        if (e.kind === 154) {
                                            if (e.argumentExpression === undefined || e.argumentExpression.kind !== 8) {
                                                return undefined;
                                            }
                                            var enumType = getTypeOfNode(e.expression);
                                            propertyName = e.argumentExpression.text;
                                        }
                                        else {
                                            var enumType = getTypeOfNode(e.expression);
                                            propertyName = e.name.text;
                                        }
                                        if (enumType !== currentType) {
                                            return undefined;
                                        }
                                    }
                                    if (propertyName === undefined) {
                                        return undefined;
                                    }
                                    var property = getPropertyOfObjectType(enumType, propertyName);
                                    if (!property || !(property.flags & 8)) {
                                        return undefined;
                                    }
                                    var propertyDecl = property.valueDeclaration;
                                    if (member === propertyDecl) {
                                        return undefined;
                                    }
                                    if (!isDefinedBefore(propertyDecl, member)) {
                                        return undefined;
                                    }
                                    return getNodeLinks(propertyDecl).enumMemberValue;
                            }
                        }
                    }
                }
                function checkEnumDeclaration(node) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Enum_name_cannot_be_0);
                    checkCollisionWithCapturedThisVariable(node, node.name);
                    checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    checkExportsOnMergedDeclarations(node);
                    computeEnumMemberValues(node);
                    var enumSymbol = getSymbolOfNode(node);
                    var firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind);
                    if (node === firstDeclaration) {
                        if (enumSymbol.declarations.length > 1) {
                            var enumIsConst = ts.isConst(node);
                            ts.forEach(enumSymbol.declarations, function (decl) {
                                if (ts.isConstEnumDeclaration(decl) !== enumIsConst) {
                                    error(decl.name, ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
                                }
                            });
                        }
                        var seenEnumMissingInitialInitializer = false;
                        ts.forEach(enumSymbol.declarations, function (declaration) {
                            if (declaration.kind !== 199) {
                                return false;
                            }
                            var enumDeclaration = declaration;
                            if (!enumDeclaration.members.length) {
                                return false;
                            }
                            var firstEnumMember = enumDeclaration.members[0];
                            if (!firstEnumMember.initializer) {
                                if (seenEnumMissingInitialInitializer) {
                                    error(firstEnumMember.name, ts.Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element);
                                }
                                else {
                                    seenEnumMissingInitialInitializer = true;
                                }
                            }
                        });
                    }
                }
                function getFirstNonAmbientClassOrFunctionDeclaration(symbol) {
                    var declarations = symbol.declarations;
                    for (var i = 0; i < declarations.length; i++) {
                        var declaration = declarations[i];
                        if ((declaration.kind === 196 || (declaration.kind === 195 && ts.nodeIsPresent(declaration.body))) && !ts.isInAmbientContext(declaration)) {
                            return declaration;
                        }
                    }
                    return undefined;
                }
                function checkModuleDeclaration(node) {
                    if (produceDiagnostics) {
                        if (!checkGrammarModifiers(node)) {
                            if (!ts.isInAmbientContext(node) && node.name.kind === 8) {
                                grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names);
                            }
                        }
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                        checkExportsOnMergedDeclarations(node);
                        var symbol = getSymbolOfNode(node);
                        if (symbol.flags & 512 && symbol.declarations.length > 1 && !ts.isInAmbientContext(node) && ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums)) {
                            var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
                            if (classOrFunc) {
                                if (ts.getSourceFileOfNode(node) !== ts.getSourceFileOfNode(classOrFunc)) {
                                    error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
                                }
                                else if (node.pos < classOrFunc.pos) {
                                    error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
                                }
                            }
                        }
                        if (node.name.kind === 8) {
                            if (!isGlobalSourceFile(node.parent)) {
                                error(node.name, ts.Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
                            }
                            if (isExternalModuleNameRelative(node.name.text)) {
                                error(node.name, ts.Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
                            }
                        }
                    }
                    checkSourceElement(node.body);
                }
                function getFirstIdentifier(node) {
                    while (node.kind === 125) {
                        node = node.left;
                    }
                    return node;
                }
                function checkExternalImportOrExportDeclaration(node) {
                    var moduleName = ts.getExternalModuleName(node);
                    if (ts.getFullWidth(moduleName) !== 0 && moduleName.kind !== 8) {
                        error(moduleName, ts.Diagnostics.String_literal_expected);
                        return false;
                    }
                    var inAmbientExternalModule = node.parent.kind === 201 && node.parent.parent.name.kind === 8;
                    if (node.parent.kind !== 221 && !inAmbientExternalModule) {
                        error(moduleName, node.kind === 210 ? ts.Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module : ts.Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
                        return false;
                    }
                    if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) {
                        error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
                        return false;
                    }
                    return true;
                }
                function checkAliasSymbol(node) {
                    var symbol = getSymbolOfNode(node);
                    var target = resolveAlias(symbol);
                    if (target !== unknownSymbol) {
                        var excludedMeanings = (symbol.flags & 107455 ? 107455 : 0) | (symbol.flags & 793056 ? 793056 : 0) | (symbol.flags & 1536 ? 1536 : 0);
                        if (target.flags & excludedMeanings) {
                            var message = node.kind === 212 ? ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
                            error(node, message, symbolToString(symbol));
                        }
                    }
                }
                function checkImportBinding(node) {
                    checkCollisionWithCapturedThisVariable(node, node.name);
                    checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    checkAliasSymbol(node);
                }
                function checkImportDeclaration(node) {
                    if (!checkGrammarModifiers(node) && (node.flags & 499)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers);
                    }
                    if (checkExternalImportOrExportDeclaration(node)) {
                        var importClause = node.importClause;
                        if (importClause) {
                            if (importClause.name) {
                                checkImportBinding(importClause);
                            }
                            if (importClause.namedBindings) {
                                if (importClause.namedBindings.kind === 206) {
                                    checkImportBinding(importClause.namedBindings);
                                }
                                else {
                                    ts.forEach(importClause.namedBindings.elements, checkImportBinding);
                                }
                            }
                        }
                    }
                }
                function checkImportEqualsDeclaration(node) {
                    checkGrammarModifiers(node);
                    if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
                        checkImportBinding(node);
                        if (node.flags & 1) {
                            markExportAsReferenced(node);
                        }
                        if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                            var target = resolveAlias(getSymbolOfNode(node));
                            if (target !== unknownSymbol) {
                                if (target.flags & 107455) {
                                    var moduleName = getFirstIdentifier(node.moduleReference);
                                    if (!(resolveEntityName(moduleName, 107455 | 1536).flags & 1536)) {
                                        error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName));
                                    }
                                }
                                if (target.flags & 793056) {
                                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0);
                                }
                            }
                        }
                    }
                }
                function checkExportDeclaration(node) {
                    if (!checkGrammarModifiers(node) && (node.flags & 499)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers);
                    }
                    if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
                        if (node.exportClause) {
                            ts.forEach(node.exportClause.elements, checkExportSpecifier);
                        }
                    }
                }
                function checkExportSpecifier(node) {
                    checkAliasSymbol(node);
                    if (!node.parent.parent.moduleSpecifier) {
                        markExportAsReferenced(node);
                    }
                }
                function checkExportAssignment(node) {
                    var container = node.parent.kind === 221 ? node.parent : node.parent.parent;
                    if (container.kind === 200 && container.name.kind === 64) {
                        error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
                        return;
                    }
                    if (!checkGrammarModifiers(node) && (node.flags & 499)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers);
                    }
                    if (node.expression.kind === 64) {
                        markExportAsReferenced(node);
                    }
                    else {
                        checkExpressionCached(node.expression);
                    }
                    checkExternalModuleExports(container);
                }
                function getModuleStatements(node) {
                    if (node.kind === 221) {
                        return node.statements;
                    }
                    if (node.kind === 200 && node.body.kind === 201) {
                        return node.body.statements;
                    }
                    return emptyArray;
                }
                function hasExportedMembers(moduleSymbol) {
                    var declarations = moduleSymbol.declarations;
                    for (var i = 0; i < declarations.length; i++) {
                        var statements = getModuleStatements(declarations[i]);
                        for (var j = 0; j < statements.length; j++) {
                            var node = statements[j];
                            if (node.kind === 210) {
                                var exportClause = node.exportClause;
                                if (!exportClause) {
                                    return true;
                                }
                                var specifiers = exportClause.elements;
                                for (var k = 0; k < specifiers.length; k++) {
                                    var specifier = specifiers[k];
                                    if (!(specifier.propertyName && specifier.name && specifier.name.text === "default")) {
                                        return true;
                                    }
                                }
                            }
                            else if (node.kind !== 209 && node.flags & 1 && !(node.flags & 256)) {
                                return true;
                            }
                        }
                    }
                }
                function checkExternalModuleExports(node) {
                    var moduleSymbol = getSymbolOfNode(node);
                    var links = getSymbolLinks(moduleSymbol);
                    if (!links.exportsChecked) {
                        var defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
                        if (defaultSymbol) {
                            if (hasExportedMembers(moduleSymbol)) {
                                var declaration = getDeclarationOfAliasSymbol(defaultSymbol) || defaultSymbol.valueDeclaration;
                                error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
                            }
                        }
                        links.exportsChecked = true;
                    }
                }
                function checkSourceElement(node) {
                    if (!node)
                        return;
                    switch (node.kind) {
                        case 127:
                            return checkTypeParameter(node);
                        case 128:
                            return checkParameter(node);
                        case 130:
                        case 129:
                            return checkPropertyDeclaration(node);
                        case 140:
                        case 141:
                        case 136:
                        case 137:
                            return checkSignatureDeclaration(node);
                        case 138:
                            return checkSignatureDeclaration(node);
                        case 132:
                        case 131:
                            return checkMethodDeclaration(node);
                        case 133:
                            return checkConstructorDeclaration(node);
                        case 134:
                        case 135:
                            return checkAccessorDeclaration(node);
                        case 139:
                            return checkTypeReference(node);
                        case 142:
                            return checkTypeQuery(node);
                        case 143:
                            return checkTypeLiteral(node);
                        case 144:
                            return checkArrayType(node);
                        case 145:
                            return checkTupleType(node);
                        case 146:
                            return checkUnionType(node);
                        case 147:
                            return checkSourceElement(node.type);
                        case 195:
                            return checkFunctionDeclaration(node);
                        case 174:
                        case 201:
                            return checkBlock(node);
                        case 175:
                            return checkVariableStatement(node);
                        case 177:
                            return checkExpressionStatement(node);
                        case 178:
                            return checkIfStatement(node);
                        case 179:
                            return checkDoStatement(node);
                        case 180:
                            return checkWhileStatement(node);
                        case 181:
                            return checkForStatement(node);
                        case 182:
                            return checkForInStatement(node);
                        case 183:
                            return checkForOfStatement(node);
                        case 184:
                        case 185:
                            return checkBreakOrContinueStatement(node);
                        case 186:
                            return checkReturnStatement(node);
                        case 187:
                            return checkWithStatement(node);
                        case 188:
                            return checkSwitchStatement(node);
                        case 189:
                            return checkLabeledStatement(node);
                        case 190:
                            return checkThrowStatement(node);
                        case 191:
                            return checkTryStatement(node);
                        case 193:
                            return checkVariableDeclaration(node);
                        case 150:
                            return checkBindingElement(node);
                        case 196:
                            return checkClassDeclaration(node);
                        case 197:
                            return checkInterfaceDeclaration(node);
                        case 198:
                            return checkTypeAliasDeclaration(node);
                        case 199:
                            return checkEnumDeclaration(node);
                        case 200:
                            return checkModuleDeclaration(node);
                        case 204:
                            return checkImportDeclaration(node);
                        case 203:
                            return checkImportEqualsDeclaration(node);
                        case 210:
                            return checkExportDeclaration(node);
                        case 209:
                            return checkExportAssignment(node);
                        case 176:
                            checkGrammarStatementInAmbientContext(node);
                            return;
                        case 192:
                            checkGrammarStatementInAmbientContext(node);
                            return;
                    }
                }
                function checkFunctionExpressionBodies(node) {
                    switch (node.kind) {
                        case 160:
                        case 161:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            checkFunctionExpressionOrObjectLiteralMethodBody(node);
                            break;
                        case 132:
                        case 131:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            if (ts.isObjectLiteralMethod(node)) {
                                checkFunctionExpressionOrObjectLiteralMethodBody(node);
                            }
                            break;
                        case 133:
                        case 134:
                        case 135:
                        case 195:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            break;
                        case 187:
                            checkFunctionExpressionBodies(node.expression);
                            break;
                        case 128:
                        case 130:
                        case 129:
                        case 148:
                        case 149:
                        case 150:
                        case 151:
                        case 152:
                        case 218:
                        case 153:
                        case 154:
                        case 155:
                        case 156:
                        case 157:
                        case 169:
                        case 173:
                        case 158:
                        case 159:
                        case 163:
                        case 164:
                        case 162:
                        case 165:
                        case 166:
                        case 167:
                        case 168:
                        case 171:
                        case 174:
                        case 201:
                        case 175:
                        case 177:
                        case 178:
                        case 179:
                        case 180:
                        case 181:
                        case 182:
                        case 183:
                        case 184:
                        case 185:
                        case 186:
                        case 188:
                        case 202:
                        case 214:
                        case 215:
                        case 189:
                        case 190:
                        case 191:
                        case 217:
                        case 193:
                        case 194:
                        case 196:
                        case 199:
                        case 220:
                        case 209:
                        case 221:
                            ts.forEachChild(node, checkFunctionExpressionBodies);
                            break;
                    }
                }
                function checkSourceFile(node) {
                    var start = new Date().getTime();
                    checkSourceFileWorker(node);
                    ts.checkTime += new Date().getTime() - start;
                }
                function checkSourceFileWorker(node) {
                    var links = getNodeLinks(node);
                    if (!(links.flags & 1)) {
                        checkGrammarSourceFile(node);
                        emitExtends = false;
                        potentialThisCollisions.length = 0;
                        ts.forEach(node.statements, checkSourceElement);
                        checkFunctionExpressionBodies(node);
                        if (ts.isExternalModule(node)) {
                            checkExternalModuleExports(node);
                        }
                        if (potentialThisCollisions.length) {
                            ts.forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
                            potentialThisCollisions.length = 0;
                        }
                        if (emitExtends) {
                            links.flags |= 8;
                        }
                        links.flags |= 1;
                    }
                }
                function getDiagnostics(sourceFile) {
                    throwIfNonDiagnosticsProducing();
                    if (sourceFile) {
                        checkSourceFile(sourceFile);
                        return diagnostics.getDiagnostics(sourceFile.fileName);
                    }
                    ts.forEach(host.getSourceFiles(), checkSourceFile);
                    return diagnostics.getDiagnostics();
                }
                function getGlobalDiagnostics() {
                    throwIfNonDiagnosticsProducing();
                    return diagnostics.getGlobalDiagnostics();
                }
                function throwIfNonDiagnosticsProducing() {
                    if (!produceDiagnostics) {
                        throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
                    }
                }
                function isInsideWithStatementBody(node) {
                    if (node) {
                        while (node.parent) {
                            if (node.parent.kind === 187 && node.parent.statement === node) {
                                return true;
                            }
                            node = node.parent;
                        }
                    }
                    return false;
                }
                function getSymbolsInScope(location, meaning) {
                    var symbols = {};
                    var memberFlags = 0;
                    function copySymbol(symbol, meaning) {
                        if (symbol.flags & meaning) {
                            var id = symbol.name;
                            if (!isReservedMemberName(id) && !ts.hasProperty(symbols, id)) {
                                symbols[id] = symbol;
                            }
                        }
                    }
                    function copySymbols(source, meaning) {
                        if (meaning) {
                            for (var id in source) {
                                if (ts.hasProperty(source, id)) {
                                    copySymbol(source[id], meaning);
                                }
                            }
                        }
                    }
                    if (isInsideWithStatementBody(location)) {
                        return [];
                    }
                    while (location) {
                        if (location.locals && !isGlobalSourceFile(location)) {
                            copySymbols(location.locals, meaning);
                        }
                        switch (location.kind) {
                            case 221:
                                if (!ts.isExternalModule(location))
                                    break;
                            case 200:
                                copySymbols(getSymbolOfNode(location).exports, meaning & 8914931);
                                break;
                            case 199:
                                copySymbols(getSymbolOfNode(location).exports, meaning & 8);
                                break;
                            case 196:
                            case 197:
                                if (!(memberFlags & 128)) {
                                    copySymbols(getSymbolOfNode(location).members, meaning & 793056);
                                }
                                break;
                            case 160:
                                if (location.name) {
                                    copySymbol(location.symbol, meaning);
                                }
                                break;
                        }
                        memberFlags = location.flags;
                        location = location.parent;
                    }
                    copySymbols(globals, meaning);
                    return ts.mapToArray(symbols);
                }
                function isTypeDeclarationName(name) {
                    return name.kind == 64 && isTypeDeclaration(name.parent) && name.parent.name === name;
                }
                function isTypeDeclaration(node) {
                    switch (node.kind) {
                        case 127:
                        case 196:
                        case 197:
                        case 198:
                        case 199:
                            return true;
                    }
                }
                function isTypeReferenceIdentifier(entityName) {
                    var node = entityName;
                    while (node.parent && node.parent.kind === 125)
                        node = node.parent;
                    return node.parent && node.parent.kind === 139;
                }
                function isTypeNode(node) {
                    if (139 <= node.kind && node.kind <= 147) {
                        return true;
                    }
                    switch (node.kind) {
                        case 111:
                        case 118:
                        case 120:
                        case 112:
                        case 121:
                            return true;
                        case 98:
                            return node.parent.kind !== 164;
                        case 8:
                            return node.parent.kind === 128;
                        case 64:
                            if (node.parent.kind === 125 && node.parent.right === node) {
                                node = node.parent;
                            }
                        case 125:
                            ts.Debug.assert(node.kind === 64 || node.kind === 125, "'node' was expected to be a qualified name or identifier in 'isTypeNode'.");
                            var parent = node.parent;
                            if (parent.kind === 142) {
                                return false;
                            }
                            if (139 <= parent.kind && parent.kind <= 147) {
                                return true;
                            }
                            switch (parent.kind) {
                                case 127:
                                    return node === parent.constraint;
                                case 130:
                                case 129:
                                case 128:
                                case 193:
                                    return node === parent.type;
                                case 195:
                                case 160:
                                case 161:
                                case 133:
                                case 132:
                                case 131:
                                case 134:
                                case 135:
                                    return node === parent.type;
                                case 136:
                                case 137:
                                case 138:
                                    return node === parent.type;
                                case 158:
                                    return node === parent.type;
                                case 155:
                                case 156:
                                    return parent.typeArguments && ts.indexOf(parent.typeArguments, node) >= 0;
                                case 157:
                                    return false;
                            }
                    }
                    return false;
                }
                function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide) {
                    while (nodeOnRightSide.parent.kind === 125) {
                        nodeOnRightSide = nodeOnRightSide.parent;
                    }
                    if (nodeOnRightSide.parent.kind === 203) {
                        return nodeOnRightSide.parent.moduleReference === nodeOnRightSide && nodeOnRightSide.parent;
                    }
                    if (nodeOnRightSide.parent.kind === 209) {
                        return nodeOnRightSide.parent.expression === nodeOnRightSide && nodeOnRightSide.parent;
                    }
                    return undefined;
                }
                function isInRightSideOfImportOrExportAssignment(node) {
                    return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
                }
                function isRightSideOfQualifiedNameOrPropertyAccess(node) {
                    return (node.parent.kind === 125 && node.parent.right === node) || (node.parent.kind === 153 && node.parent.name === node);
                }
                function getSymbolOfEntityNameOrPropertyAccessExpression(entityName) {
                    if (ts.isDeclarationName(entityName)) {
                        return getSymbolOfNode(entityName.parent);
                    }
                    if (entityName.parent.kind === 209) {
                        return resolveEntityName(entityName, 107455 | 793056 | 1536 | 8388608);
                    }
                    if (entityName.kind !== 153) {
                        if (isInRightSideOfImportOrExportAssignment(entityName)) {
                            return getSymbolOfPartOfRightHandSideOfImportEquals(entityName);
                        }
                    }
                    if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
                        entityName = entityName.parent;
                    }
                    if (ts.isExpression(entityName)) {
                        if (ts.getFullWidth(entityName) === 0) {
                            return undefined;
                        }
                        if (entityName.kind === 64) {
                            var meaning = 107455 | 8388608;
                            return resolveEntityName(entityName, meaning);
                        }
                        else if (entityName.kind === 153) {
                            var symbol = getNodeLinks(entityName).resolvedSymbol;
                            if (!symbol) {
                                checkPropertyAccessExpression(entityName);
                            }
                            return getNodeLinks(entityName).resolvedSymbol;
                        }
                        else if (entityName.kind === 125) {
                            var symbol = getNodeLinks(entityName).resolvedSymbol;
                            if (!symbol) {
                                checkQualifiedName(entityName);
                            }
                            return getNodeLinks(entityName).resolvedSymbol;
                        }
                    }
                    else if (isTypeReferenceIdentifier(entityName)) {
                        var meaning = entityName.parent.kind === 139 ? 793056 : 1536;
                        meaning |= 8388608;
                        return resolveEntityName(entityName, meaning);
                    }
                    return undefined;
                }
                function getSymbolInfo(node) {
                    if (isInsideWithStatementBody(node)) {
                        return undefined;
                    }
                    if (ts.isDeclarationName(node)) {
                        return getSymbolOfNode(node.parent);
                    }
                    if (node.kind === 64 && isInRightSideOfImportOrExportAssignment(node)) {
                        return node.parent.kind === 209 ? getSymbolOfEntityNameOrPropertyAccessExpression(node) : getSymbolOfPartOfRightHandSideOfImportEquals(node);
                    }
                    switch (node.kind) {
                        case 64:
                        case 153:
                        case 125:
                            return getSymbolOfEntityNameOrPropertyAccessExpression(node);
                        case 92:
                        case 90:
                            var type = checkExpression(node);
                            return type.symbol;
                        case 113:
                            var constructorDeclaration = node.parent;
                            if (constructorDeclaration && constructorDeclaration.kind === 133) {
                                return constructorDeclaration.parent.symbol;
                            }
                            return undefined;
                        case 8:
                            var moduleName;
                            if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || ((node.parent.kind === 204 || node.parent.kind === 210) && node.parent.moduleSpecifier === node)) {
                                return resolveExternalModuleName(node, node);
                            }
                        case 7:
                            if (node.parent.kind == 154 && node.parent.argumentExpression === node) {
                                var objectType = checkExpression(node.parent.expression);
                                if (objectType === unknownType)
                                    return undefined;
                                var apparentType = getApparentType(objectType);
                                if (apparentType === unknownType)
                                    return undefined;
                                return getPropertyOfType(apparentType, node.text);
                            }
                            break;
                    }
                    return undefined;
                }
                function getShorthandAssignmentValueSymbol(location) {
                    if (location && location.kind === 219) {
                        return resolveEntityName(location.name, 107455);
                    }
                    return undefined;
                }
                function getTypeOfNode(node) {
                    if (isInsideWithStatementBody(node)) {
                        return unknownType;
                    }
                    if (ts.isExpression(node)) {
                        return getTypeOfExpression(node);
                    }
                    if (isTypeNode(node)) {
                        return getTypeFromTypeNode(node);
                    }
                    if (isTypeDeclaration(node)) {
                        var symbol = getSymbolOfNode(node);
                        return getDeclaredTypeOfSymbol(symbol);
                    }
                    if (isTypeDeclarationName(node)) {
                        var symbol = getSymbolInfo(node);
                        return symbol && getDeclaredTypeOfSymbol(symbol);
                    }
                    if (ts.isDeclaration(node)) {
                        var symbol = getSymbolOfNode(node);
                        return getTypeOfSymbol(symbol);
                    }
                    if (ts.isDeclarationName(node)) {
                        var symbol = getSymbolInfo(node);
                        return symbol && getTypeOfSymbol(symbol);
                    }
                    if (isInRightSideOfImportOrExportAssignment(node)) {
                        var symbol = getSymbolInfo(node);
                        var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
                        return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
                    }
                    return unknownType;
                }
                function getTypeOfExpression(expr) {
                    if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
                        expr = expr.parent;
                    }
                    return checkExpression(expr);
                }
                function getAugmentedPropertiesOfType(type) {
                    var type = getApparentType(type);
                    var propsByName = createSymbolTable(getPropertiesOfType(type));
                    if (getSignaturesOfType(type, 0).length || getSignaturesOfType(type, 1).length) {
                        ts.forEach(getPropertiesOfType(globalFunctionType), function (p) {
                            if (!ts.hasProperty(propsByName, p.name)) {
                                propsByName[p.name] = p;
                            }
                        });
                    }
                    return getNamedMembers(propsByName);
                }
                function getRootSymbols(symbol) {
                    if (symbol.flags & 268435456) {
                        var symbols = [];
                        var name = symbol.name;
                        ts.forEach(getSymbolLinks(symbol).unionType.types, function (t) {
                            symbols.push(getPropertyOfType(t, name));
                        });
                        return symbols;
                    }
                    else if (symbol.flags & 67108864) {
                        var target = getSymbolLinks(symbol).target;
                        if (target) {
                            return [
                                target
                            ];
                        }
                    }
                    return [
                        symbol
                    ];
                }
                function isExternalModuleSymbol(symbol) {
                    return symbol.flags & 512 && symbol.declarations.length === 1 && symbol.declarations[0].kind === 221;
                }
                function isNodeDescendentOf(node, ancestor) {
                    while (node) {
                        if (node === ancestor)
                            return true;
                        node = node.parent;
                    }
                    return false;
                }
                function isUniqueLocalName(name, container) {
                    for (var node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
                        if (node.locals && ts.hasProperty(node.locals, name)) {
                            if (node.locals[name].flags & (107455 | 1048576 | 8388608)) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                function getGeneratedNamesForSourceFile(sourceFile) {
                    var links = getNodeLinks(sourceFile);
                    var generatedNames = links.generatedNames;
                    if (!generatedNames) {
                        generatedNames = links.generatedNames = {};
                        generateNames(sourceFile);
                    }
                    return generatedNames;
                    function generateNames(node) {
                        switch (node.kind) {
                            case 195:
                            case 196:
                                generateNameForFunctionOrClassDeclaration(node);
                                break;
                            case 200:
                                generateNameForModuleOrEnum(node);
                                generateNames(node.body);
                                break;
                            case 199:
                                generateNameForModuleOrEnum(node);
                                break;
                            case 204:
                                generateNameForImportDeclaration(node);
                                break;
                            case 210:
                                generateNameForExportDeclaration(node);
                                break;
                            case 209:
                                generateNameForExportAssignment(node);
                                break;
                            case 221:
                            case 201:
                                ts.forEach(node.statements, generateNames);
                                break;
                        }
                    }
                    function isExistingName(name) {
                        return ts.hasProperty(globals, name) || ts.hasProperty(sourceFile.identifiers, name) || ts.hasProperty(generatedNames, name);
                    }
                    function makeUniqueName(baseName) {
                        var name = ts.generateUniqueName(baseName, isExistingName);
                        return generatedNames[name] = name;
                    }
                    function assignGeneratedName(node, name) {
                        getNodeLinks(node).generatedName = ts.unescapeIdentifier(name);
                    }
                    function generateNameForFunctionOrClassDeclaration(node) {
                        if (!node.name) {
                            assignGeneratedName(node, makeUniqueName("default"));
                        }
                    }
                    function generateNameForModuleOrEnum(node) {
                        if (node.name.kind === 64) {
                            var name = node.name.text;
                            assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name));
                        }
                    }
                    function generateNameForImportOrExportDeclaration(node) {
                        var expr = ts.getExternalModuleName(node);
                        var baseName = expr.kind === 8 ? ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module";
                        assignGeneratedName(node, makeUniqueName(baseName));
                    }
                    function generateNameForImportDeclaration(node) {
                        if (node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 207) {
                            generateNameForImportOrExportDeclaration(node);
                        }
                    }
                    function generateNameForExportDeclaration(node) {
                        if (node.moduleSpecifier) {
                            generateNameForImportOrExportDeclaration(node);
                        }
                    }
                    function generateNameForExportAssignment(node) {
                        if (node.expression.kind !== 64) {
                            assignGeneratedName(node, makeUniqueName("default"));
                        }
                    }
                }
                function getGeneratedNameForNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.generatedName) {
                        getGeneratedNamesForSourceFile(getSourceFile(node));
                    }
                    return links.generatedName;
                }
                function getLocalNameOfContainer(container) {
                    return getGeneratedNameForNode(container);
                }
                function getLocalNameForImportDeclaration(node) {
                    return getGeneratedNameForNode(node);
                }
                function getAliasNameSubstitution(symbol) {
                    var declaration = getDeclarationOfAliasSymbol(symbol);
                    if (declaration && declaration.kind === 208) {
                        var moduleName = getGeneratedNameForNode(declaration.parent.parent.parent);
                        var propertyName = declaration.propertyName || declaration.name;
                        return moduleName + "." + ts.unescapeIdentifier(propertyName.text);
                    }
                }
                function getExportNameSubstitution(symbol, location) {
                    if (isExternalModuleSymbol(symbol.parent)) {
                        return "exports." + ts.unescapeIdentifier(symbol.name);
                    }
                    var node = location;
                    var containerSymbol = getParentOfSymbol(symbol);
                    while (node) {
                        if ((node.kind === 200 || node.kind === 199) && getSymbolOfNode(node) === containerSymbol) {
                            return getGeneratedNameForNode(node) + "." + ts.unescapeIdentifier(symbol.name);
                        }
                        node = node.parent;
                    }
                }
                function getExpressionNameSubstitution(node) {
                    var symbol = getNodeLinks(node).resolvedSymbol;
                    if (symbol) {
                        if (symbol.parent) {
                            return getExportNameSubstitution(symbol, node.parent);
                        }
                        var exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
                        if (symbol !== exportSymbol && !(exportSymbol.flags & 944)) {
                            return getExportNameSubstitution(exportSymbol, node.parent);
                        }
                        if (symbol.flags & 8388608) {
                            return getAliasNameSubstitution(symbol);
                        }
                    }
                }
                function hasExportDefaultValue(node) {
                    var symbol = getResolvedExportAssignmentSymbol(getSymbolOfNode(node));
                    return symbol && symbol !== unknownSymbol && symbolIsValue(symbol) && !isConstEnumSymbol(symbol);
                }
                function isTopLevelValueImportEqualsWithEntityName(node) {
                    if (node.parent.kind !== 221 || !ts.isInternalModuleImportEqualsDeclaration(node)) {
                        return false;
                    }
                    return isAliasResolvedToValue(getSymbolOfNode(node));
                }
                function isAliasResolvedToValue(symbol) {
                    var target = resolveAlias(symbol);
                    return target !== unknownSymbol && target.flags & 107455 && !isConstEnumOrConstEnumOnlyModule(target);
                }
                function isConstEnumOrConstEnumOnlyModule(s) {
                    return isConstEnumSymbol(s) || s.constEnumOnlyModule;
                }
                function isReferencedAliasDeclaration(node) {
                    if (isAliasSymbolDeclaration(node)) {
                        var symbol = getSymbolOfNode(node);
                        if (getSymbolLinks(symbol).referenced) {
                            return true;
                        }
                    }
                    return ts.forEachChild(node, isReferencedAliasDeclaration);
                }
                function isImplementationOfOverload(node) {
                    if (ts.nodeIsPresent(node.body)) {
                        var symbol = getSymbolOfNode(node);
                        var signaturesOfSymbol = getSignaturesOfSymbol(symbol);
                        return signaturesOfSymbol.length > 1 || (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
                    }
                    return false;
                }
                function getNodeCheckFlags(node) {
                    return getNodeLinks(node).flags;
                }
                function getEnumMemberValue(node) {
                    computeEnumMemberValues(node.parent);
                    return getNodeLinks(node).enumMemberValue;
                }
                function getConstantValue(node) {
                    if (node.kind === 220) {
                        return getEnumMemberValue(node);
                    }
                    var symbol = getNodeLinks(node).resolvedSymbol;
                    if (symbol && (symbol.flags & 8)) {
                        var declaration = symbol.valueDeclaration;
                        var constantValue;
                        if (declaration.kind === 220) {
                            return getEnumMemberValue(declaration);
                        }
                    }
                    return undefined;
                }
                function writeTypeOfDeclaration(declaration, enclosingDeclaration, flags, writer) {
                    var symbol = getSymbolOfNode(declaration);
                    var type = symbol && !(symbol.flags & (2048 | 131072)) ? getTypeOfSymbol(symbol) : unknownType;
                    getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                }
                function writeReturnTypeOfSignatureDeclaration(signatureDeclaration, enclosingDeclaration, flags, writer) {
                    var signature = getSignatureFromDeclaration(signatureDeclaration);
                    getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags);
                }
                function isUnknownIdentifier(location, name) {
                    ts.Debug.assert(!ts.nodeIsSynthesized(location), "isUnknownIdentifier called with a synthesized location");
                    return !resolveName(location, name, 107455, undefined, undefined) && !ts.hasProperty(getGeneratedNamesForSourceFile(getSourceFile(location)), name);
                }
                function getBlockScopedVariableId(n) {
                    ts.Debug.assert(!ts.nodeIsSynthesized(n));
                    if (n.parent.kind === 153 && n.parent.name === n) {
                        return undefined;
                    }
                    if (n.parent.kind === 150 && n.parent.propertyName === n) {
                        return undefined;
                    }
                    var declarationSymbol = (n.parent.kind === 193 && n.parent.name === n) || n.parent.kind === 150 ? getSymbolOfNode(n.parent) : undefined;
                    var symbol = declarationSymbol || getNodeLinks(n).resolvedSymbol || resolveName(n, n.text, 2 | 8388608, undefined, undefined);
                    var isLetOrConst = symbol && (symbol.flags & 2) && symbol.valueDeclaration.parent.kind !== 217;
                    if (isLetOrConst) {
                        getSymbolLinks(symbol);
                        return symbol.id;
                    }
                    return undefined;
                }
                function createResolver() {
                    return {
                        getGeneratedNameForNode: getGeneratedNameForNode,
                        getExpressionNameSubstitution: getExpressionNameSubstitution,
                        hasExportDefaultValue: hasExportDefaultValue,
                        isReferencedAliasDeclaration: isReferencedAliasDeclaration,
                        getNodeCheckFlags: getNodeCheckFlags,
                        isTopLevelValueImportEqualsWithEntityName: isTopLevelValueImportEqualsWithEntityName,
                        isDeclarationVisible: isDeclarationVisible,
                        isImplementationOfOverload: isImplementationOfOverload,
                        writeTypeOfDeclaration: writeTypeOfDeclaration,
                        writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration,
                        isSymbolAccessible: isSymbolAccessible,
                        isEntityNameVisible: isEntityNameVisible,
                        getConstantValue: getConstantValue,
                        isUnknownIdentifier: isUnknownIdentifier,
                        getBlockScopedVariableId: getBlockScopedVariableId
                    };
                }
                function initializeTypeChecker() {
                    ts.forEach(host.getSourceFiles(), function (file) {
                        ts.bindSourceFile(file);
                    });
                    ts.forEach(host.getSourceFiles(), function (file) {
                        if (!ts.isExternalModule(file)) {
                            mergeSymbolTable(globals, file.locals);
                        }
                    });
                    getSymbolLinks(undefinedSymbol).type = undefinedType;
                    getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
                    getSymbolLinks(unknownSymbol).type = unknownType;
                    globals[undefinedSymbol.name] = undefinedSymbol;
                    globalArraySymbol = getGlobalTypeSymbol("Array");
                    globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, 1);
                    globalObjectType = getGlobalType("Object");
                    globalFunctionType = getGlobalType("Function");
                    globalStringType = getGlobalType("String");
                    globalNumberType = getGlobalType("Number");
                    globalBooleanType = getGlobalType("Boolean");
                    globalRegExpType = getGlobalType("RegExp");
                    if (languageVersion >= 2) {
                        globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
                        globalESSymbolType = getGlobalType("Symbol");
                        globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
                        globalIterableType = getGlobalType("Iterable", 1);
                    }
                    else {
                        globalTemplateStringsArrayType = unknownType;
                        globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                        globalESSymbolConstructorSymbol = undefined;
                    }
                    anyArrayType = createArrayType(anyType);
                }
                function checkGrammarModifiers(node) {
                    switch (node.kind) {
                        case 134:
                        case 135:
                        case 133:
                        case 130:
                        case 129:
                        case 132:
                        case 131:
                        case 138:
                        case 196:
                        case 197:
                        case 200:
                        case 199:
                        case 175:
                        case 195:
                        case 198:
                        case 204:
                        case 203:
                        case 210:
                        case 209:
                        case 128:
                            break;
                        default:
                            return false;
                    }
                    if (!node.modifiers) {
                        return;
                    }
                    var lastStatic, lastPrivate, lastProtected, lastDeclare;
                    var flags = 0;
                    for (var i = 0, n = node.modifiers.length; i < n; i++) {
                        var modifier = node.modifiers[i];
                        switch (modifier.kind) {
                            case 108:
                            case 107:
                            case 106:
                                var text;
                                if (modifier.kind === 108) {
                                    text = "public";
                                }
                                else if (modifier.kind === 107) {
                                    text = "protected";
                                    lastProtected = modifier;
                                }
                                else {
                                    text = "private";
                                    lastPrivate = modifier;
                                }
                                if (flags & 112) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen);
                                }
                                else if (flags & 128) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
                                }
                                else if (node.parent.kind === 201 || node.parent.kind === 221) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
                                }
                                flags |= ts.modifierToFlag(modifier.kind);
                                break;
                            case 109:
                                if (flags & 128) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static");
                                }
                                else if (node.parent.kind === 201 || node.parent.kind === 221) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
                                }
                                else if (node.kind === 128) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
                                }
                                flags |= 128;
                                lastStatic = modifier;
                                break;
                            case 77:
                                if (flags & 1) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export");
                                }
                                else if (flags & 2) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
                                }
                                else if (node.parent.kind === 196) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
                                }
                                else if (node.kind === 128) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
                                }
                                flags |= 1;
                                break;
                            case 114:
                                if (flags & 2) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare");
                                }
                                else if (node.parent.kind === 196) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
                                }
                                else if (node.kind === 128) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare");
                                }
                                else if (ts.isInAmbientContext(node.parent) && node.parent.kind === 201) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
                                }
                                flags |= 2;
                                lastDeclare = modifier;
                                break;
                        }
                    }
                    if (node.kind === 133) {
                        if (flags & 128) {
                            return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
                        }
                        else if (flags & 64) {
                            return grammarErrorOnNode(lastProtected, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
                        }
                        else if (flags & 32) {
                            return grammarErrorOnNode(lastPrivate, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
                        }
                    }
                    else if ((node.kind === 204 || node.kind === 203) && flags & 2) {
                        return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
                    }
                    else if (node.kind === 197 && flags & 2) {
                        return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
                    }
                    else if (node.kind === 128 && (flags & 112) && ts.isBindingPattern(node.name)) {
                        return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
                    }
                }
                function checkGrammarForDisallowedTrailingComma(list) {
                    if (list && list.hasTrailingComma) {
                        var start = list.end - ",".length;
                        var end = list.end;
                        var sourceFile = ts.getSourceFileOfNode(list[0]);
                        return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Trailing_comma_not_allowed);
                    }
                }
                function checkGrammarTypeParameterList(node, typeParameters) {
                    if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
                        return true;
                    }
                    if (typeParameters && typeParameters.length === 0) {
                        var start = typeParameters.pos - "<".length;
                        var sourceFile = ts.getSourceFileOfNode(node);
                        var end = ts.skipTrivia(sourceFile.text, typeParameters.end) + ">".length;
                        return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Type_parameter_list_cannot_be_empty);
                    }
                }
                function checkGrammarParameterList(parameters) {
                    if (checkGrammarForDisallowedTrailingComma(parameters)) {
                        return true;
                    }
                    var seenOptionalParameter = false;
                    var parameterCount = parameters.length;
                    for (var i = 0; i < parameterCount; i++) {
                        var parameter = parameters[i];
                        if (parameter.dotDotDotToken) {
                            if (i !== (parameterCount - 1)) {
                                return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
                            }
                            if (parameter.questionToken) {
                                return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_rest_parameter_cannot_be_optional);
                            }
                            if (parameter.initializer) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_parameter_cannot_have_an_initializer);
                            }
                        }
                        else if (parameter.questionToken || parameter.initializer) {
                            seenOptionalParameter = true;
                            if (parameter.questionToken && parameter.initializer) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
                            }
                        }
                        else {
                            if (seenOptionalParameter) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
                            }
                        }
                    }
                }
                function checkGrammarFunctionLikeDeclaration(node) {
                    return checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters) || checkGrammarParameterList(node.parameters);
                }
                function checkGrammarIndexSignatureParameters(node) {
                    var parameter = node.parameters[0];
                    if (node.parameters.length !== 1) {
                        if (parameter) {
                            return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
                        }
                        else {
                            return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
                        }
                    }
                    if (parameter.dotDotDotToken) {
                        return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
                    }
                    if (parameter.flags & 499) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
                    }
                    if (parameter.questionToken) {
                        return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark);
                    }
                    if (parameter.initializer) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_initializer);
                    }
                    if (!parameter.type) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
                    }
                    if (parameter.type.kind !== 120 && parameter.type.kind !== 118) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_or_number);
                    }
                    if (!node.type) {
                        return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_a_type_annotation);
                    }
                }
                function checkGrammarForIndexSignatureModifier(node) {
                    if (node.flags & 499) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_not_permitted_on_index_signature_members);
                    }
                }
                function checkGrammarIndexSignature(node) {
                    checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
                }
                function checkGrammarForAtLeastOneTypeArgument(node, typeArguments) {
                    if (typeArguments && typeArguments.length === 0) {
                        var sourceFile = ts.getSourceFileOfNode(node);
                        var start = typeArguments.pos - "<".length;
                        var end = ts.skipTrivia(sourceFile.text, typeArguments.end) + ">".length;
                        return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Type_argument_list_cannot_be_empty);
                    }
                }
                function checkGrammarTypeArguments(node, typeArguments) {
                    return checkGrammarForDisallowedTrailingComma(typeArguments) || checkGrammarForAtLeastOneTypeArgument(node, typeArguments);
                }
                function checkGrammarForOmittedArgument(node, arguments) {
                    if (arguments) {
                        var sourceFile = ts.getSourceFileOfNode(node);
                        for (var i = 0, n = arguments.length; i < n; i++) {
                            var arg = arguments[i];
                            if (arg.kind === 172) {
                                return grammarErrorAtPos(sourceFile, arg.pos, 0, ts.Diagnostics.Argument_expression_expected);
                            }
                        }
                    }
                }
                function checkGrammarArguments(node, arguments) {
                    return checkGrammarForDisallowedTrailingComma(arguments) || checkGrammarForOmittedArgument(node, arguments);
                }
                function checkGrammarHeritageClause(node) {
                    var types = node.types;
                    if (checkGrammarForDisallowedTrailingComma(types)) {
                        return true;
                    }
                    if (types && types.length === 0) {
                        var listType = ts.tokenToString(node.token);
                        var sourceFile = ts.getSourceFileOfNode(node);
                        return grammarErrorAtPos(sourceFile, types.pos, 0, ts.Diagnostics._0_list_cannot_be_empty, listType);
                    }
                }
                function checkGrammarClassDeclarationHeritageClauses(node) {
                    var seenExtendsClause = false;
                    var seenImplementsClause = false;
                    if (!checkGrammarModifiers(node) && node.heritageClauses) {
                        for (var i = 0, n = node.heritageClauses.length; i < n; i++) {
                            ts.Debug.assert(i <= 2);
                            var heritageClause = node.heritageClauses[i];
                            if (heritageClause.token === 78) {
                                if (seenExtendsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
                                }
                                if (seenImplementsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_must_precede_implements_clause);
                                }
                                if (heritageClause.types.length > 1) {
                                    return grammarErrorOnFirstToken(heritageClause.types[1], ts.Diagnostics.Classes_can_only_extend_a_single_class);
                                }
                                seenExtendsClause = true;
                            }
                            else {
                                ts.Debug.assert(heritageClause.token === 102);
                                if (seenImplementsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen);
                                }
                                seenImplementsClause = true;
                            }
                            checkGrammarHeritageClause(heritageClause);
                        }
                    }
                }
                function checkGrammarInterfaceDeclaration(node) {
                    var seenExtendsClause = false;
                    if (node.heritageClauses) {
                        for (var i = 0, n = node.heritageClauses.length; i < n; i++) {
                            ts.Debug.assert(i <= 1);
                            var heritageClause = node.heritageClauses[i];
                            if (heritageClause.token === 78) {
                                if (seenExtendsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
                                }
                                seenExtendsClause = true;
                            }
                            else {
                                ts.Debug.assert(heritageClause.token === 102);
                                return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause);
                            }
                            checkGrammarHeritageClause(heritageClause);
                        }
                    }
                    return false;
                }
                function checkGrammarComputedPropertyName(node) {
                    if (node.kind !== 126) {
                        return false;
                    }
                    var computedPropertyName = node;
                    if (computedPropertyName.expression.kind === 167 && computedPropertyName.expression.operatorToken.kind === 23) {
                        return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
                    }
                }
                function checkGrammarForGenerator(node) {
                    if (node.asteriskToken) {
                        return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_currently_supported);
                    }
                }
                function checkGrammarFunctionName(name) {
                    return checkGrammarEvalOrArgumentsInStrictMode(name, name);
                }
                function checkGrammarForInvalidQuestionMark(node, questionToken, message) {
                    if (questionToken) {
                        return grammarErrorOnNode(questionToken, message);
                    }
                }
                function checkGrammarObjectLiteralExpression(node) {
                    var seen = {};
                    var Property = 1;
                    var GetAccessor = 2;
                    var SetAccesor = 4;
                    var GetOrSetAccessor = GetAccessor | SetAccesor;
                    var inStrictMode = (node.parserContextFlags & 1) !== 0;
                    for (var i = 0, n = node.properties.length; i < n; i++) {
                        var prop = node.properties[i];
                        var name = prop.name;
                        if (prop.kind === 172 || name.kind === 126) {
                            checkGrammarComputedPropertyName(name);
                            continue;
                        }
                        var currentKind;
                        if (prop.kind === 218 || prop.kind === 219) {
                            checkGrammarForInvalidQuestionMark(prop, prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional);
                            if (name.kind === 7) {
                                checkGrammarNumbericLiteral(name);
                            }
                            currentKind = Property;
                        }
                        else if (prop.kind === 132) {
                            currentKind = Property;
                        }
                        else if (prop.kind === 134) {
                            currentKind = GetAccessor;
                        }
                        else if (prop.kind === 135) {
                            currentKind = SetAccesor;
                        }
                        else {
                            ts.Debug.fail("Unexpected syntax kind:" + prop.kind);
                        }
                        if (!ts.hasProperty(seen, name.text)) {
                            seen[name.text] = currentKind;
                        }
                        else {
                            var existingKind = seen[name.text];
                            if (currentKind === Property && existingKind === Property) {
                                if (inStrictMode) {
                                    grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
                                }
                            }
                            else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) {
                                if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) {
                                    seen[name.text] = currentKind | existingKind;
                                }
                                else {
                                    return grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
                                }
                            }
                            else {
                                return grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
                            }
                        }
                    }
                }
                function checkGrammarForInOrForOfStatement(forInOrOfStatement) {
                    if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) {
                        return true;
                    }
                    if (forInOrOfStatement.initializer.kind === 194) {
                        var variableList = forInOrOfStatement.initializer;
                        if (!checkGrammarVariableDeclarationList(variableList)) {
                            if (variableList.declarations.length > 1) {
                                var diagnostic = forInOrOfStatement.kind === 182 ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
                                return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
                            }
                            var firstDeclaration = variableList.declarations[0];
                            if (firstDeclaration.initializer) {
                                var diagnostic = forInOrOfStatement.kind === 182 ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer;
                                return grammarErrorOnNode(firstDeclaration.name, diagnostic);
                            }
                            if (firstDeclaration.type) {
                                var diagnostic = forInOrOfStatement.kind === 182 ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation;
                                return grammarErrorOnNode(firstDeclaration, diagnostic);
                            }
                        }
                    }
                    return false;
                }
                function checkGrammarAccessor(accessor) {
                    var kind = accessor.kind;
                    if (languageVersion < 1) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
                    }
                    else if (ts.isInAmbientContext(accessor)) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context);
                    }
                    else if (accessor.body === undefined) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(accessor), accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
                    }
                    else if (accessor.typeParameters) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters);
                    }
                    else if (kind === 134 && accessor.parameters.length) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_get_accessor_cannot_have_parameters);
                    }
                    else if (kind === 135) {
                        if (accessor.type) {
                            return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
                        }
                        else if (accessor.parameters.length !== 1) {
                            return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
                        }
                        else {
                            var parameter = accessor.parameters[0];
                            if (parameter.dotDotDotToken) {
                                return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_set_accessor_cannot_have_rest_parameter);
                            }
                            else if (parameter.flags & 499) {
                                return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
                            }
                            else if (parameter.questionToken) {
                                return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
                            }
                            else if (parameter.initializer) {
                                return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
                            }
                        }
                    }
                }
                function checkGrammarForNonSymbolComputedProperty(node, message) {
                    if (node.kind === 126 && !ts.isWellKnownSymbolSyntactically(node.expression)) {
                        return grammarErrorOnNode(node, message);
                    }
                }
                function checkGrammarMethod(node) {
                    if (checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarFunctionLikeDeclaration(node) || checkGrammarForGenerator(node)) {
                        return true;
                    }
                    if (node.parent.kind === 152) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
                            return true;
                        }
                        else if (node.body === undefined) {
                            return grammarErrorAtPos(getSourceFile(node), node.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
                        }
                    }
                    if (node.parent.kind === 196) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
                            return true;
                        }
                        if (ts.isInAmbientContext(node)) {
                            return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol);
                        }
                        else if (!node.body) {
                            return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol);
                        }
                    }
                    else if (node.parent.kind === 197) {
                        return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol);
                    }
                    else if (node.parent.kind === 143) {
                        return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol);
                    }
                }
                function isIterationStatement(node, lookInLabeledStatements) {
                    switch (node.kind) {
                        case 181:
                        case 182:
                        case 183:
                        case 179:
                        case 180:
                            return true;
                        case 189:
                            return lookInLabeledStatements && isIterationStatement(node.statement, lookInLabeledStatements);
                    }
                    return false;
                }
                function checkGrammarBreakOrContinueStatement(node) {
                    var current = node;
                    while (current) {
                        if (ts.isFunctionLike(current)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary);
                        }
                        switch (current.kind) {
                            case 189:
                                if (node.label && current.label.text === node.label.text) {
                                    var isMisplacedContinueLabel = node.kind === 184 && !isIterationStatement(current.statement, true);
                                    if (isMisplacedContinueLabel) {
                                        return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
                                    }
                                    return false;
                                }
                                break;
                            case 188:
                                if (node.kind === 185 && !node.label) {
                                    return false;
                                }
                                break;
                            default:
                                if (isIterationStatement(current, false) && !node.label) {
                                    return false;
                                }
                                break;
                        }
                        current = current.parent;
                    }
                    if (node.label) {
                        var message = node.kind === 185 ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement;
                        return grammarErrorOnNode(node, message);
                    }
                    else {
                        var message = node.kind === 185 ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement;
                        return grammarErrorOnNode(node, message);
                    }
                }
                function checkGrammarBindingElement(node) {
                    if (node.dotDotDotToken) {
                        var elements = node.parent.elements;
                        if (node !== elements[elements.length - 1]) {
                            return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
                        }
                        if (node.initializer) {
                            return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer);
                        }
                    }
                    return checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                }
                function checkGrammarVariableDeclaration(node) {
                    if (node.parent.parent.kind !== 182 && node.parent.parent.kind !== 183) {
                        if (ts.isInAmbientContext(node)) {
                            if (ts.isBindingPattern(node.name)) {
                                return grammarErrorOnNode(node, ts.Diagnostics.Destructuring_declarations_are_not_allowed_in_ambient_contexts);
                            }
                            if (node.initializer) {
                                var equalsTokenLength = "=".length;
                                return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
                            }
                        }
                        else if (!node.initializer) {
                            if (ts.isBindingPattern(node.name) && !ts.isBindingPattern(node.parent)) {
                                return grammarErrorOnNode(node, ts.Diagnostics.A_destructuring_declaration_must_have_an_initializer);
                            }
                            if (ts.isConst(node)) {
                                return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_must_be_initialized);
                            }
                        }
                    }
                    var checkLetConstNames = languageVersion >= 2 && (ts.isLet(node) || ts.isConst(node));
                    return (checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name)) || checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                }
                function checkGrammarNameInLetOrConstDeclarations(name) {
                    if (name.kind === 64) {
                        if (name.text === "let") {
                            return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
                        }
                    }
                    else {
                        var elements = name.elements;
                        for (var i = 0; i < elements.length; ++i) {
                            checkGrammarNameInLetOrConstDeclarations(elements[i].name);
                        }
                    }
                }
                function checkGrammarVariableDeclarationList(declarationList) {
                    var declarations = declarationList.declarations;
                    if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) {
                        return true;
                    }
                    if (!declarationList.declarations.length) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, ts.Diagnostics.Variable_declaration_list_cannot_be_empty);
                    }
                }
                function allowLetAndConstDeclarations(parent) {
                    switch (parent.kind) {
                        case 178:
                        case 179:
                        case 180:
                        case 187:
                        case 181:
                        case 182:
                        case 183:
                            return false;
                        case 189:
                            return allowLetAndConstDeclarations(parent.parent);
                    }
                    return true;
                }
                function checkGrammarForDisallowedLetOrConstStatement(node) {
                    if (!allowLetAndConstDeclarations(node.parent)) {
                        if (ts.isLet(node.declarationList)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
                        }
                        else if (ts.isConst(node.declarationList)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
                        }
                    }
                }
                function isIntegerLiteral(expression) {
                    if (expression.kind === 165) {
                        var unaryExpression = expression;
                        if (unaryExpression.operator === 33 || unaryExpression.operator === 34) {
                            expression = unaryExpression.operand;
                        }
                    }
                    if (expression.kind === 7) {
                        return /^[0-9]+([eE]\+?[0-9]+)?$/.test(expression.text);
                    }
                    return false;
                }
                function checkGrammarEnumDeclaration(enumDecl) {
                    var enumIsConst = (enumDecl.flags & 8192) !== 0;
                    var hasError = false;
                    if (!enumIsConst) {
                        var inConstantEnumMemberSection = true;
                        var inAmbientContext = ts.isInAmbientContext(enumDecl);
                        for (var i = 0, n = enumDecl.members.length; i < n; i++) {
                            var node = enumDecl.members[i];
                            if (node.name.kind === 126) {
                                hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums);
                            }
                            else if (inAmbientContext) {
                                if (node.initializer && !isIntegerLiteral(node.initializer)) {
                                    hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers) || hasError;
                                }
                            }
                            else if (node.initializer) {
                                inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
                            }
                            else if (!inConstantEnumMemberSection) {
                                hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Enum_member_must_have_initializer) || hasError;
                            }
                        }
                    }
                    return hasError;
                }
                function hasParseDiagnostics(sourceFile) {
                    return sourceFile.parseDiagnostics.length > 0;
                }
                function grammarErrorOnFirstToken(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function grammarErrorAtPos(sourceFile, start, length, message, arg0, arg1, arg2) {
                    if (!hasParseDiagnostics(sourceFile)) {
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function grammarErrorOnNode(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        diagnostics.add(ts.createDiagnosticForNode(node, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function checkGrammarEvalOrArgumentsInStrictMode(contextNode, name) {
                    if (name && name.kind === 64) {
                        var identifier = name;
                        if (contextNode && (contextNode.parserContextFlags & 1) && ts.isEvalOrArgumentsIdentifier(identifier)) {
                            var nameText = ts.declarationNameToString(identifier);
                            return grammarErrorOnNode(identifier, ts.Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
                        }
                    }
                }
                function checkGrammarConstructorTypeParameters(node) {
                    if (node.typeParameters) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.typeParameters.pos, node.typeParameters.end - node.typeParameters.pos, ts.Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration);
                    }
                }
                function checkGrammarConstructorTypeAnnotation(node) {
                    if (node.type) {
                        return grammarErrorOnNode(node.type, ts.Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration);
                    }
                }
                function checkGrammarProperty(node) {
                    if (node.parent.kind === 196) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional) || checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    else if (node.parent.kind === 197) {
                        if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    else if (node.parent.kind === 143) {
                        if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    if (ts.isInAmbientContext(node) && node.initializer) {
                        return grammarErrorOnFirstToken(node.initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
                    }
                }
                function checkGrammarTopLevelElementForRequiredDeclareModifier(node) {
                    if (node.kind === 197 || node.kind === 204 || node.kind === 203 || node.kind === 210 || node.kind === 209 || (node.flags & 2)) {
                        return false;
                    }
                    return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
                }
                function checkGrammarTopLevelElementsForRequiredDeclareModifier(file) {
                    for (var i = 0, n = file.statements.length; i < n; i++) {
                        var decl = file.statements[i];
                        if (ts.isDeclaration(decl) || decl.kind === 175) {
                            if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) {
                                return true;
                            }
                        }
                    }
                }
                function checkGrammarSourceFile(node) {
                    return ts.isInAmbientContext(node) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node);
                }
                function checkGrammarStatementInAmbientContext(node) {
                    if (ts.isInAmbientContext(node)) {
                        if (isAccessor(node.parent.kind)) {
                            return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
                        }
                        var links = getNodeLinks(node);
                        if (!links.hasReportedStatementInAmbientContext && ts.isFunctionLike(node.parent)) {
                            return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
                        }
                        if (node.parent.kind === 174 || node.parent.kind === 201 || node.parent.kind === 221) {
                            var links = getNodeLinks(node.parent);
                            if (!links.hasReportedStatementInAmbientContext) {
                                return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
                            }
                        }
                        else {
                        }
                    }
                }
                function checkGrammarNumbericLiteral(node) {
                    if (node.flags & 16384) {
                        if (node.parserContextFlags & 1) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
                        }
                        else if (languageVersion >= 1) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
                        }
                    }
                }
                function grammarErrorAfterFirstToken(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), 0, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                initializeTypeChecker();
                return checker;
            }
            ts.createTypeChecker = createTypeChecker;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var indentStrings = [
                "",
                "    "
            ];
            function getIndentString(level) {
                if (indentStrings[level] === undefined) {
                    indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
                }
                return indentStrings[level];
            }
            ts.getIndentString = getIndentString;
            function getIndentSize() {
                return indentStrings[1].length;
            }
            function shouldEmitToOwnFile(sourceFile, compilerOptions) {
                if (!ts.isDeclarationFile(sourceFile)) {
                    if ((ts.isExternalModule(sourceFile) || !compilerOptions.out) && !ts.fileExtensionIs(sourceFile.fileName, ".js")) {
                        return true;
                    }
                    return false;
                }
                return false;
            }
            ts.shouldEmitToOwnFile = shouldEmitToOwnFile;
            function isExternalModuleOrDeclarationFile(sourceFile) {
                return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile);
            }
            ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile;
            function createTextWriter(newLine) {
                var output = "";
                var indent = 0;
                var lineStart = true;
                var lineCount = 0;
                var linePos = 0;
                function write(s) {
                    if (s && s.length) {
                        if (lineStart) {
                            output += getIndentString(indent);
                            lineStart = false;
                        }
                        output += s;
                    }
                }
                function rawWrite(s) {
                    if (s !== undefined) {
                        if (lineStart) {
                            lineStart = false;
                        }
                        output += s;
                    }
                }
                function writeLiteral(s) {
                    if (s && s.length) {
                        write(s);
                        var lineStartsOfS = ts.computeLineStarts(s);
                        if (lineStartsOfS.length > 1) {
                            lineCount = lineCount + lineStartsOfS.length - 1;
                            linePos = output.length - s.length + lineStartsOfS[lineStartsOfS.length - 1];
                        }
                    }
                }
                function writeLine() {
                    if (!lineStart) {
                        output += newLine;
                        lineCount++;
                        linePos = output.length;
                        lineStart = true;
                    }
                }
                function writeTextOfNode(sourceFile, node) {
                    write(ts.getSourceTextOfNodeFromSourceFile(sourceFile, node));
                }
                return {
                    write: write,
                    rawWrite: rawWrite,
                    writeTextOfNode: writeTextOfNode,
                    writeLiteral: writeLiteral,
                    writeLine: writeLine,
                    increaseIndent: function () {
                        return indent++;
                    },
                    decreaseIndent: function () {
                        return indent--;
                    },
                    getIndent: function () {
                        return indent;
                    },
                    getTextPos: function () {
                        return output.length;
                    },
                    getLine: function () {
                        return lineCount + 1;
                    },
                    getColumn: function () {
                        return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1;
                    },
                    getText: function () {
                        return output;
                    }
                };
            }
            function getLineOfLocalPosition(currentSourceFile, pos) {
                return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line;
            }
            function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) {
                if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
                    writer.writeLine();
                }
            }
            function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) {
                var emitLeadingSpace = !trailingSeparator;
                ts.forEach(comments, function (comment) {
                    if (emitLeadingSpace) {
                        writer.write(" ");
                        emitLeadingSpace = false;
                    }
                    writeComment(currentSourceFile, writer, comment, newLine);
                    if (comment.hasTrailingNewLine) {
                        writer.writeLine();
                    }
                    else if (trailingSeparator) {
                        writer.write(" ");
                    }
                    else {
                        emitLeadingSpace = true;
                    }
                });
            }
            function writeCommentRange(currentSourceFile, writer, comment, newLine) {
                if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) {
                    var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
                    var lineCount = ts.getLineStarts(currentSourceFile).length;
                    var firstCommentLineIndent;
                    for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
                        var nextLineStart = (currentLine + 1) === lineCount ? currentSourceFile.text.length + 1 : ts.getStartPositionOfLine(currentLine + 1, currentSourceFile);
                        if (pos !== comment.pos) {
                            if (firstCommentLineIndent === undefined) {
                                firstCommentLineIndent = calculateIndent(ts.getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
                            }
                            var currentWriterIndentSpacing = writer.getIndent() * getIndentSize();
                            var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
                            if (spacesToEmit > 0) {
                                var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
                                var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
                                writer.rawWrite(indentSizeSpaceString);
                                while (numberOfSingleSpacesToEmit) {
                                    writer.rawWrite(" ");
                                    numberOfSingleSpacesToEmit--;
                                }
                            }
                            else {
                                writer.rawWrite("");
                            }
                        }
                        writeTrimmedCurrentLine(pos, nextLineStart);
                        pos = nextLineStart;
                    }
                }
                else {
                    writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
                }
                function writeTrimmedCurrentLine(pos, nextLineStart) {
                    var end = Math.min(comment.end, nextLineStart - 1);
                    var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, '');
                    if (currentLineText) {
                        writer.write(currentLineText);
                        if (end !== comment.end) {
                            writer.writeLine();
                        }
                    }
                    else {
                        writer.writeLiteral(newLine);
                    }
                }
                function calculateIndent(pos, end) {
                    var currentLineIndent = 0;
                    for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
                        if (currentSourceFile.text.charCodeAt(pos) === 9) {
                            currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
                        }
                        else {
                            currentLineIndent++;
                        }
                    }
                    return currentLineIndent;
                }
            }
            function getFirstConstructorWithBody(node) {
                return ts.forEach(node.members, function (member) {
                    if (member.kind === 133 && ts.nodeIsPresent(member.body)) {
                        return member;
                    }
                });
            }
            function getAllAccessorDeclarations(declarations, accessor) {
                var firstAccessor;
                var getAccessor;
                var setAccessor;
                if (ts.hasDynamicName(accessor)) {
                    firstAccessor = accessor;
                    if (accessor.kind === 134) {
                        getAccessor = accessor;
                    }
                    else if (accessor.kind === 135) {
                        setAccessor = accessor;
                    }
                    else {
                        ts.Debug.fail("Accessor has wrong kind");
                    }
                }
                else {
                    ts.forEach(declarations, function (member) {
                        if ((member.kind === 134 || member.kind === 135) && (member.flags & 128) === (accessor.flags & 128)) {
                            var memberName = ts.getPropertyNameForPropertyNameNode(member.name);
                            var accessorName = ts.getPropertyNameForPropertyNameNode(accessor.name);
                            if (memberName === accessorName) {
                                if (!firstAccessor) {
                                    firstAccessor = member;
                                }
                                if (member.kind === 134 && !getAccessor) {
                                    getAccessor = member;
                                }
                                if (member.kind === 135 && !setAccessor) {
                                    setAccessor = member;
                                }
                            }
                        }
                    });
                }
                return {
                    firstAccessor: firstAccessor,
                    getAccessor: getAccessor,
                    setAccessor: setAccessor
                };
            }
            function getSourceFilePathInNewDir(sourceFile, host, newDirPath) {
                var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
                sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
                return ts.combinePaths(newDirPath, sourceFilePath);
            }
            function getOwnEmitOutputFilePath(sourceFile, host, extension) {
                var compilerOptions = host.getCompilerOptions();
                if (compilerOptions.outDir) {
                    var emitOutputFilePathWithoutExtension = ts.removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir));
                }
                else {
                    var emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
                }
                return emitOutputFilePathWithoutExtension + extension;
            }
            function writeFile(host, diagnostics, fileName, data, writeByteOrderMark) {
                host.writeFile(fileName, data, writeByteOrderMark, function (hostErrorMessage) {
                    diagnostics.push(ts.createCompilerDiagnostic(ts.Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage));
                });
            }
            function emitDeclarations(host, resolver, diagnostics, jsFilePath, root) {
                var newLine = host.getNewLine();
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0;
                var write;
                var writeLine;
                var increaseIndent;
                var decreaseIndent;
                var writeTextOfNode;
                var writer = createAndSetNewTextWriterWithSymbolWriter();
                var enclosingDeclaration;
                var currentSourceFile;
                var reportedDeclarationError = false;
                var emitJsDocComments = compilerOptions.removeComments ? function (declaration) {
                } : writeJsDocComments;
                var emit = compilerOptions.stripInternal ? stripInternal : emitNode;
                var aliasDeclarationEmitInfo = [];
                var referencePathsOutput = "";
                if (root) {
                    if (!compilerOptions.noResolve) {
                        var addedGlobalFileReference = false;
                        ts.forEach(root.referencedFiles, function (fileReference) {
                            var referencedFile = ts.tryResolveScriptReference(host, root, fileReference);
                            if (referencedFile && ((referencedFile.flags & 2048) || shouldEmitToOwnFile(referencedFile, compilerOptions) || !addedGlobalFileReference)) {
                                writeReferencePath(referencedFile);
                                if (!isExternalModuleOrDeclarationFile(referencedFile)) {
                                    addedGlobalFileReference = true;
                                }
                            }
                        });
                    }
                    emitSourceFile(root);
                }
                else {
                    var emittedReferencedFiles = [];
                    ts.forEach(host.getSourceFiles(), function (sourceFile) {
                        if (!isExternalModuleOrDeclarationFile(sourceFile)) {
                            if (!compilerOptions.noResolve) {
                                ts.forEach(sourceFile.referencedFiles, function (fileReference) {
                                    var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference);
                                    if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) && !ts.contains(emittedReferencedFiles, referencedFile))) {
                                        writeReferencePath(referencedFile);
                                        emittedReferencedFiles.push(referencedFile);
                                    }
                                });
                            }
                            emitSourceFile(sourceFile);
                        }
                    });
                }
                return {
                    reportedDeclarationError: reportedDeclarationError,
                    aliasDeclarationEmitInfo: aliasDeclarationEmitInfo,
                    synchronousDeclarationOutput: writer.getText(),
                    referencePathsOutput: referencePathsOutput
                };
                function hasInternalAnnotation(range) {
                    var text = currentSourceFile.text;
                    var comment = text.substring(range.pos, range.end);
                    return comment.indexOf("@internal") >= 0;
                }
                function stripInternal(node) {
                    if (node) {
                        var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
                        if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) {
                            return;
                        }
                        emitNode(node);
                    }
                }
                function createAndSetNewTextWriterWithSymbolWriter() {
                    var writer = createTextWriter(newLine);
                    writer.trackSymbol = trackSymbol;
                    writer.writeKeyword = writer.write;
                    writer.writeOperator = writer.write;
                    writer.writePunctuation = writer.write;
                    writer.writeSpace = writer.write;
                    writer.writeStringLiteral = writer.writeLiteral;
                    writer.writeParameter = writer.write;
                    writer.writeSymbol = writer.write;
                    setWriter(writer);
                    return writer;
                }
                function setWriter(newWriter) {
                    writer = newWriter;
                    write = newWriter.write;
                    writeTextOfNode = newWriter.writeTextOfNode;
                    writeLine = newWriter.writeLine;
                    increaseIndent = newWriter.increaseIndent;
                    decreaseIndent = newWriter.decreaseIndent;
                }
                function writeAsychronousImportEqualsDeclarations(importEqualsDeclarations) {
                    var oldWriter = writer;
                    ts.forEach(importEqualsDeclarations, function (aliasToWrite) {
                        var aliasEmitInfo = ts.forEach(aliasDeclarationEmitInfo, function (declEmitInfo) {
                            return declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined;
                        });
                        if (aliasEmitInfo) {
                            createAndSetNewTextWriterWithSymbolWriter();
                            for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
                                increaseIndent();
                            }
                            writeImportEqualsDeclaration(aliasToWrite);
                            aliasEmitInfo.asynchronousOutput = writer.getText();
                        }
                    });
                    setWriter(oldWriter);
                }
                function handleSymbolAccessibilityError(symbolAccesibilityResult) {
                    if (symbolAccesibilityResult.accessibility === 0) {
                        if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
                            writeAsychronousImportEqualsDeclarations(symbolAccesibilityResult.aliasesToMakeVisible);
                        }
                    }
                    else {
                        reportedDeclarationError = true;
                        var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
                        if (errorInfo) {
                            if (errorInfo.typeName) {
                                diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
                            }
                            else {
                                diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
                            }
                        }
                    }
                }
                function trackSymbol(symbol, enclosingDeclaration, meaning) {
                    handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
                }
                function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    write(": ");
                    if (type) {
                        emitType(type);
                    }
                    else {
                        resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2, writer);
                    }
                }
                function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    write(": ");
                    if (signature.type) {
                        emitType(signature.type);
                    }
                    else {
                        resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2, writer);
                    }
                }
                function emitLines(nodes) {
                    for (var i = 0, n = nodes.length; i < n; i++) {
                        emit(nodes[i]);
                    }
                }
                function emitSeparatedList(nodes, separator, eachNodeEmitFn) {
                    var currentWriterPos = writer.getTextPos();
                    for (var i = 0, n = nodes.length; i < n; i++) {
                        if (currentWriterPos !== writer.getTextPos()) {
                            write(separator);
                        }
                        currentWriterPos = writer.getTextPos();
                        eachNodeEmitFn(nodes[i]);
                    }
                }
                function emitCommaList(nodes, eachNodeEmitFn) {
                    emitSeparatedList(nodes, ", ", eachNodeEmitFn);
                }
                function writeJsDocComments(declaration) {
                    if (declaration) {
                        var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile);
                        emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
                        emitComments(currentSourceFile, writer, jsDocComments, true, newLine, writeCommentRange);
                    }
                }
                function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    emitType(type);
                }
                function emitType(type) {
                    switch (type.kind) {
                        case 111:
                        case 120:
                        case 118:
                        case 112:
                        case 121:
                        case 98:
                        case 8:
                            return writeTextOfNode(currentSourceFile, type);
                        case 139:
                            return emitTypeReference(type);
                        case 142:
                            return emitTypeQuery(type);
                        case 144:
                            return emitArrayType(type);
                        case 145:
                            return emitTupleType(type);
                        case 146:
                            return emitUnionType(type);
                        case 147:
                            return emitParenType(type);
                        case 140:
                        case 141:
                            return emitSignatureDeclarationWithJsDocComments(type);
                        case 143:
                            return emitTypeLiteral(type);
                        case 64:
                            return emitEntityName(type);
                        case 125:
                            return emitEntityName(type);
                        default:
                            ts.Debug.fail("Unknown type annotation: " + type.kind);
                    }
                    function emitEntityName(entityName) {
                        var visibilityResult = resolver.isEntityNameVisible(entityName, entityName.parent.kind === 203 ? entityName.parent : enclosingDeclaration);
                        handleSymbolAccessibilityError(visibilityResult);
                        writeEntityName(entityName);
                        function writeEntityName(entityName) {
                            if (entityName.kind === 64) {
                                writeTextOfNode(currentSourceFile, entityName);
                            }
                            else {
                                var qualifiedName = entityName;
                                writeEntityName(qualifiedName.left);
                                write(".");
                                writeTextOfNode(currentSourceFile, qualifiedName.right);
                            }
                        }
                    }
                    function emitTypeReference(type) {
                        emitEntityName(type.typeName);
                        if (type.typeArguments) {
                            write("<");
                            emitCommaList(type.typeArguments, emitType);
                            write(">");
                        }
                    }
                    function emitTypeQuery(type) {
                        write("typeof ");
                        emitEntityName(type.exprName);
                    }
                    function emitArrayType(type) {
                        emitType(type.elementType);
                        write("[]");
                    }
                    function emitTupleType(type) {
                        write("[");
                        emitCommaList(type.elementTypes, emitType);
                        write("]");
                    }
                    function emitUnionType(type) {
                        emitSeparatedList(type.types, " | ", emitType);
                    }
                    function emitParenType(type) {
                        write("(");
                        emitType(type.type);
                        write(")");
                    }
                    function emitTypeLiteral(type) {
                        write("{");
                        if (type.members.length) {
                            writeLine();
                            increaseIndent();
                            emitLines(type.members);
                            decreaseIndent();
                        }
                        write("}");
                    }
                }
                function emitSourceFile(node) {
                    currentSourceFile = node;
                    enclosingDeclaration = node;
                    emitLines(node.statements);
                }
                function emitExportAssignment(node) {
                    write(node.isExportEquals ? "export = " : "export default ");
                    writeTextOfNode(currentSourceFile, node.expression);
                    write(";");
                    writeLine();
                }
                function emitModuleElementDeclarationFlags(node) {
                    if (node.parent === currentSourceFile) {
                        if (node.flags & 1) {
                            write("export ");
                        }
                        if (node.kind !== 197) {
                            write("declare ");
                        }
                    }
                }
                function emitClassMemberDeclarationFlags(node) {
                    if (node.flags & 32) {
                        write("private ");
                    }
                    else if (node.flags & 64) {
                        write("protected ");
                    }
                    if (node.flags & 128) {
                        write("static ");
                    }
                }
                function emitImportEqualsDeclaration(node) {
                    var nodeEmitInfo = {
                        declaration: node,
                        outputPos: writer.getTextPos(),
                        indent: writer.getIndent(),
                        hasWritten: resolver.isDeclarationVisible(node)
                    };
                    aliasDeclarationEmitInfo.push(nodeEmitInfo);
                    if (nodeEmitInfo.hasWritten) {
                        writeImportEqualsDeclaration(node);
                    }
                }
                function writeImportEqualsDeclaration(node) {
                    emitJsDocComments(node);
                    if (node.flags & 1) {
                        write("export ");
                    }
                    write("import ");
                    writeTextOfNode(currentSourceFile, node.name);
                    write(" = ");
                    if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError);
                        write(";");
                    }
                    else {
                        write("require(");
                        writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node));
                        write(");");
                    }
                    writer.writeLine();
                    function getImportEntityNameVisibilityError(symbolAccesibilityResult) {
                        return {
                            diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1,
                            errorNode: node,
                            typeName: node.name
                        };
                    }
                }
                function emitModuleDeclaration(node) {
                    if (resolver.isDeclarationVisible(node)) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        write("module ");
                        writeTextOfNode(currentSourceFile, node.name);
                        while (node.body.kind !== 201) {
                            node = node.body;
                            write(".");
                            writeTextOfNode(currentSourceFile, node.name);
                        }
                        var prevEnclosingDeclaration = enclosingDeclaration;
                        enclosingDeclaration = node;
                        write(" {");
                        writeLine();
                        increaseIndent();
                        emitLines(node.body.statements);
                        decreaseIndent();
                        write("}");
                        writeLine();
                        enclosingDeclaration = prevEnclosingDeclaration;
                    }
                }
                function emitTypeAliasDeclaration(node) {
                    if (resolver.isDeclarationVisible(node)) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        write("type ");
                        writeTextOfNode(currentSourceFile, node.name);
                        write(" = ");
                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
                        write(";");
                        writeLine();
                    }
                    function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult) {
                        return {
                            diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
                            errorNode: node.type,
                            typeName: node.name
                        };
                    }
                }
                function emitEnumDeclaration(node) {
                    if (resolver.isDeclarationVisible(node)) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        if (ts.isConst(node)) {
                            write("const ");
                        }
                        write("enum ");
                        writeTextOfNode(currentSourceFile, node.name);
                        write(" {");
                        writeLine();
                        increaseIndent();
                        emitLines(node.members);
                        decreaseIndent();
                        write("}");
                        writeLine();
                    }
                }
                function emitEnumMemberDeclaration(node) {
                    emitJsDocComments(node);
                    writeTextOfNode(currentSourceFile, node.name);
                    var enumMemberValue = resolver.getConstantValue(node);
                    if (enumMemberValue !== undefined) {
                        write(" = ");
                        write(enumMemberValue.toString());
                    }
                    write(",");
                    writeLine();
                }
                function isPrivateMethodTypeParameter(node) {
                    return node.parent.kind === 132 && (node.parent.flags & 32);
                }
                function emitTypeParameters(typeParameters) {
                    function emitTypeParameter(node) {
                        increaseIndent();
                        emitJsDocComments(node);
                        decreaseIndent();
                        writeTextOfNode(currentSourceFile, node.name);
                        if (node.constraint && !isPrivateMethodTypeParameter(node)) {
                            write(" extends ");
                            if (node.parent.kind === 140 || node.parent.kind === 141 || (node.parent.parent && node.parent.parent.kind === 143)) {
                                ts.Debug.assert(node.parent.kind === 132 || node.parent.kind === 131 || node.parent.kind === 140 || node.parent.kind === 141 || node.parent.kind === 136 || node.parent.kind === 137);
                                emitType(node.constraint);
                            }
                            else {
                                emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
                            }
                        }
                        function getTypeParameterConstraintVisibilityError(symbolAccesibilityResult) {
                            var diagnosticMessage;
                            switch (node.parent.kind) {
                                case 196:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1;
                                    break;
                                case 197:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 137:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 136:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 132:
                                case 131:
                                    if (node.parent.flags & 128) {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
                                    }
                                    else if (node.parent.parent.kind === 196) {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
                                    }
                                    else {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
                                    }
                                    break;
                                case 195:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1;
                                    break;
                                default:
                                    ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: node,
                                typeName: node.name
                            };
                        }
                    }
                    if (typeParameters) {
                        write("<");
                        emitCommaList(typeParameters, emitTypeParameter);
                        write(">");
                    }
                }
                function emitHeritageClause(typeReferences, isImplementsList) {
                    if (typeReferences) {
                        write(isImplementsList ? " implements " : " extends ");
                        emitCommaList(typeReferences, emitTypeOfTypeReference);
                    }
                    function emitTypeOfTypeReference(node) {
                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
                        function getHeritageClauseVisibilityError(symbolAccesibilityResult) {
                            var diagnosticMessage;
                            if (node.parent.parent.kind === 196) {
                                diagnosticMessage = isImplementsList ? ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
                            }
                            else {
                                diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: node,
                                typeName: node.parent.parent.name
                            };
                        }
                    }
                }
                function emitClassDeclaration(node) {
                    function emitParameterProperties(constructorDeclaration) {
                        if (constructorDeclaration) {
                            ts.forEach(constructorDeclaration.parameters, function (param) {
                                if (param.flags & 112) {
                                    emitPropertyDeclaration(param);
                                }
                            });
                        }
                    }
                    if (resolver.isDeclarationVisible(node)) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        write("class ");
                        writeTextOfNode(currentSourceFile, node.name);
                        var prevEnclosingDeclaration = enclosingDeclaration;
                        enclosingDeclaration = node;
                        emitTypeParameters(node.typeParameters);
                        var baseTypeNode = ts.getClassBaseTypeNode(node);
                        if (baseTypeNode) {
                            emitHeritageClause([
                                baseTypeNode
                            ], false);
                        }
                        emitHeritageClause(ts.getClassImplementedTypeNodes(node), true);
                        write(" {");
                        writeLine();
                        increaseIndent();
                        emitParameterProperties(getFirstConstructorWithBody(node));
                        emitLines(node.members);
                        decreaseIndent();
                        write("}");
                        writeLine();
                        enclosingDeclaration = prevEnclosingDeclaration;
                    }
                }
                function emitInterfaceDeclaration(node) {
                    if (resolver.isDeclarationVisible(node)) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        write("interface ");
                        writeTextOfNode(currentSourceFile, node.name);
                        var prevEnclosingDeclaration = enclosingDeclaration;
                        enclosingDeclaration = node;
                        emitTypeParameters(node.typeParameters);
                        emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), false);
                        write(" {");
                        writeLine();
                        increaseIndent();
                        emitLines(node.members);
                        decreaseIndent();
                        write("}");
                        writeLine();
                        enclosingDeclaration = prevEnclosingDeclaration;
                    }
                }
                function emitPropertyDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    emitJsDocComments(node);
                    emitClassMemberDeclarationFlags(node);
                    emitVariableDeclaration(node);
                    write(";");
                    writeLine();
                }
                function emitVariableDeclaration(node) {
                    if (node.kind !== 193 || resolver.isDeclarationVisible(node)) {
                        writeTextOfNode(currentSourceFile, node.name);
                        if ((node.kind === 130 || node.kind === 129) && ts.hasQuestionToken(node)) {
                            write("?");
                        }
                        if ((node.kind === 130 || node.kind === 129) && node.parent.kind === 143) {
                            emitTypeOfVariableDeclarationFromTypeLiteral(node);
                        }
                        else if (!(node.flags & 32)) {
                            writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
                        }
                    }
                    function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        if (node.kind === 193) {
                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
                        }
                        else if (node.kind === 130 || node.kind === 129) {
                            if (node.flags & 128) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1;
                            }
                            else if (node.parent.kind === 196) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1;
                            }
                            else {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1;
                            }
                        }
                        return diagnosticMessage !== undefined ? {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node,
                            typeName: node.name
                        } : undefined;
                    }
                }
                function emitTypeOfVariableDeclarationFromTypeLiteral(node) {
                    if (node.type) {
                        write(": ");
                        emitType(node.type);
                    }
                }
                function emitVariableStatement(node) {
                    var hasDeclarationWithEmit = ts.forEach(node.declarationList.declarations, function (varDeclaration) {
                        return resolver.isDeclarationVisible(varDeclaration);
                    });
                    if (hasDeclarationWithEmit) {
                        emitJsDocComments(node);
                        emitModuleElementDeclarationFlags(node);
                        if (ts.isLet(node.declarationList)) {
                            write("let ");
                        }
                        else if (ts.isConst(node.declarationList)) {
                            write("const ");
                        }
                        else {
                            write("var ");
                        }
                        emitCommaList(node.declarationList.declarations, emitVariableDeclaration);
                        write(";");
                        writeLine();
                    }
                }
                function emitAccessorDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    var accessors = getAllAccessorDeclarations(node.parent.members, node);
                    if (node === accessors.firstAccessor) {
                        emitJsDocComments(accessors.getAccessor);
                        emitJsDocComments(accessors.setAccessor);
                        emitClassMemberDeclarationFlags(node);
                        writeTextOfNode(currentSourceFile, node.name);
                        if (!(node.flags & 32)) {
                            var accessorWithTypeAnnotation = node;
                            var type = getTypeAnnotationFromAccessor(node);
                            if (!type) {
                                var anotherAccessor = node.kind === 134 ? accessors.setAccessor : accessors.getAccessor;
                                type = getTypeAnnotationFromAccessor(anotherAccessor);
                                if (type) {
                                    accessorWithTypeAnnotation = anotherAccessor;
                                }
                            }
                            writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError);
                        }
                        write(";");
                        writeLine();
                    }
                    function getTypeAnnotationFromAccessor(accessor) {
                        if (accessor) {
                            return accessor.kind === 134 ? accessor.type : accessor.parameters.length > 0 ? accessor.parameters[0].type : undefined;
                        }
                    }
                    function getAccessorDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        if (accessorWithTypeAnnotation.kind === 135) {
                            if (accessorWithTypeAnnotation.parent.flags & 128) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
                            }
                            else {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: accessorWithTypeAnnotation.parameters[0],
                                typeName: accessorWithTypeAnnotation.name
                            };
                        }
                        else {
                            if (accessorWithTypeAnnotation.flags & 128) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0;
                            }
                            else {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: accessorWithTypeAnnotation.name,
                                typeName: undefined
                            };
                        }
                    }
                }
                function emitFunctionDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    if ((node.kind !== 195 || resolver.isDeclarationVisible(node)) && !resolver.isImplementationOfOverload(node)) {
                        emitJsDocComments(node);
                        if (node.kind === 195) {
                            emitModuleElementDeclarationFlags(node);
                        }
                        else if (node.kind === 132) {
                            emitClassMemberDeclarationFlags(node);
                        }
                        if (node.kind === 195) {
                            write("function ");
                            writeTextOfNode(currentSourceFile, node.name);
                        }
                        else if (node.kind === 133) {
                            write("constructor");
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node.name);
                            if (ts.hasQuestionToken(node)) {
                                write("?");
                            }
                        }
                        emitSignatureDeclaration(node);
                    }
                }
                function emitSignatureDeclarationWithJsDocComments(node) {
                    emitJsDocComments(node);
                    emitSignatureDeclaration(node);
                }
                function emitSignatureDeclaration(node) {
                    if (node.kind === 137 || node.kind === 141) {
                        write("new ");
                    }
                    emitTypeParameters(node.typeParameters);
                    if (node.kind === 138) {
                        write("[");
                    }
                    else {
                        write("(");
                    }
                    var prevEnclosingDeclaration = enclosingDeclaration;
                    enclosingDeclaration = node;
                    emitCommaList(node.parameters, emitParameterDeclaration);
                    if (node.kind === 138) {
                        write("]");
                    }
                    else {
                        write(")");
                    }
                    var isFunctionTypeOrConstructorType = node.kind === 140 || node.kind === 141;
                    if (isFunctionTypeOrConstructorType || node.parent.kind === 143) {
                        if (node.type) {
                            write(isFunctionTypeOrConstructorType ? " => " : ": ");
                            emitType(node.type);
                        }
                    }
                    else if (node.kind !== 133 && !(node.flags & 32)) {
                        writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
                    }
                    enclosingDeclaration = prevEnclosingDeclaration;
                    if (!isFunctionTypeOrConstructorType) {
                        write(";");
                        writeLine();
                    }
                    function getReturnTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        switch (node.kind) {
                            case 137:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 136:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 138:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 132:
                            case 131:
                                if (node.flags & 128) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0;
                                }
                                else if (node.parent.kind === 196) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0;
                                }
                                else {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0;
                                }
                                break;
                            case 195:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0;
                                break;
                            default:
                                ts.Debug.fail("This is unknown kind for signature: " + node.kind);
                        }
                        return {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node.name || node
                        };
                    }
                }
                function emitParameterDeclaration(node) {
                    increaseIndent();
                    emitJsDocComments(node);
                    if (node.dotDotDotToken) {
                        write("...");
                    }
                    if (ts.isBindingPattern(node.name)) {
                        write("_" + ts.indexOf(node.parent.parameters, node));
                    }
                    else {
                        writeTextOfNode(currentSourceFile, node.name);
                    }
                    if (node.initializer || ts.hasQuestionToken(node)) {
                        write("?");
                    }
                    decreaseIndent();
                    if (node.parent.kind === 140 || node.parent.kind === 141 || node.parent.parent.kind === 143) {
                        emitTypeOfVariableDeclarationFromTypeLiteral(node);
                    }
                    else if (!(node.parent.flags & 32)) {
                        writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
                    }
                    function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        switch (node.parent.kind) {
                            case 133:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1;
                                break;
                            case 137:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
                                break;
                            case 136:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
                                break;
                            case 132:
                            case 131:
                                if (node.parent.flags & 128) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
                                }
                                else if (node.parent.parent.kind === 196) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
                                }
                                else {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
                                }
                                break;
                            case 195:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === 2 ? ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1;
                                break;
                            default:
                                ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind);
                        }
                        return {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node,
                            typeName: node.name
                        };
                    }
                }
                function emitNode(node) {
                    switch (node.kind) {
                        case 133:
                        case 195:
                        case 132:
                        case 131:
                            return emitFunctionDeclaration(node);
                        case 137:
                        case 136:
                        case 138:
                            return emitSignatureDeclarationWithJsDocComments(node);
                        case 134:
                        case 135:
                            return emitAccessorDeclaration(node);
                        case 175:
                            return emitVariableStatement(node);
                        case 130:
                        case 129:
                            return emitPropertyDeclaration(node);
                        case 197:
                            return emitInterfaceDeclaration(node);
                        case 196:
                            return emitClassDeclaration(node);
                        case 198:
                            return emitTypeAliasDeclaration(node);
                        case 220:
                            return emitEnumMemberDeclaration(node);
                        case 199:
                            return emitEnumDeclaration(node);
                        case 200:
                            return emitModuleDeclaration(node);
                        case 203:
                            return emitImportEqualsDeclaration(node);
                        case 209:
                            return emitExportAssignment(node);
                        case 221:
                            return emitSourceFile(node);
                    }
                }
                function writeReferencePath(referencedFile) {
                    var declFileName = referencedFile.flags & 2048 ? referencedFile.fileName : shouldEmitToOwnFile(referencedFile, compilerOptions) ? getOwnEmitOutputFilePath(referencedFile, host, ".d.ts") : ts.removeFileExtension(compilerOptions.out) + ".d.ts";
                    declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(jsFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, false);
                    referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
                }
            }
            function getDeclarationDiagnostics(host, resolver, targetSourceFile) {
                var diagnostics = [];
                var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
                emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
                return diagnostics;
            }
            ts.getDeclarationDiagnostics = getDeclarationDiagnostics;
            function emitFiles(resolver, host, targetSourceFile) {
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0;
                var sourceMapDataList = compilerOptions.sourceMap ? [] : undefined;
                var diagnostics = [];
                var newLine = host.getNewLine();
                if (targetSourceFile === undefined) {
                    ts.forEach(host.getSourceFiles(), function (sourceFile) {
                        if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
                            var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, ".js");
                            emitFile(jsFilePath, sourceFile);
                        }
                    });
                    if (compilerOptions.out) {
                        emitFile(compilerOptions.out);
                    }
                }
                else {
                    if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
                        var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
                        emitFile(jsFilePath, targetSourceFile);
                    }
                    else if (!ts.isDeclarationFile(targetSourceFile) && compilerOptions.out) {
                        emitFile(compilerOptions.out);
                    }
                }
                diagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics);
                return {
                    emitSkipped: false,
                    diagnostics: diagnostics,
                    sourceMaps: sourceMapDataList
                };
                function emitJavaScript(jsFilePath, root) {
                    var writer = createTextWriter(newLine);
                    var write = writer.write;
                    var writeTextOfNode = writer.writeTextOfNode;
                    var writeLine = writer.writeLine;
                    var increaseIndent = writer.increaseIndent;
                    var decreaseIndent = writer.decreaseIndent;
                    var preserveNewLines = compilerOptions.preserveNewLines || false;
                    var currentSourceFile;
                    var lastFrame;
                    var currentScopeNames;
                    var generatedBlockScopeNames;
                    var extendsEmitted = false;
                    var tempCount = 0;
                    var tempVariables;
                    var tempParameters;
                    var externalImports;
                    var exportSpecifiers;
                    var exportDefault;
                    var writeEmittedFiles = writeJavaScriptFile;
                    var emitLeadingComments = compilerOptions.removeComments ? function (node) {
                    } : emitLeadingDeclarationComments;
                    var emitTrailingComments = compilerOptions.removeComments ? function (node) {
                    } : emitTrailingDeclarationComments;
                    var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) {
                    } : emitLeadingCommentsOfLocalPosition;
                    var detachedCommentsInfo;
                    var emitDetachedComments = compilerOptions.removeComments ? function (node) {
                    } : emitDetachedCommentsAtPosition;
                    var writeComment = writeCommentRange;
                    var emitNodeWithoutSourceMap = compilerOptions.removeComments ? emitNodeWithoutSourceMapWithoutComments : emitNodeWithoutSourceMapWithComments;
                    var emit = emitNodeWithoutSourceMap;
                    var emitWithoutComments = emitNodeWithoutSourceMapWithoutComments;
                    var emitStart = function (node) {
                    };
                    var emitEnd = function (node) {
                    };
                    var emitToken = emitTokenText;
                    var scopeEmitStart = function (scopeDeclaration, scopeName) {
                    };
                    var scopeEmitEnd = function () {
                    };
                    var sourceMapData;
                    if (compilerOptions.sourceMap) {
                        initializeEmitterWithSourceMaps();
                    }
                    if (root) {
                        emitSourceFile(root);
                    }
                    else {
                        ts.forEach(host.getSourceFiles(), function (sourceFile) {
                            if (!isExternalModuleOrDeclarationFile(sourceFile)) {
                                emitSourceFile(sourceFile);
                            }
                        });
                    }
                    writeLine();
                    writeEmittedFiles(writer.getText(), compilerOptions.emitBOM);
                    return;
                    function emitSourceFile(sourceFile) {
                        currentSourceFile = sourceFile;
                        emit(sourceFile);
                    }
                    function enterNameScope() {
                        var names = currentScopeNames;
                        currentScopeNames = undefined;
                        if (names) {
                            lastFrame = {
                                names: names,
                                previous: lastFrame
                            };
                            return true;
                        }
                        return false;
                    }
                    function exitNameScope(popFrame) {
                        if (popFrame) {
                            currentScopeNames = lastFrame.names;
                            lastFrame = lastFrame.previous;
                        }
                        else {
                            currentScopeNames = undefined;
                        }
                    }
                    function generateUniqueNameForLocation(location, baseName) {
                        var name;
                        if (!isExistingName(location, baseName)) {
                            name = baseName;
                        }
                        else {
                            name = ts.generateUniqueName(baseName, function (n) {
                                return isExistingName(location, n);
                            });
                        }
                        return recordNameInCurrentScope(name);
                    }
                    function recordNameInCurrentScope(name) {
                        if (!currentScopeNames) {
                            currentScopeNames = {};
                        }
                        return currentScopeNames[name] = name;
                    }
                    function isExistingName(location, name) {
                        if (!resolver.isUnknownIdentifier(location, name)) {
                            return true;
                        }
                        if (currentScopeNames && ts.hasProperty(currentScopeNames, name)) {
                            return true;
                        }
                        var frame = lastFrame;
                        while (frame) {
                            if (ts.hasProperty(frame.names, name)) {
                                return true;
                            }
                            frame = frame.previous;
                        }
                        return false;
                    }
                    function initializeEmitterWithSourceMaps() {
                        var sourceMapDir;
                        var sourceMapSourceIndex = -1;
                        var sourceMapNameIndexMap = {};
                        var sourceMapNameIndices = [];
                        function getSourceMapNameIndex() {
                            return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
                        }
                        var lastRecordedSourceMapSpan;
                        var lastEncodedSourceMapSpan = {
                            emittedLine: 1,
                            emittedColumn: 1,
                            sourceLine: 1,
                            sourceColumn: 1,
                            sourceIndex: 0
                        };
                        var lastEncodedNameIndex = 0;
                        function encodeLastRecordedSourceMapSpan() {
                            if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
                                return;
                            }
                            var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
                            if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
                                if (sourceMapData.sourceMapMappings) {
                                    sourceMapData.sourceMapMappings += ",";
                                }
                            }
                            else {
                                for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
                                    sourceMapData.sourceMapMappings += ";";
                                }
                                prevEncodedEmittedColumn = 1;
                            }
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
                            if (lastRecordedSourceMapSpan.nameIndex >= 0) {
                                sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
                                lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
                            }
                            lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
                            sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
                            function base64VLQFormatEncode(inValue) {
                                function base64FormatEncode(inValue) {
                                    if (inValue < 64) {
                                        return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
                                    }
                                    throw TypeError(inValue + ": not a 64 based value");
                                }
                                if (inValue < 0) {
                                    inValue = ((-inValue) << 1) + 1;
                                }
                                else {
                                    inValue = inValue << 1;
                                }
                                var encodedStr = "";
                                do {
                                    var currentDigit = inValue & 31;
                                    inValue = inValue >> 5;
                                    if (inValue > 0) {
                                        currentDigit = currentDigit | 32;
                                    }
                                    encodedStr = encodedStr + base64FormatEncode(currentDigit);
                                } while (inValue > 0);
                                return encodedStr;
                            }
                        }
                        function recordSourceMapSpan(pos) {
                            var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos);
                            sourceLinePos.line++;
                            sourceLinePos.character++;
                            var emittedLine = writer.getLine();
                            var emittedColumn = writer.getColumn();
                            if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan.emittedLine != emittedLine || lastRecordedSourceMapSpan.emittedColumn != emittedColumn || (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
                                encodeLastRecordedSourceMapSpan();
                                lastRecordedSourceMapSpan = {
                                    emittedLine: emittedLine,
                                    emittedColumn: emittedColumn,
                                    sourceLine: sourceLinePos.line,
                                    sourceColumn: sourceLinePos.character,
                                    nameIndex: getSourceMapNameIndex(),
                                    sourceIndex: sourceMapSourceIndex
                                };
                            }
                            else {
                                lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
                                lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
                                lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
                            }
                        }
                        function recordEmitNodeStartSpan(node) {
                            recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos));
                        }
                        function recordEmitNodeEndSpan(node) {
                            recordSourceMapSpan(node.end);
                        }
                        function writeTextWithSpanRecord(tokenKind, startPos, emitFn) {
                            var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
                            recordSourceMapSpan(tokenStartPos);
                            var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
                            recordSourceMapSpan(tokenEndPos);
                            return tokenEndPos;
                        }
                        function recordNewSourceFileStart(node) {
                            var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
                            sourceMapData.sourceMapSources.push(ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, node.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, true));
                            sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
                            sourceMapData.inputSourceFileNames.push(node.fileName);
                        }
                        function recordScopeNameOfNode(node, scopeName) {
                            function recordScopeNameIndex(scopeNameIndex) {
                                sourceMapNameIndices.push(scopeNameIndex);
                            }
                            function recordScopeNameStart(scopeName) {
                                var scopeNameIndex = -1;
                                if (scopeName) {
                                    var parentIndex = getSourceMapNameIndex();
                                    if (parentIndex !== -1) {
                                        var name = node.name;
                                        if (!name || name.kind !== 126) {
                                            scopeName = "." + scopeName;
                                        }
                                        scopeName = sourceMapData.sourceMapNames[parentIndex] + scopeName;
                                    }
                                    scopeNameIndex = ts.getProperty(sourceMapNameIndexMap, scopeName);
                                    if (scopeNameIndex === undefined) {
                                        scopeNameIndex = sourceMapData.sourceMapNames.length;
                                        sourceMapData.sourceMapNames.push(scopeName);
                                        sourceMapNameIndexMap[scopeName] = scopeNameIndex;
                                    }
                                }
                                recordScopeNameIndex(scopeNameIndex);
                            }
                            if (scopeName) {
                                recordScopeNameStart(scopeName);
                            }
                            else if (node.kind === 195 || node.kind === 160 || node.kind === 132 || node.kind === 131 || node.kind === 134 || node.kind === 135 || node.kind === 200 || node.kind === 196 || node.kind === 199) {
                                if (node.name) {
                                    var name = node.name;
                                    scopeName = name.kind === 126 ? ts.getTextOfNode(name) : node.name.text;
                                }
                                recordScopeNameStart(scopeName);
                            }
                            else {
                                recordScopeNameIndex(getSourceMapNameIndex());
                            }
                        }
                        function recordScopeNameEnd() {
                            sourceMapNameIndices.pop();
                        }
                        ;
                        function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) {
                            recordSourceMapSpan(comment.pos);
                            writeCommentRange(currentSourceFile, writer, comment, newLine);
                            recordSourceMapSpan(comment.end);
                        }
                        function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings) {
                            if (typeof JSON !== "undefined") {
                                return JSON.stringify({
                                    version: version,
                                    file: file,
                                    sourceRoot: sourceRoot,
                                    sources: sources,
                                    names: names,
                                    mappings: mappings
                                });
                            }
                            return "{\"version\":" + version + ",\"file\":\"" + ts.escapeString(file) + "\",\"sourceRoot\":\"" + ts.escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + ts.escapeString(mappings) + "\"}";
                            function serializeStringArray(list) {
                                var output = "";
                                for (var i = 0, n = list.length; i < n; i++) {
                                    if (i) {
                                        output += ",";
                                    }
                                    output += "\"" + ts.escapeString(list[i]) + "\"";
                                }
                                return output;
                            }
                        }
                        function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) {
                            encodeLastRecordedSourceMapSpan();
                            writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings), false);
                            sourceMapDataList.push(sourceMapData);
                            writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL, writeByteOrderMark);
                        }
                        var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath));
                        sourceMapData = {
                            sourceMapFilePath: jsFilePath + ".map",
                            jsSourceMappingURL: sourceMapJsFile + ".map",
                            sourceMapFile: sourceMapJsFile,
                            sourceMapSourceRoot: compilerOptions.sourceRoot || "",
                            sourceMapSources: [],
                            inputSourceFileNames: [],
                            sourceMapNames: [],
                            sourceMapMappings: "",
                            sourceMapDecodedMappings: []
                        };
                        sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
                        if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47) {
                            sourceMapData.sourceMapSourceRoot += ts.directorySeparator;
                        }
                        if (compilerOptions.mapRoot) {
                            sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot);
                            if (root) {
                                sourceMapDir = ts.getDirectoryPath(getSourceFilePathInNewDir(root, host, sourceMapDir));
                            }
                            if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) {
                                sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
                                sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(jsFilePath)), ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), host.getCurrentDirectory(), host.getCanonicalFileName, true);
                            }
                            else {
                                sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
                            }
                        }
                        else {
                            sourceMapDir = ts.getDirectoryPath(ts.normalizePath(jsFilePath));
                        }
                        function emitNodeWithSourceMap(node) {
                            if (node) {
                                if (ts.nodeIsSynthesized(node)) {
                                    return emitNodeWithoutSourceMap(node);
                                }
                                if (node.kind != 221) {
                                    recordEmitNodeStartSpan(node);
                                    emitNodeWithoutSourceMap(node);
                                    recordEmitNodeEndSpan(node);
                                }
                                else {
                                    recordNewSourceFileStart(node);
                                    emitNodeWithoutSourceMap(node);
                                }
                            }
                        }
                        function emitNodeWithSourceMapWithoutComments(node) {
                            if (node) {
                                recordEmitNodeStartSpan(node);
                                emitNodeWithoutSourceMapWithoutComments(node);
                                recordEmitNodeEndSpan(node);
                            }
                        }
                        writeEmittedFiles = writeJavaScriptAndSourceMapFile;
                        emit = emitNodeWithSourceMap;
                        emitWithoutComments = emitNodeWithSourceMapWithoutComments;
                        emitStart = recordEmitNodeStartSpan;
                        emitEnd = recordEmitNodeEndSpan;
                        emitToken = writeTextWithSpanRecord;
                        scopeEmitStart = recordScopeNameOfNode;
                        scopeEmitEnd = recordScopeNameEnd;
                        writeComment = writeCommentRangeWithMap;
                    }
                    function writeJavaScriptFile(emitOutput, writeByteOrderMark) {
                        writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
                    }
                    function createTempVariable(location, forLoopVariable) {
                        var name = forLoopVariable ? "_i" : undefined;
                        while (true) {
                            if (name && !isExistingName(location, name)) {
                                break;
                            }
                            name = "_" + (tempCount < 25 ? String.fromCharCode(tempCount + (tempCount < 8 ? 0 : 1) + 97) : tempCount - 25);
                            tempCount++;
                        }
                        recordNameInCurrentScope(name);
                        var result = ts.createSynthesizedNode(64);
                        result.text = name;
                        return result;
                    }
                    function recordTempDeclaration(name) {
                        if (!tempVariables) {
                            tempVariables = [];
                        }
                        tempVariables.push(name);
                    }
                    function createAndRecordTempVariable(location) {
                        var temp = createTempVariable(location, false);
                        recordTempDeclaration(temp);
                        return temp;
                    }
                    function emitTempDeclarations(newLine) {
                        if (tempVariables) {
                            if (newLine) {
                                writeLine();
                            }
                            else {
                                write(" ");
                            }
                            write("var ");
                            emitCommaList(tempVariables);
                            write(";");
                        }
                    }
                    function emitTokenText(tokenKind, startPos, emitFn) {
                        var tokenString = ts.tokenToString(tokenKind);
                        if (emitFn) {
                            emitFn();
                        }
                        else {
                            write(tokenString);
                        }
                        return startPos + tokenString.length;
                    }
                    function emitOptional(prefix, node) {
                        if (node) {
                            write(prefix);
                            emit(node);
                        }
                    }
                    function emitParenthesizedIf(node, parenthesized) {
                        if (parenthesized) {
                            write("(");
                        }
                        emit(node);
                        if (parenthesized) {
                            write(")");
                        }
                    }
                    function emitTrailingCommaIfPresent(nodeList) {
                        if (nodeList.hasTrailingComma) {
                            write(",");
                        }
                    }
                    function emitLinePreservingList(parent, nodes, allowTrailingComma, spacesBetweenBraces) {
                        ts.Debug.assert(nodes.length > 0);
                        increaseIndent();
                        if (preserveNewLines && nodeStartPositionsAreOnSameLine(parent, nodes[0])) {
                            if (spacesBetweenBraces) {
                                write(" ");
                            }
                        }
                        else {
                            writeLine();
                        }
                        for (var i = 0, n = nodes.length; i < n; i++) {
                            if (i) {
                                if (preserveNewLines && nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) {
                                    write(", ");
                                }
                                else {
                                    write(",");
                                    writeLine();
                                }
                            }
                            emit(nodes[i]);
                        }
                        if (nodes.hasTrailingComma && allowTrailingComma) {
                            write(",");
                        }
                        decreaseIndent();
                        if (preserveNewLines && nodeEndPositionsAreOnSameLine(parent, ts.lastOrUndefined(nodes))) {
                            if (spacesBetweenBraces) {
                                write(" ");
                            }
                        }
                        else {
                            writeLine();
                        }
                    }
                    function emitList(nodes, start, count, multiLine, trailingComma) {
                        for (var i = 0; i < count; i++) {
                            if (multiLine) {
                                if (i) {
                                    write(",");
                                }
                                writeLine();
                            }
                            else {
                                if (i) {
                                    write(", ");
                                }
                            }
                            emit(nodes[start + i]);
                        }
                        if (trailingComma) {
                            write(",");
                        }
                        if (multiLine) {
                            writeLine();
                        }
                    }
                    function emitCommaList(nodes) {
                        if (nodes) {
                            emitList(nodes, 0, nodes.length, false, false);
                        }
                    }
                    function emitLines(nodes) {
                        emitLinesStartingAt(nodes, 0);
                    }
                    function emitLinesStartingAt(nodes, startIndex) {
                        for (var i = startIndex; i < nodes.length; i++) {
                            writeLine();
                            emit(nodes[i]);
                        }
                    }
                    function isBinaryOrOctalIntegerLiteral(node, text) {
                        if (node.kind === 7 && text.length > 1) {
                            switch (text.charCodeAt(1)) {
                                case 98:
                                case 66:
                                case 111:
                                case 79:
                                    return true;
                            }
                        }
                        return false;
                    }
                    function emitLiteral(node) {
                        var text = getLiteralText(node);
                        if (compilerOptions.sourceMap && (node.kind === 8 || ts.isTemplateLiteralKind(node.kind))) {
                            writer.writeLiteral(text);
                        }
                        else if (languageVersion < 2 && isBinaryOrOctalIntegerLiteral(node, text)) {
                            write(node.text);
                        }
                        else {
                            write(text);
                        }
                    }
                    function getLiteralText(node) {
                        if (languageVersion < 2 && (ts.isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
                            return getQuotedEscapedLiteralText('"', node.text, '"');
                        }
                        if (node.parent) {
                            return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
                        }
                        switch (node.kind) {
                            case 8:
                                return getQuotedEscapedLiteralText('"', node.text, '"');
                            case 10:
                                return getQuotedEscapedLiteralText('`', node.text, '`');
                            case 11:
                                return getQuotedEscapedLiteralText('`', node.text, '${');
                            case 12:
                                return getQuotedEscapedLiteralText('}', node.text, '${');
                            case 13:
                                return getQuotedEscapedLiteralText('}', node.text, '`');
                            case 7:
                                return node.text;
                        }
                        ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for.");
                    }
                    function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) {
                        return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote;
                    }
                    function emitDownlevelRawTemplateLiteral(node) {
                        var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
                        var isLast = node.kind === 10 || node.kind === 13;
                        text = text.substring(1, text.length - (isLast ? 1 : 2));
                        text = text.replace(/\r\n?/g, "\n");
                        text = ts.escapeString(text);
                        write('"' + text + '"');
                    }
                    function emitDownlevelTaggedTemplateArray(node, literalEmitter) {
                        write("[");
                        if (node.template.kind === 10) {
                            literalEmitter(node.template);
                        }
                        else {
                            literalEmitter(node.template.head);
                            ts.forEach(node.template.templateSpans, function (child) {
                                write(", ");
                                literalEmitter(child.literal);
                            });
                        }
                        write("]");
                    }
                    function emitDownlevelTaggedTemplate(node) {
                        var tempVariable = createAndRecordTempVariable(node);
                        write("(");
                        emit(tempVariable);
                        write(" = ");
                        emitDownlevelTaggedTemplateArray(node, emit);
                        write(", ");
                        emit(tempVariable);
                        write(".raw = ");
                        emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral);
                        write(", ");
                        emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag));
                        write("(");
                        emit(tempVariable);
                        if (node.template.kind === 169) {
                            ts.forEach(node.template.templateSpans, function (templateSpan) {
                                write(", ");
                                var needsParens = templateSpan.expression.kind === 167 && templateSpan.expression.operatorToken.kind === 23;
                                emitParenthesizedIf(templateSpan.expression, needsParens);
                            });
                        }
                        write("))");
                    }
                    function emitTemplateExpression(node) {
                        if (languageVersion >= 2) {
                            ts.forEachChild(node, emit);
                            return;
                        }
                        var emitOuterParens = ts.isExpression(node.parent) && templateNeedsParens(node, node.parent);
                        if (emitOuterParens) {
                            write("(");
                        }
                        var headEmitted = false;
                        if (shouldEmitTemplateHead()) {
                            emitLiteral(node.head);
                            headEmitted = true;
                        }
                        for (var i = 0; i < node.templateSpans.length; i++) {
                            var templateSpan = node.templateSpans[i];
                            var needsParens = templateSpan.expression.kind !== 159 && comparePrecedenceToBinaryPlus(templateSpan.expression) !== 1;
                            if (i > 0 || headEmitted) {
                                write(" + ");
                            }
                            emitParenthesizedIf(templateSpan.expression, needsParens);
                            if (templateSpan.literal.text.length !== 0) {
                                write(" + ");
                                emitLiteral(templateSpan.literal);
                            }
                        }
                        if (emitOuterParens) {
                            write(")");
                        }
                        function shouldEmitTemplateHead() {
                            ts.Debug.assert(node.templateSpans.length !== 0);
                            return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0;
                        }
                        function templateNeedsParens(template, parent) {
                            switch (parent.kind) {
                                case 155:
                                case 156:
                                    return parent.expression === template;
                                case 157:
                                case 159:
                                    return false;
                                default:
                                    return comparePrecedenceToBinaryPlus(parent) !== -1;
                            }
                        }
                        function comparePrecedenceToBinaryPlus(expression) {
                            switch (expression.kind) {
                                case 167:
                                    switch (expression.operatorToken.kind) {
                                        case 35:
                                        case 36:
                                        case 37:
                                            return 1;
                                        case 33:
                                        case 34:
                                            return 0;
                                        default:
                                            return -1;
                                    }
                                case 168:
                                    return -1;
                                default:
                                    return 1;
                            }
                        }
                    }
                    function emitTemplateSpan(span) {
                        emit(span.expression);
                        emit(span.literal);
                    }
                    function emitExpressionForPropertyName(node) {
                        ts.Debug.assert(node.kind !== 150);
                        if (node.kind === 8) {
                            emitLiteral(node);
                        }
                        else if (node.kind === 126) {
                            emit(node.expression);
                        }
                        else {
                            write("\"");
                            if (node.kind === 7) {
                                write(node.text);
                            }
                            else {
                                writeTextOfNode(currentSourceFile, node);
                            }
                            write("\"");
                        }
                    }
                    function isNotExpressionIdentifier(node) {
                        var parent = node.parent;
                        switch (parent.kind) {
                            case 128:
                            case 193:
                            case 150:
                            case 130:
                            case 129:
                            case 218:
                            case 219:
                            case 220:
                            case 132:
                            case 131:
                            case 195:
                            case 134:
                            case 135:
                            case 160:
                            case 196:
                            case 197:
                            case 199:
                            case 200:
                            case 203:
                                return parent.name === node;
                            case 185:
                            case 184:
                            case 209:
                                return false;
                            case 189:
                                return node.parent.label === node;
                        }
                    }
                    function emitExpressionIdentifier(node) {
                        var substitution = resolver.getExpressionNameSubstitution(node);
                        if (substitution) {
                            write(substitution);
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node);
                        }
                    }
                    function getBlockScopedVariableId(node) {
                        return !ts.nodeIsSynthesized(node) && resolver.getBlockScopedVariableId(node);
                    }
                    function emitIdentifier(node) {
                        var variableId = getBlockScopedVariableId(node);
                        if (variableId !== undefined && generatedBlockScopeNames) {
                            var text = generatedBlockScopeNames[variableId];
                            if (text) {
                                write(text);
                                return;
                            }
                        }
                        if (!node.parent) {
                            write(node.text);
                        }
                        else if (!isNotExpressionIdentifier(node)) {
                            emitExpressionIdentifier(node);
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node);
                        }
                    }
                    function emitThis(node) {
                        if (resolver.getNodeCheckFlags(node) & 2) {
                            write("_this");
                        }
                        else {
                            write("this");
                        }
                    }
                    function emitSuper(node) {
                        var flags = resolver.getNodeCheckFlags(node);
                        if (flags & 16) {
                            write("_super.prototype");
                        }
                        else if (flags & 32) {
                            write("_super");
                        }
                        else {
                            write("super");
                        }
                    }
                    function emitObjectBindingPattern(node) {
                        write("{ ");
                        var elements = node.elements;
                        emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
                        write(" }");
                    }
                    function emitArrayBindingPattern(node) {
                        write("[");
                        var elements = node.elements;
                        emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
                        write("]");
                    }
                    function emitBindingElement(node) {
                        if (node.propertyName) {
                            emit(node.propertyName);
                            write(": ");
                        }
                        if (node.dotDotDotToken) {
                            write("...");
                        }
                        if (ts.isBindingPattern(node.name)) {
                            emit(node.name);
                        }
                        else {
                            emitModuleMemberName(node);
                        }
                        emitOptional(" = ", node.initializer);
                    }
                    function emitSpreadElementExpression(node) {
                        write("...");
                        emit(node.expression);
                    }
                    function needsParenthesisForPropertyAccessOrInvocation(node) {
                        switch (node.kind) {
                            case 64:
                            case 151:
                            case 153:
                            case 154:
                            case 155:
                            case 159:
                                return false;
                        }
                        return true;
                    }
                    function emitListWithSpread(elements, multiLine, trailingComma) {
                        var pos = 0;
                        var group = 0;
                        var length = elements.length;
                        while (pos < length) {
                            if (group === 1) {
                                write(".concat(");
                            }
                            else if (group > 1) {
                                write(", ");
                            }
                            var e = elements[pos];
                            if (e.kind === 171) {
                                e = e.expression;
                                emitParenthesizedIf(e, group === 0 && needsParenthesisForPropertyAccessOrInvocation(e));
                                pos++;
                            }
                            else {
                                var i = pos;
                                while (i < length && elements[i].kind !== 171) {
                                    i++;
                                }
                                write("[");
                                if (multiLine) {
                                    increaseIndent();
                                }
                                emitList(elements, pos, i - pos, multiLine, trailingComma && i === length);
                                if (multiLine) {
                                    decreaseIndent();
                                }
                                write("]");
                                pos = i;
                            }
                            group++;
                        }
                        if (group > 1) {
                            write(")");
                        }
                    }
                    function isSpreadElementExpression(node) {
                        return node.kind === 171;
                    }
                    function emitArrayLiteral(node) {
                        var elements = node.elements;
                        if (elements.length === 0) {
                            write("[]");
                        }
                        else if (languageVersion >= 2 || !ts.forEach(elements, isSpreadElementExpression)) {
                            write("[");
                            emitLinePreservingList(node, node.elements, elements.hasTrailingComma, false);
                            write("]");
                        }
                        else {
                            emitListWithSpread(elements, (node.flags & 512) !== 0, elements.hasTrailingComma);
                        }
                    }
                    function emitDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex) {
                        var parenthesizedObjectLiteral = createDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex);
                        return emit(parenthesizedObjectLiteral);
                    }
                    function createDownlevelObjectLiteralWithComputedProperties(originalObjectLiteral, firstComputedPropertyIndex) {
                        var tempVar = createAndRecordTempVariable(originalObjectLiteral);
                        var initialObjectLiteral = ts.createSynthesizedNode(152);
                        initialObjectLiteral.properties = originalObjectLiteral.properties.slice(0, firstComputedPropertyIndex);
                        initialObjectLiteral.flags |= 512;
                        var propertyPatches = createBinaryExpression(tempVar, 52, initialObjectLiteral);
                        ts.forEach(originalObjectLiteral.properties, function (property) {
                            var patchedProperty = tryCreatePatchingPropertyAssignment(originalObjectLiteral, tempVar, property);
                            if (patchedProperty) {
                                propertyPatches = createBinaryExpression(propertyPatches, 23, patchedProperty);
                            }
                        });
                        propertyPatches = createBinaryExpression(propertyPatches, 23, createIdentifier(tempVar.text, true));
                        var result = createParenthesizedExpression(propertyPatches);
                        return result;
                    }
                    function addCommentsToSynthesizedNode(node, leadingCommentRanges, trailingCommentRanges) {
                        node.leadingCommentRanges = leadingCommentRanges;
                        node.trailingCommentRanges = trailingCommentRanges;
                    }
                    function tryCreatePatchingPropertyAssignment(objectLiteral, tempVar, property) {
                        var leftHandSide = createMemberAccessForPropertyName(tempVar, property.name);
                        var maybeRightHandSide = tryGetRightHandSideOfPatchingPropertyAssignment(objectLiteral, property);
                        return maybeRightHandSide && createBinaryExpression(leftHandSide, 52, maybeRightHandSide, true);
                    }
                    function tryGetRightHandSideOfPatchingPropertyAssignment(objectLiteral, property) {
                        switch (property.kind) {
                            case 218:
                                return property.initializer;
                            case 219:
                                return createIdentifier(resolver.getExpressionNameSubstitution(property.name));
                            case 132:
                                return createFunctionExpression(property.parameters, property.body);
                            case 134:
                            case 135:
                                var _a = getAllAccessorDeclarations(objectLiteral.properties, property), firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor;
                                if (firstAccessor !== property) {
                                    return undefined;
                                }
                                var propertyDescriptor = ts.createSynthesizedNode(152);
                                var descriptorProperties = [];
                                if (getAccessor) {
                                    var getProperty = createPropertyAssignment(createIdentifier("get"), createFunctionExpression(getAccessor.parameters, getAccessor.body));
                                    descriptorProperties.push(getProperty);
                                }
                                if (setAccessor) {
                                    var setProperty = createPropertyAssignment(createIdentifier("set"), createFunctionExpression(setAccessor.parameters, setAccessor.body));
                                    descriptorProperties.push(setProperty);
                                }
                                var trueExpr = ts.createSynthesizedNode(94);
                                var enumerableTrue = createPropertyAssignment(createIdentifier("enumerable"), trueExpr);
                                descriptorProperties.push(enumerableTrue);
                                var configurableTrue = createPropertyAssignment(createIdentifier("configurable"), trueExpr);
                                descriptorProperties.push(configurableTrue);
                                propertyDescriptor.properties = descriptorProperties;
                                var objectDotDefineProperty = createPropertyAccessExpression(createIdentifier("Object"), createIdentifier("defineProperty"));
                                return createCallExpression(objectDotDefineProperty, createNodeArray(propertyDescriptor));
                            default:
                                ts.Debug.fail("ObjectLiteralElement kind " + property.kind + " not accounted for.");
                        }
                    }
                    function createParenthesizedExpression(expression) {
                        var result = ts.createSynthesizedNode(159);
                        result.expression = expression;
                        return result;
                    }
                    function createNodeArray() {
                        var elements = [];
                        for (var _i = 0; _i < arguments.length; _i++) {
                            elements[_i - 0] = arguments[_i];
                        }
                        var result = elements;
                        result.pos = -1;
                        result.end = -1;
                        return result;
                    }
                    function createBinaryExpression(left, operator, right, startsOnNewLine) {
                        var result = ts.createSynthesizedNode(167, startsOnNewLine);
                        result.operatorToken = ts.createSynthesizedNode(operator);
                        result.left = left;
                        result.right = right;
                        return result;
                    }
                    function createExpressionStatement(expression) {
                        var result = ts.createSynthesizedNode(177);
                        result.expression = expression;
                        return result;
                    }
                    function createMemberAccessForPropertyName(expression, memberName) {
                        if (memberName.kind === 64) {
                            return createPropertyAccessExpression(expression, memberName);
                        }
                        else if (memberName.kind === 8 || memberName.kind === 7) {
                            return createElementAccessExpression(expression, memberName);
                        }
                        else if (memberName.kind === 126) {
                            return createElementAccessExpression(expression, memberName.expression);
                        }
                        else {
                            ts.Debug.fail("Kind '" + memberName.kind + "' not accounted for.");
                        }
                    }
                    function createPropertyAssignment(name, initializer) {
                        var result = ts.createSynthesizedNode(218);
                        result.name = name;
                        result.initializer = initializer;
                        return result;
                    }
                    function createFunctionExpression(parameters, body) {
                        var result = ts.createSynthesizedNode(160);
                        result.parameters = parameters;
                        result.body = body;
                        return result;
                    }
                    function createPropertyAccessExpression(expression, name) {
                        var result = ts.createSynthesizedNode(153);
                        result.expression = expression;
                        result.dotToken = ts.createSynthesizedNode(20);
                        result.name = name;
                        return result;
                    }
                    function createElementAccessExpression(expression, argumentExpression) {
                        var result = ts.createSynthesizedNode(154);
                        result.expression = expression;
                        result.argumentExpression = argumentExpression;
                        return result;
                    }
                    function createIdentifier(name, startsOnNewLine) {
                        var result = ts.createSynthesizedNode(64, startsOnNewLine);
                        result.text = name;
                        return result;
                    }
                    function createCallExpression(invokedExpression, arguments) {
                        var result = ts.createSynthesizedNode(155);
                        result.expression = invokedExpression;
                        result.arguments = arguments;
                        return result;
                    }
                    function emitObjectLiteral(node) {
                        var properties = node.properties;
                        if (languageVersion < 2) {
                            var numProperties = properties.length;
                            var numInitialNonComputedProperties = numProperties;
                            for (var i = 0, n = properties.length; i < n; i++) {
                                if (properties[i].name.kind === 126) {
                                    numInitialNonComputedProperties = i;
                                    break;
                                }
                            }
                            var hasComputedProperty = numInitialNonComputedProperties !== properties.length;
                            if (hasComputedProperty) {
                                emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties);
                                return;
                            }
                        }
                        write("{");
                        var properties = node.properties;
                        if (properties.length) {
                            emitLinePreservingList(node, properties, languageVersion >= 1, true);
                        }
                        write("}");
                    }
                    function emitComputedPropertyName(node) {
                        write("[");
                        emit(node.expression);
                        write("]");
                    }
                    function emitMethod(node) {
                        emit(node.name);
                        if (languageVersion < 2) {
                            write(": function ");
                        }
                        emitSignatureAndBody(node);
                    }
                    function emitPropertyAssignment(node) {
                        emit(node.name);
                        write(": ");
                        emit(node.initializer);
                    }
                    function emitShorthandPropertyAssignment(node) {
                        emit(node.name);
                        if (languageVersion < 2 || resolver.getExpressionNameSubstitution(node.name)) {
                            write(": ");
                            emitExpressionIdentifier(node.name);
                        }
                    }
                    function tryEmitConstantValue(node) {
                        var constantValue = resolver.getConstantValue(node);
                        if (constantValue !== undefined) {
                            write(constantValue.toString());
                            if (!compilerOptions.removeComments) {
                                var propertyName = node.kind === 153 ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression);
                                write(" /* " + propertyName + " */");
                            }
                            return true;
                        }
                        return false;
                    }
                    function indentIfOnDifferentLines(parent, node1, node2, valueToWriteWhenNotIndenting) {
                        var realNodesAreOnDifferentLines = preserveNewLines && !ts.nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2);
                        var synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2);
                        if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) {
                            increaseIndent();
                            writeLine();
                            return true;
                        }
                        else {
                            if (valueToWriteWhenNotIndenting) {
                                write(valueToWriteWhenNotIndenting);
                            }
                            return false;
                        }
                    }
                    function emitPropertyAccess(node) {
                        if (tryEmitConstantValue(node)) {
                            return;
                        }
                        emit(node.expression);
                        var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
                        write(".");
                        var indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
                        emit(node.name);
                        decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
                    }
                    function emitQualifiedName(node) {
                        emit(node.left);
                        write(".");
                        emit(node.right);
                    }
                    function emitIndexedAccess(node) {
                        if (tryEmitConstantValue(node)) {
                            return;
                        }
                        emit(node.expression);
                        write("[");
                        emit(node.argumentExpression);
                        write("]");
                    }
                    function hasSpreadElement(elements) {
                        return ts.forEach(elements, function (e) {
                            return e.kind === 171;
                        });
                    }
                    function skipParentheses(node) {
                        while (node.kind === 159 || node.kind === 158) {
                            node = node.expression;
                        }
                        return node;
                    }
                    function emitCallTarget(node) {
                        if (node.kind === 64 || node.kind === 92 || node.kind === 90) {
                            emit(node);
                            return node;
                        }
                        var temp = createAndRecordTempVariable(node);
                        write("(");
                        emit(temp);
                        write(" = ");
                        emit(node);
                        write(")");
                        return temp;
                    }
                    function emitCallWithSpread(node) {
                        var target;
                        var expr = skipParentheses(node.expression);
                        if (expr.kind === 153) {
                            target = emitCallTarget(expr.expression);
                            write(".");
                            emit(expr.name);
                        }
                        else if (expr.kind === 154) {
                            target = emitCallTarget(expr.expression);
                            write("[");
                            emit(expr.argumentExpression);
                            write("]");
                        }
                        else if (expr.kind === 90) {
                            target = expr;
                            write("_super");
                        }
                        else {
                            emit(node.expression);
                        }
                        write(".apply(");
                        if (target) {
                            if (target.kind === 90) {
                                emitThis(target);
                            }
                            else {
                                emit(target);
                            }
                        }
                        else {
                            write("void 0");
                        }
                        write(", ");
                        emitListWithSpread(node.arguments, false, false);
                        write(")");
                    }
                    function emitCallExpression(node) {
                        if (languageVersion < 2 && hasSpreadElement(node.arguments)) {
                            emitCallWithSpread(node);
                            return;
                        }
                        var superCall = false;
                        if (node.expression.kind === 90) {
                            write("_super");
                            superCall = true;
                        }
                        else {
                            emit(node.expression);
                            superCall = node.expression.kind === 153 && node.expression.expression.kind === 90;
                        }
                        if (superCall) {
                            write(".call(");
                            emitThis(node.expression);
                            if (node.arguments.length) {
                                write(", ");
                                emitCommaList(node.arguments);
                            }
                            write(")");
                        }
                        else {
                            write("(");
                            emitCommaList(node.arguments);
                            write(")");
                        }
                    }
                    function emitNewExpression(node) {
                        write("new ");
                        emit(node.expression);
                        if (node.arguments) {
                            write("(");
                            emitCommaList(node.arguments);
                            write(")");
                        }
                    }
                    function emitTaggedTemplateExpression(node) {
                        if (compilerOptions.target >= 2) {
                            emit(node.tag);
                            write(" ");
                            emit(node.template);
                        }
                        else {
                            emitDownlevelTaggedTemplate(node);
                        }
                    }
                    function emitParenExpression(node) {
                        if (!node.parent || node.parent.kind !== 161) {
                            if (node.expression.kind === 158) {
                                var operand = node.expression.expression;
                                while (operand.kind == 158) {
                                    operand = operand.expression;
                                }
                                if (operand.kind !== 165 && operand.kind !== 164 && operand.kind !== 163 && operand.kind !== 162 && operand.kind !== 166 && operand.kind !== 156 && !(operand.kind === 155 && node.parent.kind === 156) && !(operand.kind === 160 && node.parent.kind === 155)) {
                                    emit(operand);
                                    return;
                                }
                            }
                        }
                        write("(");
                        emit(node.expression);
                        write(")");
                    }
                    function emitDeleteExpression(node) {
                        write(ts.tokenToString(73));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitVoidExpression(node) {
                        write(ts.tokenToString(98));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitTypeOfExpression(node) {
                        write(ts.tokenToString(96));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitPrefixUnaryExpression(node) {
                        write(ts.tokenToString(node.operator));
                        if (node.operand.kind === 165) {
                            var operand = node.operand;
                            if (node.operator === 33 && (operand.operator === 33 || operand.operator === 38)) {
                                write(" ");
                            }
                            else if (node.operator === 34 && (operand.operator === 34 || operand.operator === 39)) {
                                write(" ");
                            }
                        }
                        emit(node.operand);
                    }
                    function emitPostfixUnaryExpression(node) {
                        emit(node.operand);
                        write(ts.tokenToString(node.operator));
                    }
                    function emitBinaryExpression(node) {
                        if (languageVersion < 2 && node.operatorToken.kind === 52 && (node.left.kind === 152 || node.left.kind === 151)) {
                            emitDestructuring(node, node.parent.kind === 177);
                        }
                        else {
                            emit(node.left);
                            var indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== 23 ? " " : undefined);
                            write(ts.tokenToString(node.operatorToken.kind));
                            var indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " ");
                            emit(node.right);
                            decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
                        }
                    }
                    function synthesizedNodeStartsOnNewLine(node) {
                        return ts.nodeIsSynthesized(node) && node.startsOnNewLine;
                    }
                    function emitConditionalExpression(node) {
                        emit(node.condition);
                        var indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " ");
                        write("?");
                        var indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " ");
                        emit(node.whenTrue);
                        decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion);
                        var indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " ");
                        write(":");
                        var indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " ");
                        emit(node.whenFalse);
                        decreaseIndentIf(indentedBeforeColon, indentedAfterColon);
                    }
                    function decreaseIndentIf(value1, value2) {
                        if (value1) {
                            decreaseIndent();
                        }
                        if (value2) {
                            decreaseIndent();
                        }
                    }
                    function isSingleLineEmptyBlock(node) {
                        if (node && node.kind === 174) {
                            var block = node;
                            return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block);
                        }
                    }
                    function emitBlock(node) {
                        if (preserveNewLines && isSingleLineEmptyBlock(node)) {
                            emitToken(14, node.pos);
                            write(" ");
                            emitToken(15, node.statements.end);
                            return;
                        }
                        emitToken(14, node.pos);
                        increaseIndent();
                        scopeEmitStart(node.parent);
                        if (node.kind === 201) {
                            ts.Debug.assert(node.parent.kind === 200);
                            emitCaptureThisForNodeIfNecessary(node.parent);
                        }
                        emitLines(node.statements);
                        if (node.kind === 201) {
                            emitTempDeclarations(true);
                        }
                        decreaseIndent();
                        writeLine();
                        emitToken(15, node.statements.end);
                        scopeEmitEnd();
                    }
                    function emitEmbeddedStatement(node) {
                        if (node.kind === 174) {
                            write(" ");
                            emit(node);
                        }
                        else {
                            increaseIndent();
                            writeLine();
                            emit(node);
                            decreaseIndent();
                        }
                    }
                    function emitExpressionStatement(node) {
                        emitParenthesizedIf(node.expression, node.expression.kind === 161);
                        write(";");
                    }
                    function emitIfStatement(node) {
                        var endPos = emitToken(83, node.pos);
                        write(" ");
                        endPos = emitToken(16, endPos);
                        emit(node.expression);
                        emitToken(17, node.expression.end);
                        emitEmbeddedStatement(node.thenStatement);
                        if (node.elseStatement) {
                            writeLine();
                            emitToken(75, node.thenStatement.end);
                            if (node.elseStatement.kind === 178) {
                                write(" ");
                                emit(node.elseStatement);
                            }
                            else {
                                emitEmbeddedStatement(node.elseStatement);
                            }
                        }
                    }
                    function emitDoStatement(node) {
                        write("do");
                        emitEmbeddedStatement(node.statement);
                        if (node.statement.kind === 174) {
                            write(" ");
                        }
                        else {
                            writeLine();
                        }
                        write("while (");
                        emit(node.expression);
                        write(");");
                    }
                    function emitWhileStatement(node) {
                        write("while (");
                        emit(node.expression);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitStartOfVariableDeclarationList(decl, startPos) {
                        var tokenKind = 97;
                        if (decl && languageVersion >= 2) {
                            if (ts.isLet(decl)) {
                                tokenKind = 104;
                            }
                            else if (ts.isConst(decl)) {
                                tokenKind = 69;
                            }
                        }
                        if (startPos !== undefined) {
                            emitToken(tokenKind, startPos);
                        }
                        else {
                            switch (tokenKind) {
                                case 97:
                                    return write("var ");
                                case 104:
                                    return write("let ");
                                case 69:
                                    return write("const ");
                            }
                        }
                    }
                    function emitForStatement(node) {
                        var endPos = emitToken(81, node.pos);
                        write(" ");
                        endPos = emitToken(16, endPos);
                        if (node.initializer && node.initializer.kind === 194) {
                            var variableDeclarationList = node.initializer;
                            var declarations = variableDeclarationList.declarations;
                            emitStartOfVariableDeclarationList(declarations[0], endPos);
                            write(" ");
                            emitCommaList(declarations);
                        }
                        else if (node.initializer) {
                            emit(node.initializer);
                        }
                        write(";");
                        emitOptional(" ", node.condition);
                        write(";");
                        emitOptional(" ", node.iterator);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitForInOrForOfStatement(node) {
                        if (languageVersion < 2 && node.kind === 183) {
                            return emitDownLevelForOfStatement(node);
                        }
                        var endPos = emitToken(81, node.pos);
                        write(" ");
                        endPos = emitToken(16, endPos);
                        if (node.initializer.kind === 194) {
                            var variableDeclarationList = node.initializer;
                            if (variableDeclarationList.declarations.length >= 1) {
                                var decl = variableDeclarationList.declarations[0];
                                emitStartOfVariableDeclarationList(decl, endPos);
                                write(" ");
                                emit(decl);
                            }
                        }
                        else {
                            emit(node.initializer);
                        }
                        if (node.kind === 182) {
                            write(" in ");
                        }
                        else {
                            write(" of ");
                        }
                        emit(node.expression);
                        emitToken(17, node.expression.end);
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitDownLevelForOfStatement(node) {
                        var endPos = emitToken(81, node.pos);
                        write(" ");
                        endPos = emitToken(16, endPos);
                        var rhsIsIdentifier = node.expression.kind === 64;
                        var counter = createTempVariable(node, true);
                        var rhsReference = rhsIsIdentifier ? node.expression : createTempVariable(node, false);
                        emitStart(node.expression);
                        write("var ");
                        emitNodeWithoutSourceMap(counter);
                        write(" = 0");
                        emitEnd(node.expression);
                        if (!rhsIsIdentifier) {
                            write(", ");
                            emitStart(node.expression);
                            emitNodeWithoutSourceMap(rhsReference);
                            write(" = ");
                            emitNodeWithoutSourceMap(node.expression);
                            emitEnd(node.expression);
                        }
                        write("; ");
                        emitStart(node.initializer);
                        emitNodeWithoutSourceMap(counter);
                        write(" < ");
                        emitNodeWithoutSourceMap(rhsReference);
                        write(".length");
                        emitEnd(node.initializer);
                        write("; ");
                        emitStart(node.initializer);
                        emitNodeWithoutSourceMap(counter);
                        write("++");
                        emitEnd(node.initializer);
                        emitToken(17, node.expression.end);
                        write(" {");
                        writeLine();
                        increaseIndent();
                        var rhsIterationValue = createElementAccessExpression(rhsReference, counter);
                        emitStart(node.initializer);
                        if (node.initializer.kind === 194) {
                            write("var ");
                            var variableDeclarationList = node.initializer;
                            if (variableDeclarationList.declarations.length > 0) {
                                var declaration = variableDeclarationList.declarations[0];
                                if (ts.isBindingPattern(declaration.name)) {
                                    emitDestructuring(declaration, false, rhsIterationValue);
                                }
                                else {
                                    emitNodeWithoutSourceMap(declaration);
                                    write(" = ");
                                    emitNodeWithoutSourceMap(rhsIterationValue);
                                }
                            }
                            else {
                                emitNodeWithoutSourceMap(createTempVariable(node, false));
                                write(" = ");
                                emitNodeWithoutSourceMap(rhsIterationValue);
                            }
                        }
                        else {
                            var assignmentExpression = createBinaryExpression(node.initializer, 52, rhsIterationValue, false);
                            if (node.initializer.kind === 151 || node.initializer.kind === 152) {
                                emitDestructuring(assignmentExpression, true, undefined, node);
                            }
                            else {
                                emitNodeWithoutSourceMap(assignmentExpression);
                            }
                        }
                        emitEnd(node.initializer);
                        write(";");
                        if (node.statement.kind === 174) {
                            emitLines(node.statement.statements);
                        }
                        else {
                            writeLine();
                            emit(node.statement);
                        }
                        writeLine();
                        decreaseIndent();
                        write("}");
                    }
                    function emitBreakOrContinueStatement(node) {
                        emitToken(node.kind === 185 ? 65 : 70, node.pos);
                        emitOptional(" ", node.label);
                        write(";");
                    }
                    function emitReturnStatement(node) {
                        emitToken(89, node.pos);
                        emitOptional(" ", node.expression);
                        write(";");
                    }
                    function emitWithStatement(node) {
                        write("with (");
                        emit(node.expression);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitSwitchStatement(node) {
                        var endPos = emitToken(91, node.pos);
                        write(" ");
                        emitToken(16, endPos);
                        emit(node.expression);
                        endPos = emitToken(17, node.expression.end);
                        write(" ");
                        emitCaseBlock(node.caseBlock, endPos);
                    }
                    function emitCaseBlock(node, startPos) {
                        emitToken(14, startPos);
                        increaseIndent();
                        emitLines(node.clauses);
                        decreaseIndent();
                        writeLine();
                        emitToken(15, node.clauses.end);
                    }
                    function nodeStartPositionsAreOnSameLine(node1, node2) {
                        return getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) === getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
                    }
                    function nodeEndPositionsAreOnSameLine(node1, node2) {
                        return getLineOfLocalPosition(currentSourceFile, node1.end) === getLineOfLocalPosition(currentSourceFile, node2.end);
                    }
                    function nodeEndIsOnSameLineAsNodeStart(node1, node2) {
                        return getLineOfLocalPosition(currentSourceFile, node1.end) === getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
                    }
                    function emitCaseOrDefaultClause(node) {
                        if (node.kind === 214) {
                            write("case ");
                            emit(node.expression);
                            write(":");
                        }
                        else {
                            write("default:");
                        }
                        if (preserveNewLines && node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) {
                            write(" ");
                            emit(node.statements[0]);
                        }
                        else {
                            increaseIndent();
                            emitLines(node.statements);
                            decreaseIndent();
                        }
                    }
                    function emitThrowStatement(node) {
                        write("throw ");
                        emit(node.expression);
                        write(";");
                    }
                    function emitTryStatement(node) {
                        write("try ");
                        emit(node.tryBlock);
                        emit(node.catchClause);
                        if (node.finallyBlock) {
                            writeLine();
                            write("finally ");
                            emit(node.finallyBlock);
                        }
                    }
                    function emitCatchClause(node) {
                        writeLine();
                        var endPos = emitToken(67, node.pos);
                        write(" ");
                        emitToken(16, endPos);
                        emit(node.variableDeclaration);
                        emitToken(17, node.variableDeclaration ? node.variableDeclaration.end : endPos);
                        write(" ");
                        emitBlock(node.block);
                    }
                    function emitDebuggerStatement(node) {
                        emitToken(71, node.pos);
                        write(";");
                    }
                    function emitLabelledStatement(node) {
                        emit(node.label);
                        write(": ");
                        emit(node.statement);
                    }
                    function getContainingModule(node) {
                        do {
                            node = node.parent;
                        } while (node && node.kind !== 200);
                        return node;
                    }
                    function emitContainingModuleName(node) {
                        var container = getContainingModule(node);
                        write(container ? resolver.getGeneratedNameForNode(container) : "exports");
                    }
                    function emitModuleMemberName(node) {
                        emitStart(node.name);
                        if (ts.getCombinedNodeFlags(node) & 1) {
                            emitContainingModuleName(node);
                            write(".");
                        }
                        emitNodeWithoutSourceMap(node.name);
                        emitEnd(node.name);
                    }
                    function createVoidZero() {
                        var zero = ts.createSynthesizedNode(7);
                        zero.text = "0";
                        var result = ts.createSynthesizedNode(164);
                        result.expression = zero;
                        return result;
                    }
                    function emitExportMemberAssignments(name) {
                        if (!exportDefault && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) {
                            ts.forEach(exportSpecifiers[name.text], function (specifier) {
                                writeLine();
                                emitStart(specifier.name);
                                emitContainingModuleName(specifier);
                                write(".");
                                emitNodeWithoutSourceMap(specifier.name);
                                emitEnd(specifier.name);
                                write(" = ");
                                emitNodeWithoutSourceMap(name);
                                write(";");
                            });
                        }
                    }
                    function emitDestructuring(root, isAssignmentExpressionStatement, value, lowestNonSynthesizedAncestor) {
                        var emitCount = 0;
                        var isDeclaration = (root.kind === 193 && !(ts.getCombinedNodeFlags(root) & 1)) || root.kind === 128;
                        if (root.kind === 167) {
                            emitAssignmentExpression(root);
                        }
                        else {
                            ts.Debug.assert(!isAssignmentExpressionStatement);
                            emitBindingElement(root, value);
                        }
                        function emitAssignment(name, value) {
                            if (emitCount++) {
                                write(", ");
                            }
                            renameNonTopLevelLetAndConst(name);
                            if (name.parent && (name.parent.kind === 193 || name.parent.kind === 150)) {
                                emitModuleMemberName(name.parent);
                            }
                            else {
                                emit(name);
                            }
                            write(" = ");
                            emit(value);
                        }
                        function ensureIdentifier(expr) {
                            if (expr.kind !== 64) {
                                var identifier = createTempVariable(lowestNonSynthesizedAncestor || root);
                                if (!isDeclaration) {
                                    recordTempDeclaration(identifier);
                                }
                                emitAssignment(identifier, expr);
                                expr = identifier;
                            }
                            return expr;
                        }
                        function createDefaultValueCheck(value, defaultValue) {
                            value = ensureIdentifier(value);
                            var equals = ts.createSynthesizedNode(167);
                            equals.left = value;
                            equals.operatorToken = ts.createSynthesizedNode(30);
                            equals.right = createVoidZero();
                            return createConditionalExpression(equals, defaultValue, value);
                        }
                        function createConditionalExpression(condition, whenTrue, whenFalse) {
                            var cond = ts.createSynthesizedNode(168);
                            cond.condition = condition;
                            cond.questionToken = ts.createSynthesizedNode(50);
                            cond.whenTrue = whenTrue;
                            cond.colonToken = ts.createSynthesizedNode(51);
                            cond.whenFalse = whenFalse;
                            return cond;
                        }
                        function createNumericLiteral(value) {
                            var node = ts.createSynthesizedNode(7);
                            node.text = "" + value;
                            return node;
                        }
                        function parenthesizeForAccess(expr) {
                            if (expr.kind === 64 || expr.kind === 153 || expr.kind === 154) {
                                return expr;
                            }
                            var node = ts.createSynthesizedNode(159);
                            node.expression = expr;
                            return node;
                        }
                        function createPropertyAccess(object, propName) {
                            if (propName.kind !== 64) {
                                return createElementAccess(object, propName);
                            }
                            return createPropertyAccessExpression(parenthesizeForAccess(object), propName);
                        }
                        function createElementAccess(object, index) {
                            var node = ts.createSynthesizedNode(154);
                            node.expression = parenthesizeForAccess(object);
                            node.argumentExpression = index;
                            return node;
                        }
                        function emitObjectLiteralAssignment(target, value) {
                            var properties = target.properties;
                            if (properties.length !== 1) {
                                value = ensureIdentifier(value);
                            }
                            for (var i = 0; i < properties.length; i++) {
                                var p = properties[i];
                                if (p.kind === 218 || p.kind === 219) {
                                    var propName = (p.name);
                                    emitDestructuringAssignment(p.initializer || propName, createPropertyAccess(value, propName));
                                }
                            }
                        }
                        function emitArrayLiteralAssignment(target, value) {
                            var elements = target.elements;
                            if (elements.length !== 1) {
                                value = ensureIdentifier(value);
                            }
                            for (var i = 0; i < elements.length; i++) {
                                var e = elements[i];
                                if (e.kind !== 172) {
                                    if (e.kind !== 171) {
                                        emitDestructuringAssignment(e, createElementAccess(value, createNumericLiteral(i)));
                                    }
                                    else {
                                        if (i === elements.length - 1) {
                                            value = ensureIdentifier(value);
                                            emitAssignment(e.expression, value);
                                            write(".slice(" + i + ")");
                                        }
                                    }
                                }
                            }
                        }
                        function emitDestructuringAssignment(target, value) {
                            if (target.kind === 167 && target.operatorToken.kind === 52) {
                                value = createDefaultValueCheck(value, target.right);
                                target = target.left;
                            }
                            if (target.kind === 152) {
                                emitObjectLiteralAssignment(target, value);
                            }
                            else if (target.kind === 151) {
                                emitArrayLiteralAssignment(target, value);
                            }
                            else {
                                emitAssignment(target, value);
                            }
                        }
                        function emitAssignmentExpression(root) {
                            var target = root.left;
                            var value = root.right;
                            if (isAssignmentExpressionStatement) {
                                emitDestructuringAssignment(target, value);
                            }
                            else {
                                if (root.parent.kind !== 159) {
                                    write("(");
                                }
                                value = ensureIdentifier(value);
                                emitDestructuringAssignment(target, value);
                                write(", ");
                                emit(value);
                                if (root.parent.kind !== 159) {
                                    write(")");
                                }
                            }
                        }
                        function emitBindingElement(target, value) {
                            if (target.initializer) {
                                value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
                            }
                            else if (!value) {
                                value = createVoidZero();
                            }
                            if (ts.isBindingPattern(target.name)) {
                                var pattern = target.name;
                                var elements = pattern.elements;
                                if (elements.length !== 1) {
                                    value = ensureIdentifier(value);
                                }
                                for (var i = 0; i < elements.length; i++) {
                                    var element = elements[i];
                                    if (pattern.kind === 148) {
                                        var propName = element.propertyName || element.name;
                                        emitBindingElement(element, createPropertyAccess(value, propName));
                                    }
                                    else if (element.kind !== 172) {
                                        if (!element.dotDotDotToken) {
                                            emitBindingElement(element, createElementAccess(value, createNumericLiteral(i)));
                                        }
                                        else {
                                            if (i === elements.length - 1) {
                                                value = ensureIdentifier(value);
                                                emitAssignment(element.name, value);
                                                write(".slice(" + i + ")");
                                            }
                                        }
                                    }
                                }
                            }
                            else {
                                emitAssignment(target.name, value);
                            }
                        }
                    }
                    function emitVariableDeclaration(node) {
                        if (ts.isBindingPattern(node.name)) {
                            if (languageVersion < 2) {
                                emitDestructuring(node, false);
                            }
                            else {
                                emit(node.name);
                                emitOptional(" = ", node.initializer);
                            }
                        }
                        else {
                            renameNonTopLevelLetAndConst(node.name);
                            emitModuleMemberName(node);
                            var initializer = node.initializer;
                            if (!initializer && languageVersion < 2) {
                                var isUninitializedLet = (resolver.getNodeCheckFlags(node) & 256) && (getCombinedFlagsForIdentifier(node.name) & 4096);
                                if (isUninitializedLet && node.parent.parent.kind !== 182 && node.parent.parent.kind !== 183) {
                                    initializer = createVoidZero();
                                }
                            }
                            emitOptional(" = ", initializer);
                        }
                    }
                    function emitExportVariableAssignments(node) {
                        var name = node.name;
                        if (name.kind === 64) {
                            emitExportMemberAssignments(name);
                        }
                        else if (ts.isBindingPattern(name)) {
                            ts.forEach(name.elements, emitExportVariableAssignments);
                        }
                    }
                    function getCombinedFlagsForIdentifier(node) {
                        if (!node.parent || (node.parent.kind !== 193 && node.parent.kind !== 150)) {
                            return 0;
                        }
                        return ts.getCombinedNodeFlags(node.parent);
                    }
                    function renameNonTopLevelLetAndConst(node) {
                        if (languageVersion >= 2 || ts.nodeIsSynthesized(node) || node.kind !== 64 || (node.parent.kind !== 193 && node.parent.kind !== 150)) {
                            return;
                        }
                        var combinedFlags = getCombinedFlagsForIdentifier(node);
                        if (((combinedFlags & 12288) === 0) || combinedFlags & 1) {
                            return;
                        }
                        var list = ts.getAncestor(node, 194);
                        if (list.parent.kind === 175 && list.parent.parent.kind === 221) {
                            return;
                        }
                        var blockScopeContainer = ts.getEnclosingBlockScopeContainer(node);
                        var parent = blockScopeContainer.kind === 221 ? blockScopeContainer : blockScopeContainer.parent;
                        var generatedName = generateUniqueNameForLocation(parent, node.text);
                        var variableId = resolver.getBlockScopedVariableId(node);
                        if (!generatedBlockScopeNames) {
                            generatedBlockScopeNames = [];
                        }
                        generatedBlockScopeNames[variableId] = generatedName;
                    }
                    function emitVariableStatement(node) {
                        if (!(node.flags & 1)) {
                            emitStartOfVariableDeclarationList(node.declarationList);
                        }
                        emitCommaList(node.declarationList.declarations);
                        write(";");
                        if (languageVersion < 2 && node.parent === currentSourceFile) {
                            ts.forEach(node.declarationList.declarations, emitExportVariableAssignments);
                        }
                    }
                    function emitParameter(node) {
                        if (languageVersion < 2) {
                            if (ts.isBindingPattern(node.name)) {
                                var name = createTempVariable(node);
                                if (!tempParameters) {
                                    tempParameters = [];
                                }
                                tempParameters.push(name);
                                emit(name);
                            }
                            else {
                                emit(node.name);
                            }
                        }
                        else {
                            if (node.dotDotDotToken) {
                                write("...");
                            }
                            emit(node.name);
                            emitOptional(" = ", node.initializer);
                        }
                    }
                    function emitDefaultValueAssignments(node) {
                        if (languageVersion < 2) {
                            var tempIndex = 0;
                            ts.forEach(node.parameters, function (p) {
                                if (ts.isBindingPattern(p.name)) {
                                    writeLine();
                                    write("var ");
                                    emitDestructuring(p, false, tempParameters[tempIndex]);
                                    write(";");
                                    tempIndex++;
                                }
                                else if (p.initializer) {
                                    writeLine();
                                    emitStart(p);
                                    write("if (");
                                    emitNodeWithoutSourceMap(p.name);
                                    write(" === void 0)");
                                    emitEnd(p);
                                    write(" { ");
                                    emitStart(p);
                                    emitNodeWithoutSourceMap(p.name);
                                    write(" = ");
                                    emitNodeWithoutSourceMap(p.initializer);
                                    emitEnd(p);
                                    write("; }");
                                }
                            });
                        }
                    }
                    function emitRestParameter(node) {
                        if (languageVersion < 2 && ts.hasRestParameters(node)) {
                            var restIndex = node.parameters.length - 1;
                            var restParam = node.parameters[restIndex];
                            var tempName = createTempVariable(node, true).text;
                            writeLine();
                            emitLeadingComments(restParam);
                            emitStart(restParam);
                            write("var ");
                            emitNodeWithoutSourceMap(restParam.name);
                            write(" = [];");
                            emitEnd(restParam);
                            emitTrailingComments(restParam);
                            writeLine();
                            write("for (");
                            emitStart(restParam);
                            write("var " + tempName + " = " + restIndex + ";");
                            emitEnd(restParam);
                            write(" ");
                            emitStart(restParam);
                            write(tempName + " < arguments.length;");
                            emitEnd(restParam);
                            write(" ");
                            emitStart(restParam);
                            write(tempName + "++");
                            emitEnd(restParam);
                            write(") {");
                            increaseIndent();
                            writeLine();
                            emitStart(restParam);
                            emitNodeWithoutSourceMap(restParam.name);
                            write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
                            emitEnd(restParam);
                            decreaseIndent();
                            writeLine();
                            write("}");
                        }
                    }
                    function emitAccessor(node) {
                        write(node.kind === 134 ? "get " : "set ");
                        emit(node.name);
                        emitSignatureAndBody(node);
                    }
                    function shouldEmitAsArrowFunction(node) {
                        return node.kind === 161 && languageVersion >= 2;
                    }
                    function emitDeclarationName(node) {
                        if (node.name) {
                            emitNodeWithoutSourceMap(node.name);
                        }
                        else {
                            write(resolver.getGeneratedNameForNode(node));
                        }
                    }
                    function emitFunctionDeclaration(node) {
                        if (ts.nodeIsMissing(node.body)) {
                            return emitPinnedOrTripleSlashComments(node);
                        }
                        if (node.kind !== 132 && node.kind !== 131) {
                            emitLeadingComments(node);
                        }
                        if (!shouldEmitAsArrowFunction(node)) {
                            write("function ");
                        }
                        if (node.kind === 195 || (node.kind === 160 && node.name)) {
                            emitDeclarationName(node);
                        }
                        emitSignatureAndBody(node);
                        if (languageVersion < 2 && node.kind === 195 && node.parent === currentSourceFile && node.name) {
                            emitExportMemberAssignments(node.name);
                        }
                        if (node.kind !== 132 && node.kind !== 131) {
                            emitTrailingComments(node);
                        }
                    }
                    function emitCaptureThisForNodeIfNecessary(node) {
                        if (resolver.getNodeCheckFlags(node) & 4) {
                            writeLine();
                            emitStart(node);
                            write("var _this = this;");
                            emitEnd(node);
                        }
                    }
                    function emitSignatureParameters(node) {
                        increaseIndent();
                        write("(");
                        if (node) {
                            var parameters = node.parameters;
                            var omitCount = languageVersion < 2 && ts.hasRestParameters(node) ? 1 : 0;
                            emitList(parameters, 0, parameters.length - omitCount, false, false);
                        }
                        write(")");
                        decreaseIndent();
                    }
                    function emitSignatureParametersForArrow(node) {
                        if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) {
                            emit(node.parameters[0]);
                            return;
                        }
                        emitSignatureParameters(node);
                    }
                    function emitSignatureAndBody(node) {
                        var saveTempCount = tempCount;
                        var saveTempVariables = tempVariables;
                        var saveTempParameters = tempParameters;
                        tempCount = 0;
                        tempVariables = undefined;
                        tempParameters = undefined;
                        var popFrame = enterNameScope();
                        if (shouldEmitAsArrowFunction(node)) {
                            emitSignatureParametersForArrow(node);
                            write(" =>");
                        }
                        else {
                            emitSignatureParameters(node);
                        }
                        if (!node.body) {
                            write(" { }");
                        }
                        else if (node.body.kind === 174) {
                            emitBlockFunctionBody(node, node.body);
                        }
                        else {
                            emitExpressionFunctionBody(node, node.body);
                        }
                        if (node.flags & 1 && !(node.flags & 256)) {
                            writeLine();
                            emitStart(node);
                            emitModuleMemberName(node);
                            write(" = ");
                            emitDeclarationName(node);
                            emitEnd(node);
                            write(";");
                        }
                        exitNameScope(popFrame);
                        tempCount = saveTempCount;
                        tempVariables = saveTempVariables;
                        tempParameters = saveTempParameters;
                    }
                    function emitFunctionBodyPreamble(node) {
                        emitCaptureThisForNodeIfNecessary(node);
                        emitDefaultValueAssignments(node);
                        emitRestParameter(node);
                    }
                    function emitExpressionFunctionBody(node, body) {
                        if (languageVersion < 2) {
                            emitDownLevelExpressionFunctionBody(node, body);
                            return;
                        }
                        write(" ");
                        var current = body;
                        while (current.kind === 158) {
                            current = current.expression;
                        }
                        emitParenthesizedIf(body, current.kind === 152);
                    }
                    function emitDownLevelExpressionFunctionBody(node, body) {
                        write(" {");
                        scopeEmitStart(node);
                        increaseIndent();
                        var outPos = writer.getTextPos();
                        emitDetachedComments(node.body);
                        emitFunctionBodyPreamble(node);
                        var preambleEmitted = writer.getTextPos() !== outPos;
                        decreaseIndent();
                        if (preserveNewLines && !preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) {
                            write(" ");
                            emitStart(body);
                            write("return ");
                            emitWithoutComments(body);
                            emitEnd(body);
                            write(";");
                            emitTempDeclarations(false);
                            write(" ");
                        }
                        else {
                            increaseIndent();
                            writeLine();
                            emitLeadingComments(node.body);
                            write("return ");
                            emitWithoutComments(node.body);
                            write(";");
                            emitTrailingComments(node.body);
                            emitTempDeclarations(true);
                            decreaseIndent();
                            writeLine();
                        }
                        emitStart(node.body);
                        write("}");
                        emitEnd(node.body);
                        scopeEmitEnd();
                    }
                    function emitBlockFunctionBody(node, body) {
                        write(" {");
                        scopeEmitStart(node);
                        var initialTextPos = writer.getTextPos();
                        increaseIndent();
                        emitDetachedComments(body.statements);
                        var startIndex = emitDirectivePrologues(body.statements, true);
                        emitFunctionBodyPreamble(node);
                        decreaseIndent();
                        var preambleEmitted = writer.getTextPos() !== initialTextPos;
                        if (preserveNewLines && !preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) {
                            for (var i = 0, n = body.statements.length; i < n; i++) {
                                write(" ");
                                emit(body.statements[i]);
                            }
                            emitTempDeclarations(false);
                            write(" ");
                            emitLeadingCommentsOfPosition(body.statements.end);
                        }
                        else {
                            increaseIndent();
                            emitLinesStartingAt(body.statements, startIndex);
                            emitTempDeclarations(true);
                            writeLine();
                            emitLeadingCommentsOfPosition(body.statements.end);
                            decreaseIndent();
                        }
                        emitToken(15, body.statements.end);
                        scopeEmitEnd();
                    }
                    function findInitialSuperCall(ctor) {
                        if (ctor.body) {
                            var statement = ctor.body.statements[0];
                            if (statement && statement.kind === 177) {
                                var expr = statement.expression;
                                if (expr && expr.kind === 155) {
                                    var func = expr.expression;
                                    if (func && func.kind === 90) {
                                        return statement;
                                    }
                                }
                            }
                        }
                    }
                    function emitParameterPropertyAssignments(node) {
                        ts.forEach(node.parameters, function (param) {
                            if (param.flags & 112) {
                                writeLine();
                                emitStart(param);
                                emitStart(param.name);
                                write("this.");
                                emitNodeWithoutSourceMap(param.name);
                                emitEnd(param.name);
                                write(" = ");
                                emit(param.name);
                                write(";");
                                emitEnd(param);
                            }
                        });
                    }
                    function emitMemberAccessForPropertyName(memberName) {
                        if (memberName.kind === 8 || memberName.kind === 7) {
                            write("[");
                            emitNodeWithoutSourceMap(memberName);
                            write("]");
                        }
                        else if (memberName.kind === 126) {
                            emitComputedPropertyName(memberName);
                        }
                        else {
                            write(".");
                            emitNodeWithoutSourceMap(memberName);
                        }
                    }
                    function emitMemberAssignments(node, staticFlag) {
                        ts.forEach(node.members, function (member) {
                            if (member.kind === 130 && (member.flags & 128) === staticFlag && member.initializer) {
                                writeLine();
                                emitLeadingComments(member);
                                emitStart(member);
                                emitStart(member.name);
                                if (staticFlag) {
                                    emitDeclarationName(node);
                                }
                                else {
                                    write("this");
                                }
                                emitMemberAccessForPropertyName(member.name);
                                emitEnd(member.name);
                                write(" = ");
                                emit(member.initializer);
                                write(";");
                                emitEnd(member);
                                emitTrailingComments(member);
                            }
                        });
                    }
                    function emitMemberFunctions(node) {
                        ts.forEach(node.members, function (member) {
                            if (member.kind === 132 || node.kind === 131) {
                                if (!member.body) {
                                    return emitPinnedOrTripleSlashComments(member);
                                }
                                writeLine();
                                emitLeadingComments(member);
                                emitStart(member);
                                emitStart(member.name);
                                emitDeclarationName(node);
                                if (!(member.flags & 128)) {
                                    write(".prototype");
                                }
                                emitMemberAccessForPropertyName(member.name);
                                emitEnd(member.name);
                                write(" = ");
                                emitStart(member);
                                emitFunctionDeclaration(member);
                                emitEnd(member);
                                emitEnd(member);
                                write(";");
                                emitTrailingComments(member);
                            }
                            else if (member.kind === 134 || member.kind === 135) {
                                var accessors = getAllAccessorDeclarations(node.members, member);
                                if (member === accessors.firstAccessor) {
                                    writeLine();
                                    emitStart(member);
                                    write("Object.defineProperty(");
                                    emitStart(member.name);
                                    emitDeclarationName(node);
                                    if (!(member.flags & 128)) {
                                        write(".prototype");
                                    }
                                    write(", ");
                                    emitExpressionForPropertyName(member.name);
                                    emitEnd(member.name);
                                    write(", {");
                                    increaseIndent();
                                    if (accessors.getAccessor) {
                                        writeLine();
                                        emitLeadingComments(accessors.getAccessor);
                                        write("get: ");
                                        emitStart(accessors.getAccessor);
                                        write("function ");
                                        emitSignatureAndBody(accessors.getAccessor);
                                        emitEnd(accessors.getAccessor);
                                        emitTrailingComments(accessors.getAccessor);
                                        write(",");
                                    }
                                    if (accessors.setAccessor) {
                                        writeLine();
                                        emitLeadingComments(accessors.setAccessor);
                                        write("set: ");
                                        emitStart(accessors.setAccessor);
                                        write("function ");
                                        emitSignatureAndBody(accessors.setAccessor);
                                        emitEnd(accessors.setAccessor);
                                        emitTrailingComments(accessors.setAccessor);
                                        write(",");
                                    }
                                    writeLine();
                                    write("enumerable: true,");
                                    writeLine();
                                    write("configurable: true");
                                    decreaseIndent();
                                    writeLine();
                                    write("});");
                                    emitEnd(member);
                                }
                            }
                        });
                    }
                    function emitClassDeclaration(node) {
                        write("var ");
                        emitDeclarationName(node);
                        write(" = (function (");
                        var baseTypeNode = ts.getClassBaseTypeNode(node);
                        if (baseTypeNode) {
                            write("_super");
                        }
                        write(") {");
                        increaseIndent();
                        scopeEmitStart(node);
                        if (baseTypeNode) {
                            writeLine();
                            emitStart(baseTypeNode);
                            write("__extends(");
                            emitDeclarationName(node);
                            write(", _super);");
                            emitEnd(baseTypeNode);
                        }
                        writeLine();
                        emitConstructorOfClass();
                        emitMemberFunctions(node);
                        emitMemberAssignments(node, 128);
                        writeLine();
                        emitToken(15, node.members.end, function () {
                            write("return ");
                            emitDeclarationName(node);
                        });
                        write(";");
                        decreaseIndent();
                        writeLine();
                        emitToken(15, node.members.end);
                        scopeEmitEnd();
                        emitStart(node);
                        write(")(");
                        if (baseTypeNode) {
                            emit(baseTypeNode.typeName);
                        }
                        write(");");
                        emitEnd(node);
                        if (node.flags & 1 && !(node.flags & 256)) {
                            writeLine();
                            emitStart(node);
                            emitModuleMemberName(node);
                            write(" = ");
                            emitDeclarationName(node);
                            emitEnd(node);
                            write(";");
                        }
                        if (languageVersion < 2 && node.parent === currentSourceFile && node.name) {
                            emitExportMemberAssignments(node.name);
                        }
                        function emitConstructorOfClass() {
                            var saveTempCount = tempCount;
                            var saveTempVariables = tempVariables;
                            var saveTempParameters = tempParameters;
                            tempCount = 0;
                            tempVariables = undefined;
                            tempParameters = undefined;
                            var popFrame = enterNameScope();
                            ts.forEach(node.members, function (member) {
                                if (member.kind === 133 && !member.body) {
                                    emitPinnedOrTripleSlashComments(member);
                                }
                            });
                            var ctor = getFirstConstructorWithBody(node);
                            if (ctor) {
                                emitLeadingComments(ctor);
                            }
                            emitStart(ctor || node);
                            write("function ");
                            emitDeclarationName(node);
                            emitSignatureParameters(ctor);
                            write(" {");
                            scopeEmitStart(node, "constructor");
                            increaseIndent();
                            if (ctor) {
                                emitDetachedComments(ctor.body.statements);
                            }
                            emitCaptureThisForNodeIfNecessary(node);
                            if (ctor) {
                                emitDefaultValueAssignments(ctor);
                                emitRestParameter(ctor);
                                if (baseTypeNode) {
                                    var superCall = findInitialSuperCall(ctor);
                                    if (superCall) {
                                        writeLine();
                                        emit(superCall);
                                    }
                                }
                                emitParameterPropertyAssignments(ctor);
                            }
                            else {
                                if (baseTypeNode) {
                                    writeLine();
                                    emitStart(baseTypeNode);
                                    write("_super.apply(this, arguments);");
                                    emitEnd(baseTypeNode);
                                }
                            }
                            emitMemberAssignments(node, 0);
                            if (ctor) {
                                var statements = ctor.body.statements;
                                if (superCall)
                                    statements = statements.slice(1);
                                emitLines(statements);
                            }
                            emitTempDeclarations(true);
                            writeLine();
                            if (ctor) {
                                emitLeadingCommentsOfPosition(ctor.body.statements.end);
                            }
                            decreaseIndent();
                            emitToken(15, ctor ? ctor.body.statements.end : node.members.end);
                            scopeEmitEnd();
                            emitEnd(ctor || node);
                            if (ctor) {
                                emitTrailingComments(ctor);
                            }
                            exitNameScope(popFrame);
                            tempCount = saveTempCount;
                            tempVariables = saveTempVariables;
                            tempParameters = saveTempParameters;
                        }
                    }
                    function emitInterfaceDeclaration(node) {
                        emitPinnedOrTripleSlashComments(node);
                    }
                    function shouldEmitEnumDeclaration(node) {
                        var isConstEnum = ts.isConst(node);
                        return !isConstEnum || compilerOptions.preserveConstEnums;
                    }
                    function emitEnumDeclaration(node) {
                        if (!shouldEmitEnumDeclaration(node)) {
                            return;
                        }
                        if (!(node.flags & 1)) {
                            emitStart(node);
                            write("var ");
                            emit(node.name);
                            emitEnd(node);
                            write(";");
                        }
                        writeLine();
                        emitStart(node);
                        write("(function (");
                        emitStart(node.name);
                        write(resolver.getGeneratedNameForNode(node));
                        emitEnd(node.name);
                        write(") {");
                        increaseIndent();
                        scopeEmitStart(node);
                        emitLines(node.members);
                        decreaseIndent();
                        writeLine();
                        emitToken(15, node.members.end);
                        scopeEmitEnd();
                        write(")(");
                        emitModuleMemberName(node);
                        write(" || (");
                        emitModuleMemberName(node);
                        write(" = {}));");
                        emitEnd(node);
                        if (node.flags & 1) {
                            writeLine();
                            emitStart(node);
                            write("var ");
                            emit(node.name);
                            write(" = ");
                            emitModuleMemberName(node);
                            emitEnd(node);
                            write(";");
                        }
                        if (languageVersion < 2 && node.parent === currentSourceFile) {
                            emitExportMemberAssignments(node.name);
                        }
                    }
                    function emitEnumMember(node) {
                        var enumParent = node.parent;
                        emitStart(node);
                        write(resolver.getGeneratedNameForNode(enumParent));
                        write("[");
                        write(resolver.getGeneratedNameForNode(enumParent));
                        write("[");
                        emitExpressionForPropertyName(node.name);
                        write("] = ");
                        writeEnumMemberDeclarationValue(node);
                        write("] = ");
                        emitExpressionForPropertyName(node.name);
                        emitEnd(node);
                        write(";");
                    }
                    function writeEnumMemberDeclarationValue(member) {
                        if (!member.initializer || ts.isConst(member.parent)) {
                            var value = resolver.getConstantValue(member);
                            if (value !== undefined) {
                                write(value.toString());
                                return;
                            }
                        }
                        if (member.initializer) {
                            emit(member.initializer);
                        }
                        else {
                            write("undefined");
                        }
                    }
                    function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) {
                        if (moduleDeclaration.body.kind === 200) {
                            var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body);
                            return recursiveInnerModule || moduleDeclaration.body;
                        }
                    }
                    function shouldEmitModuleDeclaration(node) {
                        return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums);
                    }
                    function emitModuleDeclaration(node) {
                        var shouldEmit = shouldEmitModuleDeclaration(node);
                        if (!shouldEmit) {
                            return emitPinnedOrTripleSlashComments(node);
                        }
                        emitStart(node);
                        write("var ");
                        emit(node.name);
                        write(";");
                        emitEnd(node);
                        writeLine();
                        emitStart(node);
                        write("(function (");
                        emitStart(node.name);
                        write(resolver.getGeneratedNameForNode(node));
                        emitEnd(node.name);
                        write(") ");
                        if (node.body.kind === 201) {
                            var saveTempCount = tempCount;
                            var saveTempVariables = tempVariables;
                            tempCount = 0;
                            tempVariables = undefined;
                            var popFrame = enterNameScope();
                            emit(node.body);
                            exitNameScope(popFrame);
                            tempCount = saveTempCount;
                            tempVariables = saveTempVariables;
                        }
                        else {
                            write("{");
                            increaseIndent();
                            scopeEmitStart(node);
                            emitCaptureThisForNodeIfNecessary(node);
                            writeLine();
                            emit(node.body);
                            decreaseIndent();
                            writeLine();
                            var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body;
                            emitToken(15, moduleBlock.statements.end);
                            scopeEmitEnd();
                        }
                        write(")(");
                        if (node.flags & 1) {
                            emit(node.name);
                            write(" = ");
                        }
                        emitModuleMemberName(node);
                        write(" || (");
                        emitModuleMemberName(node);
                        write(" = {}));");
                        emitEnd(node);
                        if (languageVersion < 2 && node.name.kind === 64 && node.parent === currentSourceFile) {
                            emitExportMemberAssignments(node.name);
                        }
                    }
                    function emitRequire(moduleName) {
                        if (moduleName.kind === 8) {
                            write("require(");
                            emitStart(moduleName);
                            emitLiteral(moduleName);
                            emitEnd(moduleName);
                            emitToken(17, moduleName.end);
                            write(";");
                        }
                        else {
                            write("require();");
                        }
                    }
                    function emitImportDeclaration(node) {
                        var info = getExternalImportInfo(node);
                        if (info) {
                            var declarationNode = info.declarationNode;
                            var namedImports = info.namedImports;
                            if (compilerOptions.module !== 2) {
                                emitLeadingComments(node);
                                emitStart(node);
                                var moduleName = ts.getExternalModuleName(node);
                                if (declarationNode) {
                                    if (!(declarationNode.flags & 1))
                                        write("var ");
                                    emitModuleMemberName(declarationNode);
                                    write(" = ");
                                    emitRequire(moduleName);
                                }
                                else if (namedImports) {
                                    write("var ");
                                    write(resolver.getGeneratedNameForNode(node));
                                    write(" = ");
                                    emitRequire(moduleName);
                                }
                                else {
                                    emitRequire(moduleName);
                                }
                                emitEnd(node);
                                emitTrailingComments(node);
                            }
                            else {
                                if (declarationNode) {
                                    if (declarationNode.flags & 1) {
                                        emitModuleMemberName(declarationNode);
                                        write(" = ");
                                        emit(declarationNode.name);
                                        write(";");
                                    }
                                }
                            }
                        }
                    }
                    function emitImportEqualsDeclaration(node) {
                        if (ts.isExternalModuleImportEqualsDeclaration(node)) {
                            emitImportDeclaration(node);
                            return;
                        }
                        if (resolver.isReferencedAliasDeclaration(node) || (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
                            emitLeadingComments(node);
                            emitStart(node);
                            if (!(node.flags & 1))
                                write("var ");
                            emitModuleMemberName(node);
                            write(" = ");
                            emit(node.moduleReference);
                            write(";");
                            emitEnd(node);
                            emitTrailingComments(node);
                        }
                    }
                    function emitExportDeclaration(node) {
                        if (node.moduleSpecifier) {
                            emitStart(node);
                            var generatedName = resolver.getGeneratedNameForNode(node);
                            if (compilerOptions.module !== 2) {
                                write("var ");
                                write(generatedName);
                                write(" = ");
                                emitRequire(ts.getExternalModuleName(node));
                            }
                            if (node.exportClause) {
                                ts.forEach(node.exportClause.elements, function (specifier) {
                                    writeLine();
                                    emitStart(specifier);
                                    emitContainingModuleName(specifier);
                                    write(".");
                                    emitNodeWithoutSourceMap(specifier.name);
                                    write(" = ");
                                    write(generatedName);
                                    write(".");
                                    emitNodeWithoutSourceMap(specifier.propertyName || specifier.name);
                                    write(";");
                                    emitEnd(specifier);
                                });
                            }
                            else {
                                var tempName = createTempVariable(node).text;
                                writeLine();
                                write("for (var " + tempName + " in " + generatedName + ") if (!");
                                emitContainingModuleName(node);
                                write(".hasOwnProperty(" + tempName + ")) ");
                                emitContainingModuleName(node);
                                write("[" + tempName + "] = " + generatedName + "[" + tempName + "];");
                            }
                            emitEnd(node);
                        }
                    }
                    function createExternalImportInfo(node) {
                        if (node.kind === 203) {
                            if (node.moduleReference.kind === 213) {
                                return {
                                    rootNode: node,
                                    declarationNode: node
                                };
                            }
                        }
                        else if (node.kind === 204) {
                            var importClause = node.importClause;
                            if (importClause) {
                                if (importClause.name) {
                                    return {
                                        rootNode: node,
                                        declarationNode: importClause
                                    };
                                }
                                if (importClause.namedBindings.kind === 206) {
                                    return {
                                        rootNode: node,
                                        declarationNode: importClause.namedBindings
                                    };
                                }
                                return {
                                    rootNode: node,
                                    namedImports: importClause.namedBindings,
                                    localName: resolver.getGeneratedNameForNode(node)
                                };
                            }
                            return {
                                rootNode: node
                            };
                        }
                        else if (node.kind === 210) {
                            if (node.moduleSpecifier) {
                                return {
                                    rootNode: node
                                };
                            }
                        }
                    }
                    function createExternalModuleInfo(sourceFile) {
                        externalImports = [];
                        exportSpecifiers = {};
                        exportDefault = undefined;
                        ts.forEach(sourceFile.statements, function (node) {
                            if (node.kind === 210 && !node.moduleSpecifier) {
                                ts.forEach(node.exportClause.elements, function (specifier) {
                                    if (specifier.name.text === "default") {
                                        exportDefault = exportDefault || specifier;
                                    }
                                    var name = (specifier.propertyName || specifier.name).text;
                                    (exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
                                });
                            }
                            else if (node.kind === 209) {
                                exportDefault = exportDefault || node;
                            }
                            else if (node.kind === 195 || node.kind === 196) {
                                if (node.flags & 1 && node.flags & 256) {
                                    exportDefault = exportDefault || node;
                                }
                            }
                            else {
                                var info = createExternalImportInfo(node);
                                if (info) {
                                    if ((!info.declarationNode && !info.namedImports) || resolver.isReferencedAliasDeclaration(node)) {
                                        externalImports.push(info);
                                    }
                                }
                            }
                        });
                    }
                    function getExternalImportInfo(node) {
                        if (externalImports) {
                            for (var i = 0; i < externalImports.length; i++) {
                                var info = externalImports[i];
                                if (info.rootNode === node) {
                                    return info;
                                }
                            }
                        }
                    }
                    function getFirstExportAssignment(sourceFile) {
                        return ts.forEach(sourceFile.statements, function (node) {
                            if (node.kind === 209) {
                                return node;
                            }
                        });
                    }
                    function sortAMDModules(amdModules) {
                        return amdModules.sort(function (moduleA, moduleB) {
                            if (moduleA.name === moduleB.name) {
                                return 0;
                            }
                            else if (!moduleA.name) {
                                return 1;
                            }
                            else {
                                return -1;
                            }
                        });
                    }
                    function emitAMDModule(node, startIndex) {
                        writeLine();
                        write("define(");
                        sortAMDModules(node.amdDependencies);
                        if (node.amdModuleName) {
                            write("\"" + node.amdModuleName + "\", ");
                        }
                        write("[\"require\", \"exports\"");
                        ts.forEach(externalImports, function (info) {
                            write(", ");
                            var moduleName = ts.getExternalModuleName(info.rootNode);
                            if (moduleName.kind === 8) {
                                emitLiteral(moduleName);
                            }
                            else {
                                write("\"\"");
                            }
                        });
                        ts.forEach(node.amdDependencies, function (amdDependency) {
                            var text = "\"" + amdDependency.path + "\"";
                            write(", ");
                            write(text);
                        });
                        write("], function (require, exports");
                        ts.forEach(externalImports, function (info) {
                            write(", ");
                            if (info.declarationNode) {
                                emit(info.declarationNode.name);
                            }
                            else {
                                write(resolver.getGeneratedNameForNode(info.rootNode));
                            }
                        });
                        ts.forEach(node.amdDependencies, function (amdDependency) {
                            if (amdDependency.name) {
                                write(", ");
                                write(amdDependency.name);
                            }
                        });
                        write(") {");
                        increaseIndent();
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        emitExportDefault(node, true);
                        decreaseIndent();
                        writeLine();
                        write("});");
                    }
                    function emitCommonJSModule(node, startIndex) {
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        emitExportDefault(node, false);
                    }
                    function emitExportDefault(sourceFile, emitAsReturn) {
                        if (exportDefault && resolver.hasExportDefaultValue(sourceFile)) {
                            writeLine();
                            emitStart(exportDefault);
                            write(emitAsReturn ? "return " : "module.exports = ");
                            if (exportDefault.kind === 209) {
                                emit(exportDefault.expression);
                            }
                            else if (exportDefault.kind === 212) {
                                emit(exportDefault.propertyName);
                            }
                            else {
                                emitDeclarationName(exportDefault);
                            }
                            write(";");
                            emitEnd(exportDefault);
                        }
                    }
                    function emitDirectivePrologues(statements, startWithNewLine) {
                        for (var i = 0; i < statements.length; ++i) {
                            if (ts.isPrologueDirective(statements[i])) {
                                if (startWithNewLine || i > 0) {
                                    writeLine();
                                }
                                emit(statements[i]);
                            }
                            else {
                                return i;
                            }
                        }
                        return statements.length;
                    }
                    function emitSourceFileNode(node) {
                        writeLine();
                        emitDetachedComments(node);
                        var startIndex = emitDirectivePrologues(node.statements, false);
                        if (!extendsEmitted && resolver.getNodeCheckFlags(node) & 8) {
                            writeLine();
                            write("var __extends = this.__extends || function (d, b) {");
                            increaseIndent();
                            writeLine();
                            write("for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
                            writeLine();
                            write("function __() { this.constructor = d; }");
                            writeLine();
                            write("__.prototype = b.prototype;");
                            writeLine();
                            write("d.prototype = new __();");
                            decreaseIndent();
                            writeLine();
                            write("};");
                            extendsEmitted = true;
                        }
                        if (ts.isExternalModule(node)) {
                            createExternalModuleInfo(node);
                            if (compilerOptions.module === 2) {
                                emitAMDModule(node, startIndex);
                            }
                            else {
                                emitCommonJSModule(node, startIndex);
                            }
                        }
                        else {
                            externalImports = undefined;
                            exportSpecifiers = undefined;
                            exportDefault = undefined;
                            emitCaptureThisForNodeIfNecessary(node);
                            emitLinesStartingAt(node.statements, startIndex);
                            emitTempDeclarations(true);
                        }
                        emitLeadingComments(node.endOfFileToken);
                    }
                    function emitNodeWithoutSourceMapWithComments(node) {
                        if (!node) {
                            return;
                        }
                        if (node.flags & 2) {
                            return emitPinnedOrTripleSlashComments(node);
                        }
                        var emitComments = shouldEmitLeadingAndTrailingComments(node);
                        if (emitComments) {
                            emitLeadingComments(node);
                        }
                        emitJavaScriptWorker(node);
                        if (emitComments) {
                            emitTrailingComments(node);
                        }
                    }
                    function emitNodeWithoutSourceMapWithoutComments(node) {
                        if (!node) {
                            return;
                        }
                        if (node.flags & 2) {
                            return emitPinnedOrTripleSlashComments(node);
                        }
                        emitJavaScriptWorker(node);
                    }
                    function shouldEmitLeadingAndTrailingComments(node) {
                        switch (node.kind) {
                            case 197:
                            case 195:
                            case 204:
                            case 203:
                            case 198:
                            case 209:
                                return false;
                            case 200:
                                return shouldEmitModuleDeclaration(node);
                            case 199:
                                return shouldEmitEnumDeclaration(node);
                        }
                        return true;
                    }
                    function emitJavaScriptWorker(node) {
                        switch (node.kind) {
                            case 64:
                                return emitIdentifier(node);
                            case 128:
                                return emitParameter(node);
                            case 132:
                            case 131:
                                return emitMethod(node);
                            case 134:
                            case 135:
                                return emitAccessor(node);
                            case 92:
                                return emitThis(node);
                            case 90:
                                return emitSuper(node);
                            case 88:
                                return write("null");
                            case 94:
                                return write("true");
                            case 79:
                                return write("false");
                            case 7:
                            case 8:
                            case 9:
                            case 10:
                            case 11:
                            case 12:
                            case 13:
                                return emitLiteral(node);
                            case 169:
                                return emitTemplateExpression(node);
                            case 173:
                                return emitTemplateSpan(node);
                            case 125:
                                return emitQualifiedName(node);
                            case 148:
                                return emitObjectBindingPattern(node);
                            case 149:
                                return emitArrayBindingPattern(node);
                            case 150:
                                return emitBindingElement(node);
                            case 151:
                                return emitArrayLiteral(node);
                            case 152:
                                return emitObjectLiteral(node);
                            case 218:
                                return emitPropertyAssignment(node);
                            case 219:
                                return emitShorthandPropertyAssignment(node);
                            case 126:
                                return emitComputedPropertyName(node);
                            case 153:
                                return emitPropertyAccess(node);
                            case 154:
                                return emitIndexedAccess(node);
                            case 155:
                                return emitCallExpression(node);
                            case 156:
                                return emitNewExpression(node);
                            case 157:
                                return emitTaggedTemplateExpression(node);
                            case 158:
                                return emit(node.expression);
                            case 159:
                                return emitParenExpression(node);
                            case 195:
                            case 160:
                            case 161:
                                return emitFunctionDeclaration(node);
                            case 162:
                                return emitDeleteExpression(node);
                            case 163:
                                return emitTypeOfExpression(node);
                            case 164:
                                return emitVoidExpression(node);
                            case 165:
                                return emitPrefixUnaryExpression(node);
                            case 166:
                                return emitPostfixUnaryExpression(node);
                            case 167:
                                return emitBinaryExpression(node);
                            case 168:
                                return emitConditionalExpression(node);
                            case 171:
                                return emitSpreadElementExpression(node);
                            case 172:
                                return;
                            case 174:
                            case 201:
                                return emitBlock(node);
                            case 175:
                                return emitVariableStatement(node);
                            case 176:
                                return write(";");
                            case 177:
                                return emitExpressionStatement(node);
                            case 178:
                                return emitIfStatement(node);
                            case 179:
                                return emitDoStatement(node);
                            case 180:
                                return emitWhileStatement(node);
                            case 181:
                                return emitForStatement(node);
                            case 183:
                            case 182:
                                return emitForInOrForOfStatement(node);
                            case 184:
                            case 185:
                                return emitBreakOrContinueStatement(node);
                            case 186:
                                return emitReturnStatement(node);
                            case 187:
                                return emitWithStatement(node);
                            case 188:
                                return emitSwitchStatement(node);
                            case 214:
                            case 215:
                                return emitCaseOrDefaultClause(node);
                            case 189:
                                return emitLabelledStatement(node);
                            case 190:
                                return emitThrowStatement(node);
                            case 191:
                                return emitTryStatement(node);
                            case 217:
                                return emitCatchClause(node);
                            case 192:
                                return emitDebuggerStatement(node);
                            case 193:
                                return emitVariableDeclaration(node);
                            case 196:
                                return emitClassDeclaration(node);
                            case 197:
                                return emitInterfaceDeclaration(node);
                            case 199:
                                return emitEnumDeclaration(node);
                            case 220:
                                return emitEnumMember(node);
                            case 200:
                                return emitModuleDeclaration(node);
                            case 204:
                                return emitImportDeclaration(node);
                            case 203:
                                return emitImportEqualsDeclaration(node);
                            case 210:
                                return emitExportDeclaration(node);
                            case 221:
                                return emitSourceFileNode(node);
                        }
                    }
                    function hasDetachedComments(pos) {
                        return detachedCommentsInfo !== undefined && detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos === pos;
                    }
                    function getLeadingCommentsWithoutDetachedComments() {
                        var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
                        if (detachedCommentsInfo.length - 1) {
                            detachedCommentsInfo.pop();
                        }
                        else {
                            detachedCommentsInfo = undefined;
                        }
                        return leadingComments;
                    }
                    function getLeadingCommentsToEmit(node) {
                        if (node.parent) {
                            if (node.parent.kind === 221 || node.pos !== node.parent.pos) {
                                var leadingComments;
                                if (hasDetachedComments(node.pos)) {
                                    leadingComments = getLeadingCommentsWithoutDetachedComments();
                                }
                                else {
                                    leadingComments = ts.getLeadingCommentRangesOfNode(node, currentSourceFile);
                                }
                                return leadingComments;
                            }
                        }
                    }
                    function emitLeadingDeclarationComments(node) {
                        var leadingComments = getLeadingCommentsToEmit(node);
                        emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
                        emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
                    }
                    function emitTrailingDeclarationComments(node) {
                        if (node.parent) {
                            if (node.parent.kind === 221 || node.end !== node.parent.end) {
                                var trailingComments = ts.getTrailingCommentRanges(currentSourceFile.text, node.end);
                                emitComments(currentSourceFile, writer, trailingComments, false, newLine, writeComment);
                            }
                        }
                    }
                    function emitLeadingCommentsOfLocalPosition(pos) {
                        var leadingComments;
                        if (hasDetachedComments(pos)) {
                            leadingComments = getLeadingCommentsWithoutDetachedComments();
                        }
                        else {
                            leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos);
                        }
                        emitNewLineBeforeLeadingComments(currentSourceFile, writer, {
                            pos: pos,
                            end: pos
                        }, leadingComments);
                        emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
                    }
                    function emitDetachedCommentsAtPosition(node) {
                        var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
                        if (leadingComments) {
                            var detachedComments = [];
                            var lastComment;
                            ts.forEach(leadingComments, function (comment) {
                                if (lastComment) {
                                    var lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end);
                                    var commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos);
                                    if (commentLine >= lastCommentLine + 2) {
                                        return detachedComments;
                                    }
                                }
                                detachedComments.push(comment);
                                lastComment = comment;
                            });
                            if (detachedComments.length) {
                                var lastCommentLine = getLineOfLocalPosition(currentSourceFile, detachedComments[detachedComments.length - 1].end);
                                var nodeLine = getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos));
                                if (nodeLine >= lastCommentLine + 2) {
                                    emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
                                    emitComments(currentSourceFile, writer, detachedComments, true, newLine, writeComment);
                                    var currentDetachedCommentInfo = {
                                        nodePos: node.pos,
                                        detachedCommentEndPos: detachedComments[detachedComments.length - 1].end
                                    };
                                    if (detachedCommentsInfo) {
                                        detachedCommentsInfo.push(currentDetachedCommentInfo);
                                    }
                                    else {
                                        detachedCommentsInfo = [
                                            currentDetachedCommentInfo
                                        ];
                                    }
                                }
                            }
                        }
                    }
                    function emitPinnedOrTripleSlashComments(node) {
                        var pinnedComments = ts.filter(getLeadingCommentsToEmit(node), isPinnedOrTripleSlashComment);
                        function isPinnedOrTripleSlashComment(comment) {
                            if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) {
                                return currentSourceFile.text.charCodeAt(comment.pos + 2) === 33;
                            }
                            else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 && comment.pos + 2 < comment.end && currentSourceFile.text.charCodeAt(comment.pos + 2) === 47 && currentSourceFile.text.substring(comment.pos, comment.end).match(ts.fullTripleSlashReferencePathRegEx)) {
                                return true;
                            }
                        }
                        emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, pinnedComments);
                        emitComments(currentSourceFile, writer, pinnedComments, true, newLine, writeComment);
                    }
                }
                function writeDeclarationFile(jsFilePath, sourceFile) {
                    var emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);
                    if (!emitDeclarationResult.reportedDeclarationError) {
                        var declarationOutput = emitDeclarationResult.referencePathsOutput;
                        var appliedSyncOutputPos = 0;
                        ts.forEach(emitDeclarationResult.aliasDeclarationEmitInfo, function (aliasEmitInfo) {
                            if (aliasEmitInfo.asynchronousOutput) {
                                declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
                                declarationOutput += aliasEmitInfo.asynchronousOutput;
                                appliedSyncOutputPos = aliasEmitInfo.outputPos;
                            }
                        });
                        declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos);
                        writeFile(host, diagnostics, ts.removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
                    }
                }
                function emitFile(jsFilePath, sourceFile) {
                    emitJavaScript(jsFilePath, sourceFile);
                    if (compilerOptions.declaration) {
                        writeDeclarationFile(jsFilePath, sourceFile);
                    }
                }
            }
            ts.emitFiles = emitFiles;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            ts.emitTime = 0;
            ts.ioReadTime = 0;
            ts.version = "1.5.0.0";
            function createCompilerHost(options) {
                var currentDirectory;
                var existingDirectories = {};
                function getCanonicalFileName(fileName) {
                    return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
                }
                var unsupportedFileEncodingErrorCode = -2147024809;
                function getSourceFile(fileName, languageVersion, onError) {
                    try {
                        var start = new Date().getTime();
                        var text = ts.sys.readFile(fileName, options.charset);
                        ts.ioReadTime += new Date().getTime() - start;
                    }
                    catch (e) {
                        if (onError) {
                            onError(e.number === unsupportedFileEncodingErrorCode ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText : e.message);
                        }
                        text = "";
                    }
                    return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion) : undefined;
                }
                function writeFile(fileName, data, writeByteOrderMark, onError) {
                    function directoryExists(directoryPath) {
                        if (ts.hasProperty(existingDirectories, directoryPath)) {
                            return true;
                        }
                        if (ts.sys.directoryExists(directoryPath)) {
                            existingDirectories[directoryPath] = true;
                            return true;
                        }
                        return false;
                    }
                    function ensureDirectoriesExist(directoryPath) {
                        if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
                            var parentDirectory = ts.getDirectoryPath(directoryPath);
                            ensureDirectoriesExist(parentDirectory);
                            ts.sys.createDirectory(directoryPath);
                        }
                    }
                    try {
                        ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
                        ts.sys.writeFile(fileName, data, writeByteOrderMark);
                    }
                    catch (e) {
                        if (onError) {
                            onError(e.message);
                        }
                    }
                }
                return {
                    getSourceFile: getSourceFile,
                    getDefaultLibFileName: function (options) {
                        return ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())), ts.getDefaultLibFileName(options));
                    },
                    writeFile: writeFile,
                    getCurrentDirectory: function () {
                        return currentDirectory || (currentDirectory = ts.sys.getCurrentDirectory());
                    },
                    useCaseSensitiveFileNames: function () {
                        return ts.sys.useCaseSensitiveFileNames;
                    },
                    getCanonicalFileName: getCanonicalFileName,
                    getNewLine: function () {
                        return ts.sys.newLine;
                    }
                };
            }
            ts.createCompilerHost = createCompilerHost;
            function getPreEmitDiagnostics(program) {
                var diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
                return ts.sortAndDeduplicateDiagnostics(diagnostics);
            }
            ts.getPreEmitDiagnostics = getPreEmitDiagnostics;
            function flattenDiagnosticMessageText(messageText, newLine) {
                if (typeof messageText === "string") {
                    return messageText;
                }
                else {
                    var diagnosticChain = messageText;
                    var result = "";
                    var indent = 0;
                    while (diagnosticChain) {
                        if (indent) {
                            result += newLine;
                            for (var i = 0; i < indent; i++) {
                                result += "  ";
                            }
                        }
                        result += diagnosticChain.messageText;
                        indent++;
                        diagnosticChain = diagnosticChain.next;
                    }
                    return result;
                }
            }
            ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText;
            function createProgram(rootNames, options, host) {
                var program;
                var files = [];
                var filesByName = {};
                var diagnostics = ts.createDiagnosticCollection();
                var seenNoDefaultLib = options.noLib;
                var commonSourceDirectory;
                host = host || createCompilerHost(options);
                ts.forEach(rootNames, function (name) {
                    return processRootFile(name, false);
                });
                if (!seenNoDefaultLib) {
                    processRootFile(host.getDefaultLibFileName(options), true);
                }
                verifyCompilerOptions();
                var diagnosticsProducingTypeChecker;
                var noDiagnosticsTypeChecker;
                program = {
                    getSourceFile: getSourceFile,
                    getSourceFiles: function () {
                        return files;
                    },
                    getCompilerOptions: function () {
                        return options;
                    },
                    getSyntacticDiagnostics: getSyntacticDiagnostics,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getSemanticDiagnostics: getSemanticDiagnostics,
                    getDeclarationDiagnostics: getDeclarationDiagnostics,
                    getTypeChecker: getTypeChecker,
                    getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker,
                    getCommonSourceDirectory: function () {
                        return commonSourceDirectory;
                    },
                    emit: emit,
                    getCurrentDirectory: host.getCurrentDirectory,
                    getNodeCount: function () {
                        return getDiagnosticsProducingTypeChecker().getNodeCount();
                    },
                    getIdentifierCount: function () {
                        return getDiagnosticsProducingTypeChecker().getIdentifierCount();
                    },
                    getSymbolCount: function () {
                        return getDiagnosticsProducingTypeChecker().getSymbolCount();
                    },
                    getTypeCount: function () {
                        return getDiagnosticsProducingTypeChecker().getTypeCount();
                    }
                };
                return program;
                function getEmitHost(writeFileCallback) {
                    return {
                        getCanonicalFileName: host.getCanonicalFileName,
                        getCommonSourceDirectory: program.getCommonSourceDirectory,
                        getCompilerOptions: program.getCompilerOptions,
                        getCurrentDirectory: host.getCurrentDirectory,
                        getNewLine: host.getNewLine,
                        getSourceFile: program.getSourceFile,
                        getSourceFiles: program.getSourceFiles,
                        writeFile: writeFileCallback || host.writeFile
                    };
                }
                function getDiagnosticsProducingTypeChecker() {
                    return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, true));
                }
                function getTypeChecker() {
                    return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, false));
                }
                function getDeclarationDiagnostics(targetSourceFile) {
                    var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(targetSourceFile);
                    return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
                }
                function emit(sourceFile, writeFileCallback) {
                    if (options.noEmitOnError && getPreEmitDiagnostics(this).length > 0) {
                        return {
                            diagnostics: [],
                            sourceMaps: undefined,
                            emitSkipped: true
                        };
                    }
                    var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
                    var start = new Date().getTime();
                    var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile);
                    ts.emitTime += new Date().getTime() - start;
                    return emitResult;
                }
                function getSourceFile(fileName) {
                    fileName = host.getCanonicalFileName(fileName);
                    return ts.hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
                }
                function getDiagnosticsHelper(sourceFile, getDiagnostics) {
                    if (sourceFile) {
                        return getDiagnostics(sourceFile);
                    }
                    var allDiagnostics = [];
                    ts.forEach(program.getSourceFiles(), function (sourceFile) {
                        ts.addRange(allDiagnostics, getDiagnostics(sourceFile));
                    });
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function getSyntacticDiagnostics(sourceFile) {
                    return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile);
                }
                function getSemanticDiagnostics(sourceFile) {
                    return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile);
                }
                function getSyntacticDiagnosticsForFile(sourceFile) {
                    return sourceFile.parseDiagnostics;
                }
                function getSemanticDiagnosticsForFile(sourceFile) {
                    var typeChecker = getDiagnosticsProducingTypeChecker();
                    ts.Debug.assert(!!sourceFile.bindDiagnostics);
                    var bindDiagnostics = sourceFile.bindDiagnostics;
                    var checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
                    var programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
                    return bindDiagnostics.concat(checkDiagnostics).concat(programDiagnostics);
                }
                function getGlobalDiagnostics() {
                    var typeChecker = getDiagnosticsProducingTypeChecker();
                    var allDiagnostics = [];
                    ts.addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
                    ts.addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function hasExtension(fileName) {
                    return ts.getBaseFileName(fileName).indexOf(".") >= 0;
                }
                function processRootFile(fileName, isDefaultLib) {
                    processSourceFile(ts.normalizePath(fileName), isDefaultLib);
                }
                function processSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd) {
                    if (refEnd !== undefined && refPos !== undefined) {
                        var start = refPos;
                        var length = refEnd - refPos;
                    }
                    var diagnostic;
                    if (hasExtension(fileName)) {
                        if (!options.allowNonTsExtensions && !ts.fileExtensionIs(host.getCanonicalFileName(fileName), ".ts")) {
                            diagnostic = ts.Diagnostics.File_0_must_have_extension_ts_or_d_ts;
                        }
                        else if (!findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                        }
                        else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
                            diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself;
                        }
                    }
                    else {
                        if (options.allowNonTsExtensions && !findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                        }
                        else if (!findSourceFile(fileName + ".ts", isDefaultLib, refFile, refPos, refEnd) && !findSourceFile(fileName + ".d.ts", isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                            fileName += ".ts";
                        }
                    }
                    if (diagnostic) {
                        if (refFile) {
                            diagnostics.add(ts.createFileDiagnostic(refFile, start, length, diagnostic, fileName));
                        }
                        else {
                            diagnostics.add(ts.createCompilerDiagnostic(diagnostic, fileName));
                        }
                    }
                }
                function findSourceFile(fileName, isDefaultLib, refFile, refStart, refLength) {
                    var canonicalName = host.getCanonicalFileName(fileName);
                    if (ts.hasProperty(filesByName, canonicalName)) {
                        return getSourceFileFromCache(fileName, canonicalName, false);
                    }
                    else {
                        var normalizedAbsolutePath = ts.getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
                        var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
                        if (ts.hasProperty(filesByName, canonicalAbsolutePath)) {
                            return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, true);
                        }
                        var file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, function (hostErrorMessage) {
                            if (refFile) {
                                diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
                            }
                            else {
                                diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
                            }
                        });
                        if (file) {
                            seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
                            filesByName[canonicalAbsolutePath] = file;
                            if (!options.noResolve) {
                                var basePath = ts.getDirectoryPath(fileName);
                                processReferencedFiles(file, basePath);
                                processImportedModules(file, basePath);
                            }
                            if (isDefaultLib) {
                                files.unshift(file);
                            }
                            else {
                                files.push(file);
                            }
                        }
                    }
                    return file;
                    function getSourceFileFromCache(fileName, canonicalName, useAbsolutePath) {
                        var file = filesByName[canonicalName];
                        if (file && host.useCaseSensitiveFileNames()) {
                            var sourceFileName = useAbsolutePath ? ts.getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
                            if (canonicalName !== sourceFileName) {
                                diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
                            }
                        }
                        return file;
                    }
                }
                function processReferencedFiles(file, basePath) {
                    ts.forEach(file.referencedFiles, function (ref) {
                        var referencedFileName = ts.isRootedDiskPath(ref.fileName) ? ref.fileName : ts.combinePaths(basePath, ref.fileName);
                        processSourceFile(ts.normalizePath(referencedFileName), false, file, ref.pos, ref.end);
                    });
                }
                function processImportedModules(file, basePath) {
                    ts.forEach(file.statements, function (node) {
                        if (node.kind === 204 || node.kind === 203 || node.kind === 210) {
                            var moduleNameExpr = ts.getExternalModuleName(node);
                            if (moduleNameExpr && moduleNameExpr.kind === 8) {
                                var moduleNameText = moduleNameExpr.text;
                                if (moduleNameText) {
                                    var searchPath = basePath;
                                    while (true) {
                                        var searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleNameText));
                                        if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
                                            break;
                                        }
                                        var parentPath = ts.getDirectoryPath(searchPath);
                                        if (parentPath === searchPath) {
                                            break;
                                        }
                                        searchPath = parentPath;
                                    }
                                }
                            }
                        }
                        else if (node.kind === 200 && node.name.kind === 8 && (node.flags & 2 || ts.isDeclarationFile(file))) {
                            ts.forEachChild(node.body, function (node) {
                                if (ts.isExternalModuleImportEqualsDeclaration(node) && ts.getExternalModuleImportEqualsDeclarationExpression(node).kind === 8) {
                                    var nameLiteral = ts.getExternalModuleImportEqualsDeclarationExpression(node);
                                    var moduleName = nameLiteral.text;
                                    if (moduleName) {
                                        var searchName = ts.normalizePath(ts.combinePaths(basePath, moduleName));
                                        var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
                                        if (!tsFile) {
                                            findModuleSourceFile(searchName + ".d.ts", nameLiteral);
                                        }
                                    }
                                }
                            });
                        }
                    });
                    function findModuleSourceFile(fileName, nameLiteral) {
                        return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
                    }
                }
                function verifyCompilerOptions() {
                    if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
                        if (options.mapRoot) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
                        }
                        if (options.sourceRoot) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
                        }
                        return;
                    }
                    var firstExternalModuleSourceFile = ts.forEach(files, function (f) {
                        return ts.isExternalModule(f) ? f : undefined;
                    });
                    if (firstExternalModuleSourceFile && !options.module) {
                        var span = ts.getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
                        diagnostics.add(ts.createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
                    }
                    if (options.outDir || options.sourceRoot || (options.mapRoot && (!options.out || firstExternalModuleSourceFile !== undefined))) {
                        var commonPathComponents;
                        ts.forEach(files, function (sourceFile) {
                            if (!(sourceFile.flags & 2048) && !ts.fileExtensionIs(sourceFile.fileName, ".js")) {
                                var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory());
                                sourcePathComponents.pop();
                                if (commonPathComponents) {
                                    for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
                                        if (commonPathComponents[i] !== sourcePathComponents[i]) {
                                            if (i === 0) {
                                                diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
                                                return;
                                            }
                                            commonPathComponents.length = i;
                                            break;
                                        }
                                    }
                                    if (sourcePathComponents.length < commonPathComponents.length) {
                                        commonPathComponents.length = sourcePathComponents.length;
                                    }
                                }
                                else {
                                    commonPathComponents = sourcePathComponents;
                                }
                            }
                        });
                        commonSourceDirectory = ts.getNormalizedPathFromPathComponents(commonPathComponents);
                        if (commonSourceDirectory) {
                            commonSourceDirectory += ts.directorySeparator;
                        }
                    }
                    if (options.noEmit) {
                        if (options.out || options.outDir) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
                        }
                        if (options.declaration) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
                        }
                    }
                }
            }
            ts.createProgram = createProgram;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            ts.optionDeclarations = [
                {
                    name: "charset",
                    type: "string"
                },
                {
                    name: "codepage",
                    type: "number"
                },
                {
                    name: "declaration",
                    shortName: "d",
                    type: "boolean",
                    description: ts.Diagnostics.Generates_corresponding_d_ts_file
                },
                {
                    name: "diagnostics",
                    type: "boolean"
                },
                {
                    name: "emitBOM",
                    type: "boolean"
                },
                {
                    name: "help",
                    shortName: "h",
                    type: "boolean",
                    description: ts.Diagnostics.Print_this_message
                },
                {
                    name: "listFiles",
                    type: "boolean"
                },
                {
                    name: "locale",
                    type: "string"
                },
                {
                    name: "mapRoot",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
                    paramType: ts.Diagnostics.LOCATION
                },
                {
                    name: "module",
                    shortName: "m",
                    type: {
                        "commonjs": 1,
                        "amd": 2
                    },
                    description: ts.Diagnostics.Specify_module_code_generation_Colon_commonjs_or_amd,
                    paramType: ts.Diagnostics.KIND,
                    error: ts.Diagnostics.Argument_for_module_option_must_be_commonjs_or_amd
                },
                {
                    name: "noEmit",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_outputs
                },
                {
                    name: "noEmitOnError",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_outputs_if_any_type_checking_errors_were_reported
                },
                {
                    name: "noImplicitAny",
                    type: "boolean",
                    description: ts.Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type
                },
                {
                    name: "noLib",
                    type: "boolean"
                },
                {
                    name: "noLibCheck",
                    type: "boolean"
                },
                {
                    name: "noResolve",
                    type: "boolean"
                },
                {
                    name: "out",
                    type: "string",
                    description: ts.Diagnostics.Concatenate_and_emit_output_to_single_file,
                    paramType: ts.Diagnostics.FILE
                },
                {
                    name: "outDir",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Redirect_output_structure_to_the_directory,
                    paramType: ts.Diagnostics.DIRECTORY
                },
                {
                    name: "preserveConstEnums",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
                },
                {
                    name: "project",
                    shortName: "p",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Compile_the_project_in_the_given_directory,
                    paramType: ts.Diagnostics.DIRECTORY
                },
                {
                    name: "removeComments",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_comments_to_output
                },
                {
                    name: "sourceMap",
                    type: "boolean",
                    description: ts.Diagnostics.Generates_corresponding_map_file
                },
                {
                    name: "sourceRoot",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
                    paramType: ts.Diagnostics.LOCATION
                },
                {
                    name: "suppressImplicitAnyIndexErrors",
                    type: "boolean",
                    description: ts.Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures
                },
                {
                    name: "stripInternal",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
                    experimental: true
                },
                {
                    name: "preserveNewLines",
                    type: "boolean",
                    description: ts.Diagnostics.Preserve_new_lines_when_emitting_code,
                    experimental: true
                },
                {
                    name: "target",
                    shortName: "t",
                    type: {
                        "es3": 0,
                        "es5": 1,
                        "es6": 2
                    },
                    description: ts.Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
                    paramType: ts.Diagnostics.VERSION,
                    error: ts.Diagnostics.Argument_for_target_option_must_be_es3_es5_or_es6
                },
                {
                    name: "version",
                    shortName: "v",
                    type: "boolean",
                    description: ts.Diagnostics.Print_the_compiler_s_version
                },
                {
                    name: "watch",
                    shortName: "w",
                    type: "boolean",
                    description: ts.Diagnostics.Watch_input_files
                }
            ];
            function parseCommandLine(commandLine) {
                var options = {};
                var fileNames = [];
                var errors = [];
                var shortOptionNames = {};
                var optionNameMap = {};
                ts.forEach(ts.optionDeclarations, function (option) {
                    optionNameMap[option.name.toLowerCase()] = option;
                    if (option.shortName) {
                        shortOptionNames[option.shortName] = option.name;
                    }
                });
                parseStrings(commandLine);
                return {
                    options: options,
                    fileNames: fileNames,
                    errors: errors
                };
                function parseStrings(args) {
                    var i = 0;
                    while (i < args.length) {
                        var s = args[i++];
                        if (s.charCodeAt(0) === 64) {
                            parseResponseFile(s.slice(1));
                        }
                        else if (s.charCodeAt(0) === 45) {
                            s = s.slice(s.charCodeAt(1) === 45 ? 2 : 1).toLowerCase();
                            if (ts.hasProperty(shortOptionNames, s)) {
                                s = shortOptionNames[s];
                            }
                            if (ts.hasProperty(optionNameMap, s)) {
                                var opt = optionNameMap[s];
                                if (!args[i] && opt.type !== "boolean") {
                                    errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
                                }
                                switch (opt.type) {
                                    case "number":
                                        options[opt.name] = parseInt(args[i++]);
                                        break;
                                    case "boolean":
                                        options[opt.name] = true;
                                        break;
                                    case "string":
                                        options[opt.name] = args[i++] || "";
                                        break;
                                    default:
                                        var map = opt.type;
                                        var key = (args[i++] || "").toLowerCase();
                                        if (ts.hasProperty(map, key)) {
                                            options[opt.name] = map[key];
                                        }
                                        else {
                                            errors.push(ts.createCompilerDiagnostic(opt.error));
                                        }
                                }
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, s));
                            }
                        }
                        else {
                            fileNames.push(s);
                        }
                    }
                }
                function parseResponseFile(fileName) {
                    var text = ts.sys.readFile(fileName);
                    if (!text) {
                        errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, fileName));
                        return;
                    }
                    var args = [];
                    var pos = 0;
                    while (true) {
                        while (pos < text.length && text.charCodeAt(pos) <= 32)
                            pos++;
                        if (pos >= text.length)
                            break;
                        var start = pos;
                        if (text.charCodeAt(start) === 34) {
                            pos++;
                            while (pos < text.length && text.charCodeAt(pos) !== 34)
                                pos++;
                            if (pos < text.length) {
                                args.push(text.substring(start + 1, pos));
                                pos++;
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName));
                            }
                        }
                        else {
                            while (text.charCodeAt(pos) > 32)
                                pos++;
                            args.push(text.substring(start, pos));
                        }
                    }
                    parseStrings(args);
                }
            }
            ts.parseCommandLine = parseCommandLine;
            function readConfigFile(fileName) {
                try {
                    var text = ts.sys.readFile(fileName);
                    return /\S/.test(text) ? JSON.parse(text) : {};
                }
                catch (e) {
                }
            }
            ts.readConfigFile = readConfigFile;
            function parseConfigFile(json, basePath) {
                var errors = [];
                return {
                    options: getCompilerOptions(),
                    fileNames: getFiles(),
                    errors: errors
                };
                function getCompilerOptions() {
                    var options = {};
                    var optionNameMap = {};
                    ts.forEach(ts.optionDeclarations, function (option) {
                        optionNameMap[option.name] = option;
                    });
                    var jsonOptions = json["compilerOptions"];
                    if (jsonOptions) {
                        for (var id in jsonOptions) {
                            if (ts.hasProperty(optionNameMap, id)) {
                                var opt = optionNameMap[id];
                                var optType = opt.type;
                                var value = jsonOptions[id];
                                var expectedType = typeof optType === "string" ? optType : "string";
                                if (typeof value === expectedType) {
                                    if (typeof optType !== "string") {
                                        var key = value.toLowerCase();
                                        if (ts.hasProperty(optType, key)) {
                                            value = optType[key];
                                        }
                                        else {
                                            errors.push(ts.createCompilerDiagnostic(opt.error));
                                            value = 0;
                                        }
                                    }
                                    if (opt.isFilePath) {
                                        value = ts.normalizePath(ts.combinePaths(basePath, value));
                                    }
                                    options[opt.name] = value;
                                }
                                else {
                                    errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
                                }
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, id));
                            }
                        }
                    }
                    return options;
                }
                function getFiles() {
                    var files = [];
                    if (ts.hasProperty(json, "files")) {
                        if (json["files"] instanceof Array) {
                            var files = ts.map(json["files"], function (s) {
                                return ts.combinePaths(basePath, s);
                            });
                        }
                    }
                    else {
                        var sysFiles = ts.sys.readDirectory(basePath, ".ts");
                        for (var i = 0; i < sysFiles.length; i++) {
                            var name = sysFiles[i];
                            if (!ts.fileExtensionIs(name, ".d.ts") || !ts.contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
                                files.push(name);
                            }
                        }
                    }
                    return files;
                }
            }
            ts.parseConfigFile = parseConfigFile;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var OutliningElementsCollector;
            (function (OutliningElementsCollector) {
                function collectElements(sourceFile) {
                    var elements = [];
                    var collapseText = "...";
                    function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) {
                        if (hintSpanNode && startElement && endElement) {
                            var span = {
                                textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end),
                                hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
                                bannerText: collapseText,
                                autoCollapse: autoCollapse
                            };
                            elements.push(span);
                        }
                    }
                    function autoCollapse(node) {
                        return ts.isFunctionBlock(node) && node.parent.kind !== 161;
                    }
                    var depth = 0;
                    var maxDepth = 20;
                    function walk(n) {
                        if (depth > maxDepth) {
                            return;
                        }
                        switch (n.kind) {
                            case 174:
                                if (!ts.isFunctionBlock(n)) {
                                    var parent = n.parent;
                                    var openBrace = ts.findChildOfKind(n, 14, sourceFile);
                                    var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
                                    if (parent.kind === 179 || parent.kind === 182 || parent.kind === 183 || parent.kind === 181 || parent.kind === 178 || parent.kind === 180 || parent.kind === 187 || parent.kind === 217) {
                                        addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
                                        break;
                                    }
                                    if (parent.kind === 191) {
                                        var tryStatement = parent;
                                        if (tryStatement.tryBlock === n) {
                                            addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
                                            break;
                                        }
                                        else if (tryStatement.finallyBlock === n) {
                                            var finallyKeyword = ts.findChildOfKind(tryStatement, 80, sourceFile);
                                            if (finallyKeyword) {
                                                addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
                                                break;
                                            }
                                        }
                                    }
                                    var span = ts.createTextSpanFromBounds(n.getStart(), n.end);
                                    elements.push({
                                        textSpan: span,
                                        hintSpan: span,
                                        bannerText: collapseText,
                                        autoCollapse: autoCollapse(n)
                                    });
                                    break;
                                }
                            case 201:
                                var openBrace = ts.findChildOfKind(n, 14, sourceFile);
                                var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
                                addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
                                break;
                            case 196:
                            case 197:
                            case 199:
                            case 152:
                            case 202:
                                var openBrace = ts.findChildOfKind(n, 14, sourceFile);
                                var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
                                addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
                                break;
                            case 151:
                                var openBracket = ts.findChildOfKind(n, 18, sourceFile);
                                var closeBracket = ts.findChildOfKind(n, 19, sourceFile);
                                addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
                                break;
                        }
                        depth++;
                        ts.forEachChild(n, walk);
                        depth--;
                    }
                    walk(sourceFile);
                    return elements;
                }
                OutliningElementsCollector.collectElements = collectElements;
            })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var NavigateTo;
            (function (NavigateTo) {
                function getNavigateToItems(program, cancellationToken, searchValue, maxResultCount) {
                    var patternMatcher = ts.createPatternMatcher(searchValue);
                    var rawItems = [];
                    ts.forEach(program.getSourceFiles(), function (sourceFile) {
                        cancellationToken.throwIfCancellationRequested();
                        var declarations = sourceFile.getNamedDeclarations();
                        for (var i = 0, n = declarations.length; i < n; i++) {
                            var declaration = declarations[i];
                            var name = getDeclarationName(declaration);
                            if (name !== undefined) {
                                var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
                                if (!matches) {
                                    continue;
                                }
                                if (patternMatcher.patternContainsDots) {
                                    var containers = getContainers(declaration);
                                    if (!containers) {
                                        return undefined;
                                    }
                                    matches = patternMatcher.getMatches(containers, name);
                                    if (!matches) {
                                        continue;
                                    }
                                }
                                var fileName = sourceFile.fileName;
                                var matchKind = bestMatchKind(matches);
                                rawItems.push({
                                    name: name,
                                    fileName: fileName,
                                    matchKind: matchKind,
                                    isCaseSensitive: allMatchesAreCaseSensitive(matches),
                                    declaration: declaration
                                });
                            }
                        }
                    });
                    rawItems.sort(compareNavigateToItems);
                    if (maxResultCount !== undefined) {
                        rawItems = rawItems.slice(0, maxResultCount);
                    }
                    var items = ts.map(rawItems, createNavigateToItem);
                    return items;
                    function allMatchesAreCaseSensitive(matches) {
                        ts.Debug.assert(matches.length > 0);
                        for (var i = 0, n = matches.length; i < n; i++) {
                            if (!matches[i].isCaseSensitive) {
                                return false;
                            }
                        }
                        return true;
                    }
                    function getDeclarationName(declaration) {
                        var result = getTextOfIdentifierOrLiteral(declaration.name);
                        if (result !== undefined) {
                            return result;
                        }
                        if (declaration.name.kind === 126) {
                            var expr = declaration.name.expression;
                            if (expr.kind === 153) {
                                return expr.name.text;
                            }
                            return getTextOfIdentifierOrLiteral(expr);
                        }
                        return undefined;
                    }
                    function getTextOfIdentifierOrLiteral(node) {
                        if (node.kind === 64 || node.kind === 8 || node.kind === 7) {
                            return node.text;
                        }
                        return undefined;
                    }
                    function tryAddSingleDeclarationName(declaration, containers) {
                        if (declaration && declaration.name) {
                            var text = getTextOfIdentifierOrLiteral(declaration.name);
                            if (text !== undefined) {
                                containers.unshift(text);
                            }
                            else if (declaration.name.kind === 126) {
                                return tryAddComputedPropertyName(declaration.name.expression, containers, true);
                            }
                            else {
                                return false;
                            }
                        }
                        return true;
                    }
                    function tryAddComputedPropertyName(expression, containers, includeLastPortion) {
                        var text = getTextOfIdentifierOrLiteral(expression);
                        if (text !== undefined) {
                            if (includeLastPortion) {
                                containers.unshift(text);
                            }
                            return true;
                        }
                        if (expression.kind === 153) {
                            var propertyAccess = expression;
                            if (includeLastPortion) {
                                containers.unshift(propertyAccess.name.text);
                            }
                            return tryAddComputedPropertyName(propertyAccess.expression, containers, true);
                        }
                        return false;
                    }
                    function getContainers(declaration) {
                        var containers = [];
                        if (declaration.name.kind === 126) {
                            if (!tryAddComputedPropertyName(declaration.name.expression, containers, false)) {
                                return undefined;
                            }
                        }
                        declaration = ts.getContainerNode(declaration);
                        while (declaration) {
                            if (!tryAddSingleDeclarationName(declaration, containers)) {
                                return undefined;
                            }
                            declaration = ts.getContainerNode(declaration);
                        }
                        return containers;
                    }
                    function bestMatchKind(matches) {
                        ts.Debug.assert(matches.length > 0);
                        var bestMatchKind = 3;
                        for (var i = 0, n = matches.length; i < n; i++) {
                            var kind = matches[i].kind;
                            if (kind < bestMatchKind) {
                                bestMatchKind = kind;
                            }
                        }
                        return bestMatchKind;
                    }
                    var baseSensitivity = {
                        sensitivity: "base"
                    };
                    function compareNavigateToItems(i1, i2) {
                        return i1.matchKind - i2.matchKind || i1.name.localeCompare(i2.name, undefined, baseSensitivity) || i1.name.localeCompare(i2.name);
                    }
                    function createNavigateToItem(rawItem) {
                        var declaration = rawItem.declaration;
                        var container = ts.getContainerNode(declaration);
                        return {
                            name: rawItem.name,
                            kind: ts.getNodeKind(declaration),
                            kindModifiers: ts.getNodeModifiers(declaration),
                            matchKind: ts.PatternMatchKind[rawItem.matchKind],
                            isCaseSensitive: rawItem.isCaseSensitive,
                            fileName: rawItem.fileName,
                            textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()),
                            containerName: container && container.name ? container.name.text : "",
                            containerKind: container && container.name ? ts.getNodeKind(container) : ""
                        };
                    }
                }
                NavigateTo.getNavigateToItems = getNavigateToItems;
            })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var NavigationBar;
            (function (NavigationBar) {
                function getNavigationBarItems(sourceFile) {
                    var hasGlobalNode = false;
                    return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
                    function getIndent(node) {
                        var indent = hasGlobalNode ? 1 : 0;
                        var current = node.parent;
                        while (current) {
                            switch (current.kind) {
                                case 200:
                                    do {
                                        current = current.parent;
                                    } while (current.kind === 200);
                                case 196:
                                case 199:
                                case 197:
                                case 195:
                                    indent++;
                            }
                            current = current.parent;
                        }
                        return indent;
                    }
                    function getChildNodes(nodes) {
                        var childNodes = [];
                        function visit(node) {
                            switch (node.kind) {
                                case 175:
                                    ts.forEach(node.declarationList.declarations, visit);
                                    break;
                                case 148:
                                case 149:
                                    ts.forEach(node.elements, visit);
                                    break;
                                case 210:
                                    if (node.exportClause) {
                                        ts.forEach(node.exportClause.elements, visit);
                                    }
                                    break;
                                case 204:
                                    var importClause = node.importClause;
                                    if (importClause) {
                                        if (importClause.name) {
                                            childNodes.push(importClause);
                                        }
                                        if (importClause.namedBindings) {
                                            if (importClause.namedBindings.kind === 206) {
                                                childNodes.push(importClause.namedBindings);
                                            }
                                            else {
                                                ts.forEach(importClause.namedBindings.elements, visit);
                                            }
                                        }
                                    }
                                    break;
                                case 150:
                                case 193:
                                    if (ts.isBindingPattern(node.name)) {
                                        visit(node.name);
                                        break;
                                    }
                                case 196:
                                case 199:
                                case 197:
                                case 200:
                                case 195:
                                case 203:
                                case 208:
                                case 212:
                                    childNodes.push(node);
                                    break;
                            }
                        }
                        ts.forEach(nodes, visit);
                        return sortNodes(childNodes);
                    }
                    function getTopLevelNodes(node) {
                        var topLevelNodes = [];
                        topLevelNodes.push(node);
                        addTopLevelNodes(node.statements, topLevelNodes);
                        return topLevelNodes;
                    }
                    function sortNodes(nodes) {
                        return nodes.slice(0).sort(function (n1, n2) {
                            if (n1.name && n2.name) {
                                return ts.getPropertyNameForPropertyNameNode(n1.name).localeCompare(ts.getPropertyNameForPropertyNameNode(n2.name));
                            }
                            else if (n1.name) {
                                return 1;
                            }
                            else if (n2.name) {
                                return -1;
                            }
                            else {
                                return n1.kind - n2.kind;
                            }
                        });
                    }
                    function addTopLevelNodes(nodes, topLevelNodes) {
                        nodes = sortNodes(nodes);
                        for (var i = 0, n = nodes.length; i < n; i++) {
                            var node = nodes[i];
                            switch (node.kind) {
                                case 196:
                                case 199:
                                case 197:
                                    topLevelNodes.push(node);
                                    break;
                                case 200:
                                    var moduleDeclaration = node;
                                    topLevelNodes.push(node);
                                    addTopLevelNodes(getInnermostModule(moduleDeclaration).body.statements, topLevelNodes);
                                    break;
                                case 195:
                                    var functionDeclaration = node;
                                    if (isTopLevelFunctionDeclaration(functionDeclaration)) {
                                        topLevelNodes.push(node);
                                        addTopLevelNodes(functionDeclaration.body.statements, topLevelNodes);
                                    }
                                    break;
                            }
                        }
                    }
                    function isTopLevelFunctionDeclaration(functionDeclaration) {
                        if (functionDeclaration.kind === 195) {
                            if (functionDeclaration.body && functionDeclaration.body.kind === 174) {
                                if (ts.forEach(functionDeclaration.body.statements, function (s) {
                                    return s.kind === 195 && !isEmpty(s.name.text);
                                })) {
                                    return true;
                                }
                                if (!ts.isFunctionBlock(functionDeclaration.parent)) {
                                    return true;
                                }
                            }
                        }
                        return false;
                    }
                    function getItemsWorker(nodes, createItem) {
                        var items = [];
                        var keyToItem = {};
                        for (var i = 0, n = nodes.length; i < n; i++) {
                            var child = nodes[i];
                            var item = createItem(child);
                            if (item !== undefined) {
                                if (item.text.length > 0) {
                                    var key = item.text + "-" + item.kind + "-" + item.indent;
                                    var itemWithSameName = keyToItem[key];
                                    if (itemWithSameName) {
                                        merge(itemWithSameName, item);
                                    }
                                    else {
                                        keyToItem[key] = item;
                                        items.push(item);
                                    }
                                }
                            }
                        }
                        return items;
                    }
                    function merge(target, source) {
                        target.spans.push.apply(target.spans, source.spans);
                        if (source.childItems) {
                            if (!target.childItems) {
                                target.childItems = [];
                            }
                            outer: for (var i = 0, n = source.childItems.length; i < n; i++) {
                                var sourceChild = source.childItems[i];
                                for (var j = 0, m = target.childItems.length; j < m; j++) {
                                    var targetChild = target.childItems[j];
                                    if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
                                        merge(targetChild, sourceChild);
                                        continue outer;
                                    }
                                }
                                target.childItems.push(sourceChild);
                            }
                        }
                    }
                    function createChildItem(node) {
                        switch (node.kind) {
                            case 128:
                                if (ts.isBindingPattern(node.name)) {
                                    break;
                                }
                                if ((node.flags & 499) === 0) {
                                    return undefined;
                                }
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 132:
                            case 131:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberFunctionElement);
                            case 134:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberGetAccessorElement);
                            case 135:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberSetAccessorElement);
                            case 138:
                                return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
                            case 220:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 136:
                                return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
                            case 137:
                                return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
                            case 130:
                            case 129:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 195:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.functionElement);
                            case 193:
                            case 150:
                                var variableDeclarationNode;
                                var name;
                                if (node.kind === 150) {
                                    name = node.name;
                                    variableDeclarationNode = node;
                                    while (variableDeclarationNode && variableDeclarationNode.kind !== 193) {
                                        variableDeclarationNode = variableDeclarationNode.parent;
                                    }
                                    ts.Debug.assert(variableDeclarationNode !== undefined);
                                }
                                else {
                                    ts.Debug.assert(!ts.isBindingPattern(node.name));
                                    variableDeclarationNode = node;
                                    name = node.name;
                                }
                                if (ts.isConst(variableDeclarationNode)) {
                                    return createItem(node, getTextOfNode(name), ts.ScriptElementKind.constElement);
                                }
                                else if (ts.isLet(variableDeclarationNode)) {
                                    return createItem(node, getTextOfNode(name), ts.ScriptElementKind.letElement);
                                }
                                else {
                                    return createItem(node, getTextOfNode(name), ts.ScriptElementKind.variableElement);
                                }
                            case 133:
                                return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
                            case 212:
                            case 208:
                            case 203:
                            case 205:
                            case 206:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.alias);
                        }
                        return undefined;
                        function createItem(node, name, scriptElementKind) {
                            return getNavigationBarItem(name, scriptElementKind, ts.getNodeModifiers(node), [
                                getNodeSpan(node)
                            ]);
                        }
                    }
                    function isEmpty(text) {
                        return !text || text.trim() === "";
                    }
                    function getNavigationBarItem(text, kind, kindModifiers, spans, childItems, indent) {
                        if (childItems === void 0) { childItems = []; }
                        if (indent === void 0) { indent = 0; }
                        if (isEmpty(text)) {
                            return undefined;
                        }
                        return {
                            text: text,
                            kind: kind,
                            kindModifiers: kindModifiers,
                            spans: spans,
                            childItems: childItems,
                            indent: indent,
                            bolded: false,
                            grayed: false
                        };
                    }
                    function createTopLevelItem(node) {
                        switch (node.kind) {
                            case 221:
                                return createSourceFileItem(node);
                            case 196:
                                return createClassItem(node);
                            case 199:
                                return createEnumItem(node);
                            case 197:
                                return createIterfaceItem(node);
                            case 200:
                                return createModuleItem(node);
                            case 195:
                                return createFunctionItem(node);
                        }
                        return undefined;
                        function getModuleName(moduleDeclaration) {
                            if (moduleDeclaration.name.kind === 8) {
                                return getTextOfNode(moduleDeclaration.name);
                            }
                            var result = [];
                            result.push(moduleDeclaration.name.text);
                            while (moduleDeclaration.body && moduleDeclaration.body.kind === 200) {
                                moduleDeclaration = moduleDeclaration.body;
                                result.push(moduleDeclaration.name.text);
                            }
                            return result.join(".");
                        }
                        function createModuleItem(node) {
                            var moduleName = getModuleName(node);
                            var childItems = getItemsWorker(getChildNodes(getInnermostModule(node).body.statements), createChildItem);
                            return getNavigationBarItem(moduleName, ts.ScriptElementKind.moduleElement, ts.getNodeModifiers(node), [
                                getNodeSpan(node)
                            ], childItems, getIndent(node));
                        }
                        function createFunctionItem(node) {
                            if (node.name && node.body && node.body.kind === 174) {
                                var childItems = getItemsWorker(sortNodes(node.body.statements), createChildItem);
                                return getNavigationBarItem(node.name.text, ts.ScriptElementKind.functionElement, ts.getNodeModifiers(node), [
                                    getNodeSpan(node)
                                ], childItems, getIndent(node));
                            }
                            return undefined;
                        }
                        function createSourceFileItem(node) {
                            var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
                            if (childItems === undefined || childItems.length === 0) {
                                return undefined;
                            }
                            hasGlobalNode = true;
                            var rootName = ts.isExternalModule(node) ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(node.fileName)))) + "\"" : "<global>";
                            return getNavigationBarItem(rootName, ts.ScriptElementKind.moduleElement, ts.ScriptElementKindModifier.none, [
                                getNodeSpan(node)
                            ], childItems);
                        }
                        function createClassItem(node) {
                            if (!node.name) {
                                return undefined;
                            }
                            var childItems;
                            if (node.members) {
                                var constructor = ts.forEach(node.members, function (member) {
                                    return member.kind === 133 && member;
                                });
                                var nodes = removeDynamicallyNamedProperties(node);
                                if (constructor) {
                                    nodes.push.apply(nodes, ts.filter(constructor.parameters, function (p) {
                                        return !ts.isBindingPattern(p.name);
                                    }));
                                }
                                var childItems = getItemsWorker(sortNodes(nodes), createChildItem);
                            }
                            return getNavigationBarItem(node.name.text, ts.ScriptElementKind.classElement, ts.getNodeModifiers(node), [
                                getNodeSpan(node)
                            ], childItems, getIndent(node));
                        }
                        function createEnumItem(node) {
                            var childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
                            return getNavigationBarItem(node.name.text, ts.ScriptElementKind.enumElement, ts.getNodeModifiers(node), [
                                getNodeSpan(node)
                            ], childItems, getIndent(node));
                        }
                        function createIterfaceItem(node) {
                            var childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
                            return getNavigationBarItem(node.name.text, ts.ScriptElementKind.interfaceElement, ts.getNodeModifiers(node), [
                                getNodeSpan(node)
                            ], childItems, getIndent(node));
                        }
                    }
                    function removeComputedProperties(node) {
                        return ts.filter(node.members, function (member) {
                            return member.name === undefined || member.name.kind !== 126;
                        });
                    }
                    function removeDynamicallyNamedProperties(node) {
                        return ts.filter(node.members, function (member) {
                            return !ts.hasDynamicName(member);
                        });
                    }
                    function getInnermostModule(node) {
                        while (node.body.kind === 200) {
                            node = node.body;
                        }
                        return node;
                    }
                    function getNodeSpan(node) {
                        return node.kind === 221 ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd()) : ts.createTextSpanFromBounds(node.getStart(), node.getEnd());
                    }
                    function getTextOfNode(node) {
                        return ts.getTextOfNodeFromSourceText(sourceFile.text, node);
                    }
                }
                NavigationBar.getNavigationBarItems = getNavigationBarItems;
            })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            (function (PatternMatchKind) {
                PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact";
                PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix";
                PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring";
                PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase";
            })(ts.PatternMatchKind || (ts.PatternMatchKind = {}));
            var PatternMatchKind = ts.PatternMatchKind;
            function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) {
                return {
                    kind: kind,
                    punctuationStripped: punctuationStripped,
                    isCaseSensitive: isCaseSensitive,
                    camelCaseWeight: camelCaseWeight
                };
            }
            function createPatternMatcher(pattern) {
                var stringToWordSpans = {};
                pattern = pattern.trim();
                var fullPatternSegment = createSegment(pattern);
                var dotSeparatedSegments = pattern.split(".").map(function (p) {
                    return createSegment(p.trim());
                });
                var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid);
                return {
                    getMatches: getMatches,
                    getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern,
                    patternContainsDots: dotSeparatedSegments.length > 1
                };
                function skipMatch(candidate) {
                    return invalidPattern || !candidate;
                }
                function getMatchesForLastSegmentOfPattern(candidate) {
                    if (skipMatch(candidate)) {
                        return undefined;
                    }
                    return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
                }
                function getMatches(candidateContainers, candidate) {
                    if (skipMatch(candidate)) {
                        return undefined;
                    }
                    var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
                    if (!candidateMatch) {
                        return undefined;
                    }
                    candidateContainers = candidateContainers || [];
                    if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
                        return undefined;
                    }
                    var totalMatch = candidateMatch;
                    for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i--, j--) {
                        var segment = dotSeparatedSegments[i];
                        var containerName = candidateContainers[j];
                        var containerMatch = matchSegment(containerName, segment);
                        if (!containerMatch) {
                            return undefined;
                        }
                        ts.addRange(totalMatch, containerMatch);
                    }
                    return totalMatch;
                }
                function getWordSpans(word) {
                    if (!ts.hasProperty(stringToWordSpans, word)) {
                        stringToWordSpans[word] = breakIntoWordSpans(word);
                    }
                    return stringToWordSpans[word];
                }
                function matchTextChunk(candidate, chunk, punctuationStripped) {
                    var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
                    if (index === 0) {
                        if (chunk.text.length === candidate.length) {
                            return createPatternMatch(0, punctuationStripped, candidate === chunk.text);
                        }
                        else {
                            return createPatternMatch(1, punctuationStripped, startsWith(candidate, chunk.text));
                        }
                    }
                    var isLowercase = chunk.isLowerCase;
                    if (isLowercase) {
                        if (index > 0) {
                            var wordSpans = getWordSpans(candidate);
                            for (var i = 0, n = wordSpans.length; i < n; i++) {
                                var span = wordSpans[i];
                                if (partStartsWith(candidate, span, chunk.text, true)) {
                                    return createPatternMatch(2, punctuationStripped, partStartsWith(candidate, span, chunk.text, false));
                                }
                            }
                        }
                    }
                    else {
                        if (candidate.indexOf(chunk.text) > 0) {
                            return createPatternMatch(2, punctuationStripped, true);
                        }
                    }
                    if (!isLowercase) {
                        if (chunk.characterSpans.length > 0) {
                            var candidateParts = getWordSpans(candidate);
                            var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, false);
                            if (camelCaseWeight !== undefined) {
                                return createPatternMatch(3, punctuationStripped, true, camelCaseWeight);
                            }
                            camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, true);
                            if (camelCaseWeight !== undefined) {
                                return createPatternMatch(3, punctuationStripped, false, camelCaseWeight);
                            }
                        }
                    }
                    if (isLowercase) {
                        if (chunk.text.length < candidate.length) {
                            if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
                                return createPatternMatch(2, punctuationStripped, false);
                            }
                        }
                    }
                    return undefined;
                }
                function containsSpaceOrAsterisk(text) {
                    for (var i = 0; i < text.length; i++) {
                        var ch = text.charCodeAt(i);
                        if (ch === 32 || ch === 42) {
                            return true;
                        }
                    }
                    return false;
                }
                function matchSegment(candidate, segment) {
                    if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
                        var match = matchTextChunk(candidate, segment.totalTextChunk, false);
                        if (match) {
                            return [
                                match
                            ];
                        }
                    }
                    var subWordTextChunks = segment.subWordTextChunks;
                    var matches = undefined;
                    for (var i = 0, n = subWordTextChunks.length; i < n; i++) {
                        var subWordTextChunk = subWordTextChunks[i];
                        var result = matchTextChunk(candidate, subWordTextChunk, true);
                        if (!result) {
                            return undefined;
                        }
                        matches = matches || [];
                        matches.push(result);
                    }
                    return matches;
                }
                function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) {
                    var patternPartStart = patternSpan ? patternSpan.start : 0;
                    var patternPartLength = patternSpan ? patternSpan.length : pattern.length;
                    if (patternPartLength > candidateSpan.length) {
                        return false;
                    }
                    if (ignoreCase) {
                        for (var i = 0; i < patternPartLength; i++) {
                            var ch1 = pattern.charCodeAt(patternPartStart + i);
                            var ch2 = candidate.charCodeAt(candidateSpan.start + i);
                            if (toLowerCase(ch1) !== toLowerCase(ch2)) {
                                return false;
                            }
                        }
                    }
                    else {
                        for (var i = 0; i < patternPartLength; i++) {
                            var ch1 = pattern.charCodeAt(patternPartStart + i);
                            var ch2 = candidate.charCodeAt(candidateSpan.start + i);
                            if (ch1 !== ch2) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) {
                    var chunkCharacterSpans = chunk.characterSpans;
                    var currentCandidate = 0;
                    var currentChunkSpan = 0;
                    var firstMatch = undefined;
                    var contiguous = undefined;
                    while (true) {
                        if (currentChunkSpan === chunkCharacterSpans.length) {
                            var weight = 0;
                            if (contiguous) {
                                weight += 1;
                            }
                            if (firstMatch === 0) {
                                weight += 2;
                            }
                            return weight;
                        }
                        else if (currentCandidate === candidateParts.length) {
                            return undefined;
                        }
                        var candidatePart = candidateParts[currentCandidate];
                        var gotOneMatchThisCandidate = false;
                        for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
                            var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
                            if (gotOneMatchThisCandidate) {
                                if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
                                    break;
                                }
                            }
                            if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
                                break;
                            }
                            gotOneMatchThisCandidate = true;
                            firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
                            contiguous = contiguous === undefined ? true : contiguous;
                            candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
                        }
                        if (!gotOneMatchThisCandidate && contiguous !== undefined) {
                            contiguous = false;
                        }
                        currentCandidate++;
                    }
                }
            }
            ts.createPatternMatcher = createPatternMatcher;
            function patternMatchCompareTo(match1, match2) {
                return compareType(match1, match2) || compareCamelCase(match1, match2) || compareCase(match1, match2) || comparePunctuation(match1, match2);
            }
            function comparePunctuation(result1, result2) {
                if (result1.punctuationStripped !== result2.punctuationStripped) {
                    return result1.punctuationStripped ? 1 : -1;
                }
                return 0;
            }
            function compareCase(result1, result2) {
                if (result1.isCaseSensitive !== result2.isCaseSensitive) {
                    return result1.isCaseSensitive ? -1 : 1;
                }
                return 0;
            }
            function compareType(result1, result2) {
                return result1.kind - result2.kind;
            }
            function compareCamelCase(result1, result2) {
                if (result1.kind === 3 && result2.kind === 3) {
                    return result2.camelCaseWeight - result1.camelCaseWeight;
                }
                return 0;
            }
            function createSegment(text) {
                return {
                    totalTextChunk: createTextChunk(text),
                    subWordTextChunks: breakPatternIntoTextChunks(text)
                };
            }
            function segmentIsInvalid(segment) {
                return segment.subWordTextChunks.length === 0;
            }
            function isUpperCaseLetter(ch) {
                if (ch >= 65 && ch <= 90) {
                    return true;
                }
                if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 2)) {
                    return false;
                }
                var str = String.fromCharCode(ch);
                return str === str.toUpperCase();
            }
            function isLowerCaseLetter(ch) {
                if (ch >= 97 && ch <= 122) {
                    return true;
                }
                if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 2)) {
                    return false;
                }
                var str = String.fromCharCode(ch);
                return str === str.toLowerCase();
            }
            function containsUpperCaseLetter(string) {
                for (var i = 0, n = string.length; i < n; i++) {
                    if (isUpperCaseLetter(string.charCodeAt(i))) {
                        return true;
                    }
                }
                return false;
            }
            function startsWith(string, search) {
                for (var i = 0, n = search.length; i < n; i++) {
                    if (string.charCodeAt(i) !== search.charCodeAt(i)) {
                        return false;
                    }
                }
                return true;
            }
            function indexOfIgnoringCase(string, value) {
                for (var i = 0, n = string.length - value.length; i <= n; i++) {
                    if (startsWithIgnoringCase(string, value, i)) {
                        return i;
                    }
                }
                return -1;
            }
            function startsWithIgnoringCase(string, value, start) {
                for (var i = 0, n = value.length; i < n; i++) {
                    var ch1 = toLowerCase(string.charCodeAt(i + start));
                    var ch2 = value.charCodeAt(i);
                    if (ch1 !== ch2) {
                        return false;
                    }
                }
                return true;
            }
            function toLowerCase(ch) {
                if (ch >= 65 && ch <= 90) {
                    return 97 + (ch - 65);
                }
                if (ch < 127) {
                    return ch;
                }
                return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
            }
            function isDigit(ch) {
                return ch >= 48 && ch <= 57;
            }
            function isWordChar(ch) {
                return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 || ch === 36;
            }
            function breakPatternIntoTextChunks(pattern) {
                var result = [];
                var wordStart = 0;
                var wordLength = 0;
                for (var i = 0; i < pattern.length; i++) {
                    var ch = pattern.charCodeAt(i);
                    if (isWordChar(ch)) {
                        if (wordLength++ === 0) {
                            wordStart = i;
                        }
                    }
                    else {
                        if (wordLength > 0) {
                            result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
                            wordLength = 0;
                        }
                    }
                }
                if (wordLength > 0) {
                    result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
                }
                return result;
            }
            function createTextChunk(text) {
                var textLowerCase = text.toLowerCase();
                return {
                    text: text,
                    textLowerCase: textLowerCase,
                    isLowerCase: text === textLowerCase,
                    characterSpans: breakIntoCharacterSpans(text)
                };
            }
            function breakIntoCharacterSpans(identifier) {
                return breakIntoSpans(identifier, false);
            }
            ts.breakIntoCharacterSpans = breakIntoCharacterSpans;
            function breakIntoWordSpans(identifier) {
                return breakIntoSpans(identifier, true);
            }
            ts.breakIntoWordSpans = breakIntoWordSpans;
            function breakIntoSpans(identifier, word) {
                var result = [];
                var wordStart = 0;
                for (var i = 1, n = identifier.length; i < n; i++) {
                    var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
                    var currentIsDigit = isDigit(identifier.charCodeAt(i));
                    var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
                    var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
                    if (charIsPunctuation(identifier.charCodeAt(i - 1)) || charIsPunctuation(identifier.charCodeAt(i)) || lastIsDigit != currentIsDigit || hasTransitionFromLowerToUpper || hasTransitionFromUpperToLower) {
                        if (!isAllPunctuation(identifier, wordStart, i)) {
                            result.push(ts.createTextSpan(wordStart, i - wordStart));
                        }
                        wordStart = i;
                    }
                }
                if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
                    result.push(ts.createTextSpan(wordStart, identifier.length - wordStart));
                }
                return result;
            }
            function charIsPunctuation(ch) {
                switch (ch) {
                    case 33:
                    case 34:
                    case 35:
                    case 37:
                    case 38:
                    case 39:
                    case 40:
                    case 41:
                    case 42:
                    case 44:
                    case 45:
                    case 46:
                    case 47:
                    case 58:
                    case 59:
                    case 63:
                    case 64:
                    case 91:
                    case 92:
                    case 93:
                    case 95:
                    case 123:
                    case 125:
                        return true;
                }
                return false;
            }
            function isAllPunctuation(identifier, start, end) {
                for (var i = start; i < end; i++) {
                    var ch = identifier.charCodeAt(i);
                    if (!charIsPunctuation(ch) || ch === 95 || ch === 36) {
                        return false;
                    }
                }
                return true;
            }
            function transitionFromUpperToLower(identifier, word, index, wordStart) {
                if (word) {
                    if (index != wordStart && index + 1 < identifier.length) {
                        var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
                        var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
                        if (currentIsUpper && nextIsLower) {
                            for (var i = wordStart; i < index; i++) {
                                if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
                                    return false;
                                }
                            }
                            return true;
                        }
                    }
                }
                return false;
            }
            function transitionFromLowerToUpper(identifier, word, index) {
                var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
                var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
                var transition = word ? (currentIsUpper && !lastIsUpper) : currentIsUpper;
                return transition;
            }
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var SignatureHelp;
            (function (SignatureHelp) {
                var emptyArray = [];
                var ArgumentListKind;
                (function (ArgumentListKind) {
                    ArgumentListKind[ArgumentListKind["TypeArguments"] = 0] = "TypeArguments";
                    ArgumentListKind[ArgumentListKind["CallArguments"] = 1] = "CallArguments";
                    ArgumentListKind[ArgumentListKind["TaggedTemplateArguments"] = 2] = "TaggedTemplateArguments";
                })(ArgumentListKind || (ArgumentListKind = {}));
                function getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken) {
                    var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position);
                    if (!startingToken) {
                        return undefined;
                    }
                    var argumentInfo = getContainingArgumentInfo(startingToken);
                    cancellationToken.throwIfCancellationRequested();
                    if (!argumentInfo) {
                        return undefined;
                    }
                    var call = argumentInfo.invocation;
                    var candidates = [];
                    var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
                    cancellationToken.throwIfCancellationRequested();
                    if (!candidates.length) {
                        return undefined;
                    }
                    return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
                    function getImmediatelyContainingArgumentInfo(node) {
                        if (node.parent.kind === 155 || node.parent.kind === 156) {
                            var callExpression = node.parent;
                            if (node.kind === 24 || node.kind === 16) {
                                var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
                                var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                                ts.Debug.assert(list !== undefined);
                                return {
                                    kind: isTypeArgList ? 0 : 1,
                                    invocation: callExpression,
                                    argumentsSpan: getApplicableSpanForArguments(list),
                                    argumentIndex: 0,
                                    argumentCount: getArgumentCount(list)
                                };
                            }
                            var listItemInfo = ts.findListItemInfo(node);
                            if (listItemInfo) {
                                var list = listItemInfo.list;
                                var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                                var argumentIndex = getArgumentIndex(list, node);
                                var argumentCount = getArgumentCount(list);
                                ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                                return {
                                    kind: isTypeArgList ? 0 : 1,
                                    invocation: callExpression,
                                    argumentsSpan: getApplicableSpanForArguments(list),
                                    argumentIndex: argumentIndex,
                                    argumentCount: argumentCount
                                };
                            }
                        }
                        else if (node.kind === 10 && node.parent.kind === 157) {
                            if (ts.isInsideTemplateLiteral(node, position)) {
                                return getArgumentListInfoForTemplate(node.parent, 0);
                            }
                        }
                        else if (node.kind === 11 && node.parent.parent.kind === 157) {
                            var templateExpression = node.parent;
                            var tagExpression = templateExpression.parent;
                            ts.Debug.assert(templateExpression.kind === 169);
                            var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1;
                            return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                        }
                        else if (node.parent.kind === 173 && node.parent.parent.parent.kind === 157) {
                            var templateSpan = node.parent;
                            var templateExpression = templateSpan.parent;
                            var tagExpression = templateExpression.parent;
                            ts.Debug.assert(templateExpression.kind === 169);
                            if (node.kind === 13 && !ts.isInsideTemplateLiteral(node, position)) {
                                return undefined;
                            }
                            var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
                            var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
                            return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                        }
                        return undefined;
                    }
                    function getArgumentIndex(argumentsList, node) {
                        var argumentIndex = 0;
                        var listChildren = argumentsList.getChildren();
                        for (var i = 0, n = listChildren.length; i < n; i++) {
                            var child = listChildren[i];
                            if (child === node) {
                                break;
                            }
                            if (child.kind !== 23) {
                                argumentIndex++;
                            }
                        }
                        return argumentIndex;
                    }
                    function getArgumentCount(argumentsList) {
                        var listChildren = argumentsList.getChildren();
                        var argumentCount = ts.countWhere(listChildren, function (arg) {
                            return arg.kind !== 23;
                        });
                        if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 23) {
                            argumentCount++;
                        }
                        return argumentCount;
                    }
                    function getArgumentIndexForTemplatePiece(spanIndex, node) {
                        ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
                        if (ts.isTemplateLiteralKind(node.kind)) {
                            if (ts.isInsideTemplateLiteral(node, position)) {
                                return 0;
                            }
                            return spanIndex + 2;
                        }
                        return spanIndex + 1;
                    }
                    function getArgumentListInfoForTemplate(tagExpression, argumentIndex) {
                        var argumentCount = tagExpression.template.kind === 10 ? 1 : tagExpression.template.templateSpans.length + 1;
                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                        return {
                            kind: 2,
                            invocation: tagExpression,
                            argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
                            argumentIndex: argumentIndex,
                            argumentCount: argumentCount
                        };
                    }
                    function getApplicableSpanForArguments(argumentsList) {
                        var applicableSpanStart = argumentsList.getFullStart();
                        var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), false);
                        return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
                    }
                    function getApplicableSpanForTaggedTemplate(taggedTemplate) {
                        var template = taggedTemplate.template;
                        var applicableSpanStart = template.getStart();
                        var applicableSpanEnd = template.getEnd();
                        if (template.kind === 169) {
                            var lastSpan = ts.lastOrUndefined(template.templateSpans);
                            if (lastSpan.literal.getFullWidth() === 0) {
                                applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, false);
                            }
                        }
                        return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
                    }
                    function getContainingArgumentInfo(node) {
                        for (var n = node; n.kind !== 221; n = n.parent) {
                            if (ts.isFunctionBlock(n)) {
                                return undefined;
                            }
                            if (n.pos < n.parent.pos || n.end > n.parent.end) {
                                ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
                            }
                            var argumentInfo = getImmediatelyContainingArgumentInfo(n);
                            if (argumentInfo) {
                                return argumentInfo;
                            }
                        }
                        return undefined;
                    }
                    function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) {
                        var children = parent.getChildren(sourceFile);
                        var indexOfOpenerToken = children.indexOf(openerToken);
                        ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
                        return children[indexOfOpenerToken + 1];
                    }
                    function selectBestInvalidOverloadIndex(candidates, argumentCount) {
                        var maxParamsSignatureIndex = -1;
                        var maxParams = -1;
                        for (var i = 0; i < candidates.length; i++) {
                            var candidate = candidates[i];
                            if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
                                return i;
                            }
                            if (candidate.parameters.length > maxParams) {
                                maxParams = candidate.parameters.length;
                                maxParamsSignatureIndex = i;
                            }
                        }
                        return maxParamsSignatureIndex;
                    }
                    function createSignatureHelpItems(candidates, bestSignature, argumentListInfo) {
                        var applicableSpan = argumentListInfo.argumentsSpan;
                        var isTypeParameterList = argumentListInfo.kind === 0;
                        var invocation = argumentListInfo.invocation;
                        var callTarget = ts.getInvokedExpression(invocation);
                        var callTargetSymbol = typeInfoResolver.getSymbolAtLocation(callTarget);
                        var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeInfoResolver, callTargetSymbol, undefined, undefined);
                        var items = ts.map(candidates, function (candidateSignature) {
                            var signatureHelpParameters;
                            var prefixDisplayParts = [];
                            var suffixDisplayParts = [];
                            if (callTargetDisplayParts) {
                                prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
                            }
                            if (isTypeParameterList) {
                                prefixDisplayParts.push(ts.punctuationPart(24));
                                var typeParameters = candidateSignature.typeParameters;
                                signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
                                suffixDisplayParts.push(ts.punctuationPart(25));
                                var parameterParts = ts.mapToDisplayParts(function (writer) {
                                    return typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation);
                                });
                                suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
                            }
                            else {
                                var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                                    return typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation);
                                });
                                prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
                                prefixDisplayParts.push(ts.punctuationPart(16));
                                var parameters = candidateSignature.parameters;
                                signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
                                suffixDisplayParts.push(ts.punctuationPart(17));
                            }
                            var returnTypeParts = ts.mapToDisplayParts(function (writer) {
                                return typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation);
                            });
                            suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
                            return {
                                isVariadic: candidateSignature.hasRestParameter,
                                prefixDisplayParts: prefixDisplayParts,
                                suffixDisplayParts: suffixDisplayParts,
                                separatorDisplayParts: [
                                    ts.punctuationPart(23),
                                    ts.spacePart()
                                ],
                                parameters: signatureHelpParameters,
                                documentation: candidateSignature.getDocumentationComment()
                            };
                        });
                        var argumentIndex = argumentListInfo.argumentIndex;
                        var argumentCount = argumentListInfo.argumentCount;
                        var selectedItemIndex = candidates.indexOf(bestSignature);
                        if (selectedItemIndex < 0) {
                            selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
                        }
                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                        return {
                            items: items,
                            applicableSpan: applicableSpan,
                            selectedItemIndex: selectedItemIndex,
                            argumentIndex: argumentIndex,
                            argumentCount: argumentCount
                        };
                        function createSignatureHelpParameterForParameter(parameter) {
                            var displayParts = ts.mapToDisplayParts(function (writer) {
                                return typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation);
                            });
                            var isOptional = ts.hasQuestionToken(parameter.valueDeclaration);
                            return {
                                name: parameter.name,
                                documentation: parameter.getDocumentationComment(),
                                displayParts: displayParts,
                                isOptional: isOptional
                            };
                        }
                        function createSignatureHelpParameterForTypeParameter(typeParameter) {
                            var displayParts = ts.mapToDisplayParts(function (writer) {
                                return typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation);
                            });
                            return {
                                name: typeParameter.symbol.name,
                                documentation: emptyArray,
                                displayParts: displayParts,
                                isOptional: false
                            };
                        }
                    }
                }
                SignatureHelp.getSignatureHelpItems = getSignatureHelpItems;
            })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            function getEndLinePosition(line, sourceFile) {
                ts.Debug.assert(line >= 0);
                var lineStarts = sourceFile.getLineStarts();
                var lineIndex = line;
                if (lineIndex + 1 === lineStarts.length) {
                    return sourceFile.text.length - 1;
                }
                else {
                    var start = lineStarts[lineIndex];
                    var pos = lineStarts[lineIndex + 1] - 1;
                    ts.Debug.assert(ts.isLineBreak(sourceFile.text.charCodeAt(pos)));
                    while (start <= pos && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                        pos--;
                    }
                    return pos;
                }
            }
            ts.getEndLinePosition = getEndLinePosition;
            function getLineStartPositionForPosition(position, sourceFile) {
                var lineStarts = sourceFile.getLineStarts();
                var line = sourceFile.getLineAndCharacterOfPosition(position).line;
                return lineStarts[line];
            }
            ts.getLineStartPositionForPosition = getLineStartPositionForPosition;
            function rangeContainsRange(r1, r2) {
                return startEndContainsRange(r1.pos, r1.end, r2);
            }
            ts.rangeContainsRange = rangeContainsRange;
            function startEndContainsRange(start, end, range) {
                return start <= range.pos && end >= range.end;
            }
            ts.startEndContainsRange = startEndContainsRange;
            function rangeContainsStartEnd(range, start, end) {
                return range.pos <= start && range.end >= end;
            }
            ts.rangeContainsStartEnd = rangeContainsStartEnd;
            function rangeOverlapsWithStartEnd(r1, start, end) {
                return startEndOverlapsWithStartEnd(r1.pos, r1.end, start, end);
            }
            ts.rangeOverlapsWithStartEnd = rangeOverlapsWithStartEnd;
            function startEndOverlapsWithStartEnd(start1, end1, start2, end2) {
                var start = Math.max(start1, start2);
                var end = Math.min(end1, end2);
                return start < end;
            }
            ts.startEndOverlapsWithStartEnd = startEndOverlapsWithStartEnd;
            function findListItemInfo(node) {
                var list = findContainingList(node);
                if (!list) {
                    return undefined;
                }
                var children = list.getChildren();
                var listItemIndex = ts.indexOf(children, node);
                return {
                    listItemIndex: listItemIndex,
                    list: list
                };
            }
            ts.findListItemInfo = findListItemInfo;
            function findChildOfKind(n, kind, sourceFile) {
                return ts.forEach(n.getChildren(sourceFile), function (c) {
                    return c.kind === kind && c;
                });
            }
            ts.findChildOfKind = findChildOfKind;
            function findContainingList(node) {
                var syntaxList = ts.forEach(node.parent.getChildren(), function (c) {
                    if (c.kind === 222 && c.pos <= node.pos && c.end >= node.end) {
                        return c;
                    }
                });
                ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node));
                return syntaxList;
            }
            ts.findContainingList = findContainingList;
            function getTouchingWord(sourceFile, position) {
                return getTouchingToken(sourceFile, position, function (n) {
                    return isWord(n.kind);
                });
            }
            ts.getTouchingWord = getTouchingWord;
            function getTouchingPropertyName(sourceFile, position) {
                return getTouchingToken(sourceFile, position, function (n) {
                    return isPropertyName(n.kind);
                });
            }
            ts.getTouchingPropertyName = getTouchingPropertyName;
            function getTouchingToken(sourceFile, position, includeItemAtEndPosition) {
                return getTokenAtPositionWorker(sourceFile, position, false, includeItemAtEndPosition);
            }
            ts.getTouchingToken = getTouchingToken;
            function getTokenAtPosition(sourceFile, position) {
                return getTokenAtPositionWorker(sourceFile, position, true, undefined);
            }
            ts.getTokenAtPosition = getTokenAtPosition;
            function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition) {
                var current = sourceFile;
                outer: while (true) {
                    if (isToken(current)) {
                        return current;
                    }
                    for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
                        var child = current.getChildAt(i);
                        var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
                        if (start <= position) {
                            var end = child.getEnd();
                            if (position < end || (position === end && child.kind === 1)) {
                                current = child;
                                continue outer;
                            }
                            else if (includeItemAtEndPosition && end === position) {
                                var previousToken = findPrecedingToken(position, sourceFile, child);
                                if (previousToken && includeItemAtEndPosition(previousToken)) {
                                    return previousToken;
                                }
                            }
                        }
                    }
                    return current;
                }
            }
            function findTokenOnLeftOfPosition(file, position) {
                var tokenAtPosition = getTokenAtPosition(file, position);
                if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
                    return tokenAtPosition;
                }
                return findPrecedingToken(position, file);
            }
            ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition;
            function findNextToken(previousToken, parent) {
                return find(parent);
                function find(n) {
                    if (isToken(n) && n.pos === previousToken.end) {
                        return n;
                    }
                    var children = n.getChildren();
                    for (var i = 0, len = children.length; i < len; ++i) {
                        var child = children[i];
                        var shouldDiveInChildNode = (child.pos <= previousToken.pos && child.end > previousToken.end) || (child.pos === previousToken.end);
                        if (shouldDiveInChildNode && nodeHasTokens(child)) {
                            return find(child);
                        }
                    }
                    return undefined;
                }
            }
            ts.findNextToken = findNextToken;
            function findPrecedingToken(position, sourceFile, startNode) {
                return find(startNode || sourceFile);
                function findRightmostToken(n) {
                    if (isToken(n)) {
                        return n;
                    }
                    var children = n.getChildren();
                    var candidate = findRightmostChildNodeWithTokens(children, children.length);
                    return candidate && findRightmostToken(candidate);
                }
                function find(n) {
                    if (isToken(n)) {
                        return n;
                    }
                    var children = n.getChildren();
                    for (var i = 0, len = children.length; i < len; ++i) {
                        var child = children[i];
                        if (nodeHasTokens(child)) {
                            if (position <= child.end) {
                                if (child.getStart(sourceFile) >= position) {
                                    var candidate = findRightmostChildNodeWithTokens(children, i);
                                    return candidate && findRightmostToken(candidate);
                                }
                                else {
                                    return find(child);
                                }
                            }
                        }
                    }
                    ts.Debug.assert(startNode !== undefined || n.kind === 221);
                    if (children.length) {
                        var candidate = findRightmostChildNodeWithTokens(children, children.length);
                        return candidate && findRightmostToken(candidate);
                    }
                }
                function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) {
                    for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
                        if (nodeHasTokens(children[i])) {
                            return children[i];
                        }
                    }
                }
            }
            ts.findPrecedingToken = findPrecedingToken;
            function nodeHasTokens(n) {
                return n.getWidth() !== 0;
            }
            function getNodeModifiers(node) {
                var flags = ts.getCombinedNodeFlags(node);
                var result = [];
                if (flags & 32)
                    result.push(ts.ScriptElementKindModifier.privateMemberModifier);
                if (flags & 64)
                    result.push(ts.ScriptElementKindModifier.protectedMemberModifier);
                if (flags & 16)
                    result.push(ts.ScriptElementKindModifier.publicMemberModifier);
                if (flags & 128)
                    result.push(ts.ScriptElementKindModifier.staticModifier);
                if (flags & 1)
                    result.push(ts.ScriptElementKindModifier.exportedModifier);
                if (ts.isInAmbientContext(node))
                    result.push(ts.ScriptElementKindModifier.ambientModifier);
                return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none;
            }
            ts.getNodeModifiers = getNodeModifiers;
            function getTypeArgumentOrTypeParameterList(node) {
                if (node.kind === 139 || node.kind === 155) {
                    return node.typeArguments;
                }
                if (ts.isFunctionLike(node) || node.kind === 196 || node.kind === 197) {
                    return node.typeParameters;
                }
                return undefined;
            }
            ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList;
            function isToken(n) {
                return n.kind >= 0 && n.kind <= 124;
            }
            ts.isToken = isToken;
            function isWord(kind) {
                return kind === 64 || ts.isKeyword(kind);
            }
            function isPropertyName(kind) {
                return kind === 8 || kind === 7 || isWord(kind);
            }
            function isComment(kind) {
                return kind === 2 || kind === 3;
            }
            ts.isComment = isComment;
            function isPunctuation(kind) {
                return 14 <= kind && kind <= 63;
            }
            ts.isPunctuation = isPunctuation;
            function isInsideTemplateLiteral(node, position) {
                return ts.isTemplateLiteralKind(node.kind) && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
            }
            ts.isInsideTemplateLiteral = isInsideTemplateLiteral;
            function compareDataObjects(dst, src) {
                for (var e in dst) {
                    if (typeof dst[e] === "object") {
                        if (!compareDataObjects(dst[e], src[e])) {
                            return false;
                        }
                    }
                    else if (typeof dst[e] !== "function") {
                        if (dst[e] !== src[e]) {
                            return false;
                        }
                    }
                }
                return true;
            }
            ts.compareDataObjects = compareDataObjects;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            function isFirstDeclarationOfSymbolParameter(symbol) {
                return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 128;
            }
            ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter;
            var displayPartWriter = getDisplayPartWriter();
            function getDisplayPartWriter() {
                var displayParts;
                var lineStart;
                var indent;
                resetWriter();
                return {
                    displayParts: function () {
                        return displayParts;
                    },
                    writeKeyword: function (text) {
                        return writeKind(text, 5);
                    },
                    writeOperator: function (text) {
                        return writeKind(text, 12);
                    },
                    writePunctuation: function (text) {
                        return writeKind(text, 15);
                    },
                    writeSpace: function (text) {
                        return writeKind(text, 16);
                    },
                    writeStringLiteral: function (text) {
                        return writeKind(text, 8);
                    },
                    writeParameter: function (text) {
                        return writeKind(text, 13);
                    },
                    writeSymbol: writeSymbol,
                    writeLine: writeLine,
                    increaseIndent: function () {
                        indent++;
                    },
                    decreaseIndent: function () {
                        indent--;
                    },
                    clear: resetWriter,
                    trackSymbol: function () {
                    }
                };
                function writeIndent() {
                    if (lineStart) {
                        var indentString = ts.getIndentString(indent);
                        if (indentString) {
                            displayParts.push(displayPart(indentString, 16));
                        }
                        lineStart = false;
                    }
                }
                function writeKind(text, kind) {
                    writeIndent();
                    displayParts.push(displayPart(text, kind));
                }
                function writeSymbol(text, symbol) {
                    writeIndent();
                    displayParts.push(symbolPart(text, symbol));
                }
                function writeLine() {
                    displayParts.push(lineBreakPart());
                    lineStart = true;
                }
                function resetWriter() {
                    displayParts = [];
                    lineStart = true;
                    indent = 0;
                }
            }
            function symbolPart(text, symbol) {
                return displayPart(text, displayPartKind(symbol), symbol);
                function displayPartKind(symbol) {
                    var flags = symbol.flags;
                    if (flags & 3) {
                        return isFirstDeclarationOfSymbolParameter(symbol) ? 13 : 9;
                    }
                    else if (flags & 4) {
                        return 14;
                    }
                    else if (flags & 32768) {
                        return 14;
                    }
                    else if (flags & 65536) {
                        return 14;
                    }
                    else if (flags & 8) {
                        return 19;
                    }
                    else if (flags & 16) {
                        return 20;
                    }
                    else if (flags & 32) {
                        return 1;
                    }
                    else if (flags & 64) {
                        return 4;
                    }
                    else if (flags & 384) {
                        return 2;
                    }
                    else if (flags & 1536) {
                        return 11;
                    }
                    else if (flags & 8192) {
                        return 10;
                    }
                    else if (flags & 262144) {
                        return 18;
                    }
                    else if (flags & 524288) {
                        return 0;
                    }
                    else if (flags & 8388608) {
                        return 0;
                    }
                    return 17;
                }
            }
            ts.symbolPart = symbolPart;
            function displayPart(text, kind, symbol) {
                return {
                    text: text,
                    kind: ts.SymbolDisplayPartKind[kind]
                };
            }
            ts.displayPart = displayPart;
            function spacePart() {
                return displayPart(" ", 16);
            }
            ts.spacePart = spacePart;
            function keywordPart(kind) {
                return displayPart(ts.tokenToString(kind), 5);
            }
            ts.keywordPart = keywordPart;
            function punctuationPart(kind) {
                return displayPart(ts.tokenToString(kind), 15);
            }
            ts.punctuationPart = punctuationPart;
            function operatorPart(kind) {
                return displayPart(ts.tokenToString(kind), 12);
            }
            ts.operatorPart = operatorPart;
            function textPart(text) {
                return displayPart(text, 17);
            }
            ts.textPart = textPart;
            function lineBreakPart() {
                return displayPart("\n", 6);
            }
            ts.lineBreakPart = lineBreakPart;
            function mapToDisplayParts(writeDisplayParts) {
                writeDisplayParts(displayPartWriter);
                var result = displayPartWriter.displayParts();
                displayPartWriter.clear();
                return result;
            }
            ts.mapToDisplayParts = mapToDisplayParts;
            function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) {
                return mapToDisplayParts(function (writer) {
                    typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                });
            }
            ts.typeToDisplayParts = typeToDisplayParts;
            function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) {
                return mapToDisplayParts(function (writer) {
                    typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
                });
            }
            ts.symbolToDisplayParts = symbolToDisplayParts;
            function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) {
                return mapToDisplayParts(function (writer) {
                    typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
                });
            }
            ts.signatureToDisplayParts = signatureToDisplayParts;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var scanner = ts.createScanner(2, false);
                var ScanAction;
                (function (ScanAction) {
                    ScanAction[ScanAction["Scan"] = 0] = "Scan";
                    ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken";
                    ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken";
                    ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken";
                })(ScanAction || (ScanAction = {}));
                function getFormattingScanner(sourceFile, startPos, endPos) {
                    scanner.setText(sourceFile.text);
                    scanner.setTextPos(startPos);
                    var wasNewLine = true;
                    var leadingTrivia;
                    var trailingTrivia;
                    var savedPos;
                    var lastScanAction;
                    var lastTokenInfo;
                    return {
                        advance: advance,
                        readTokenInfo: readTokenInfo,
                        isOnToken: isOnToken,
                        lastTrailingTriviaWasNewLine: function () {
                            return wasNewLine;
                        },
                        close: function () {
                            lastTokenInfo = undefined;
                            scanner.setText(undefined);
                        }
                    };
                    function advance() {
                        lastTokenInfo = undefined;
                        var isStarted = scanner.getStartPos() !== startPos;
                        if (isStarted) {
                            if (trailingTrivia) {
                                ts.Debug.assert(trailingTrivia.length !== 0);
                                wasNewLine = trailingTrivia[trailingTrivia.length - 1].kind === 4;
                            }
                            else {
                                wasNewLine = false;
                            }
                        }
                        leadingTrivia = undefined;
                        trailingTrivia = undefined;
                        if (!isStarted) {
                            scanner.scan();
                        }
                        var t;
                        var pos = scanner.getStartPos();
                        while (pos < endPos) {
                            var t = scanner.getToken();
                            if (!ts.isTrivia(t)) {
                                break;
                            }
                            scanner.scan();
                            var item = {
                                pos: pos,
                                end: scanner.getStartPos(),
                                kind: t
                            };
                            pos = scanner.getStartPos();
                            if (!leadingTrivia) {
                                leadingTrivia = [];
                            }
                            leadingTrivia.push(item);
                        }
                        savedPos = scanner.getStartPos();
                    }
                    function shouldRescanGreaterThanToken(node) {
                        if (node) {
                            switch (node.kind) {
                                case 27:
                                case 59:
                                case 60:
                                case 42:
                                case 41:
                                    return true;
                            }
                        }
                        return false;
                    }
                    function shouldRescanSlashToken(container) {
                        return container.kind === 9;
                    }
                    function shouldRescanTemplateToken(container) {
                        return container.kind === 12 || container.kind === 13;
                    }
                    function startsWithSlashToken(t) {
                        return t === 36 || t === 56;
                    }
                    function readTokenInfo(n) {
                        if (!isOnToken()) {
                            return {
                                leadingTrivia: leadingTrivia,
                                trailingTrivia: undefined,
                                token: undefined
                            };
                        }
                        var expectedScanAction = shouldRescanGreaterThanToken(n) ? 1 : shouldRescanSlashToken(n) ? 2 : shouldRescanTemplateToken(n) ? 3 : 0;
                        if (lastTokenInfo && expectedScanAction === lastScanAction) {
                            return fixTokenKind(lastTokenInfo, n);
                        }
                        if (scanner.getStartPos() !== savedPos) {
                            ts.Debug.assert(lastTokenInfo !== undefined);
                            scanner.setTextPos(savedPos);
                            scanner.scan();
                        }
                        var currentToken = scanner.getToken();
                        if (expectedScanAction === 1 && currentToken === 25) {
                            currentToken = scanner.reScanGreaterToken();
                            ts.Debug.assert(n.kind === currentToken);
                            lastScanAction = 1;
                        }
                        else if (expectedScanAction === 2 && startsWithSlashToken(currentToken)) {
                            currentToken = scanner.reScanSlashToken();
                            ts.Debug.assert(n.kind === currentToken);
                            lastScanAction = 2;
                        }
                        else if (expectedScanAction === 3 && currentToken === 15) {
                            currentToken = scanner.reScanTemplateToken();
                            lastScanAction = 3;
                        }
                        else {
                            lastScanAction = 0;
                        }
                        var token = {
                            pos: scanner.getStartPos(),
                            end: scanner.getTextPos(),
                            kind: currentToken
                        };
                        if (trailingTrivia) {
                            trailingTrivia = undefined;
                        }
                        while (scanner.getStartPos() < endPos) {
                            currentToken = scanner.scan();
                            if (!ts.isTrivia(currentToken)) {
                                break;
                            }
                            var trivia = {
                                pos: scanner.getStartPos(),
                                end: scanner.getTextPos(),
                                kind: currentToken
                            };
                            if (!trailingTrivia) {
                                trailingTrivia = [];
                            }
                            trailingTrivia.push(trivia);
                            if (currentToken === 4) {
                                scanner.scan();
                                break;
                            }
                        }
                        lastTokenInfo = {
                            leadingTrivia: leadingTrivia,
                            trailingTrivia: trailingTrivia,
                            token: token
                        };
                        return fixTokenKind(lastTokenInfo, n);
                    }
                    function isOnToken() {
                        var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
                        var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
                        return startPos < endPos && current !== 1 && !ts.isTrivia(current);
                    }
                    function fixTokenKind(tokenInfo, container) {
                        if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) {
                            tokenInfo.token.kind = container.kind;
                        }
                        return tokenInfo;
                    }
                }
                formatting.getFormattingScanner = getFormattingScanner;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var FormattingContext = (function () {
                    function FormattingContext(sourceFile, formattingRequestKind) {
                        this.sourceFile = sourceFile;
                        this.formattingRequestKind = formattingRequestKind;
                    }
                    FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) {
                        ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
                        ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
                        ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
                        ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
                        ts.Debug.assert(commonParent !== undefined, "commonParent is null");
                        this.currentTokenSpan = currentRange;
                        this.currentTokenParent = currentTokenParent;
                        this.nextTokenSpan = nextRange;
                        this.nextTokenParent = nextTokenParent;
                        this.contextNode = commonParent;
                        this.contextNodeAllOnSameLine = undefined;
                        this.nextNodeAllOnSameLine = undefined;
                        this.tokensAreOnSameLine = undefined;
                        this.contextNodeBlockIsOnOneLine = undefined;
                        this.nextNodeBlockIsOnOneLine = undefined;
                    };
                    FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
                        if (this.contextNodeAllOnSameLine === undefined) {
                            this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
                        }
                        return this.contextNodeAllOnSameLine;
                    };
                    FormattingContext.prototype.NextNodeAllOnSameLine = function () {
                        if (this.nextNodeAllOnSameLine === undefined) {
                            this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
                        }
                        return this.nextNodeAllOnSameLine;
                    };
                    FormattingContext.prototype.TokensAreOnSameLine = function () {
                        if (this.tokensAreOnSameLine === undefined) {
                            var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
                            var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
                            this.tokensAreOnSameLine = (startLine == endLine);
                        }
                        return this.tokensAreOnSameLine;
                    };
                    FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
                        if (this.contextNodeBlockIsOnOneLine === undefined) {
                            this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
                        }
                        return this.contextNodeBlockIsOnOneLine;
                    };
                    FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
                        if (this.nextNodeBlockIsOnOneLine === undefined) {
                            this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
                        }
                        return this.nextNodeBlockIsOnOneLine;
                    };
                    FormattingContext.prototype.NodeIsOnOneLine = function (node) {
                        var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
                        var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
                        return startLine == endLine;
                    };
                    FormattingContext.prototype.BlockIsOnOneLine = function (node) {
                        var openBrace = ts.findChildOfKind(node, 14, this.sourceFile);
                        var closeBrace = ts.findChildOfKind(node, 15, this.sourceFile);
                        if (openBrace && closeBrace) {
                            var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
                            var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
                            return startLine === endLine;
                        }
                        return false;
                    };
                    return FormattingContext;
                })();
                formatting.FormattingContext = FormattingContext;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (FormattingRequestKind) {
                    FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
                    FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
                    FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
                    FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
                    FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace";
                })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {}));
                var FormattingRequestKind = formatting.FormattingRequestKind;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Rule = (function () {
                    function Rule(Descriptor, Operation, Flag) {
                        if (Flag === void 0) { Flag = 0; }
                        this.Descriptor = Descriptor;
                        this.Operation = Operation;
                        this.Flag = Flag;
                    }
                    Rule.prototype.toString = function () {
                        return "[desc=" + this.Descriptor + "," + "operation=" + this.Operation + "," + "flag=" + this.Flag + "]";
                    };
                    return Rule;
                })();
                formatting.Rule = Rule;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (RuleAction) {
                    RuleAction[RuleAction["Ignore"] = 1] = "Ignore";
                    RuleAction[RuleAction["Space"] = 2] = "Space";
                    RuleAction[RuleAction["NewLine"] = 4] = "NewLine";
                    RuleAction[RuleAction["Delete"] = 8] = "Delete";
                })(formatting.RuleAction || (formatting.RuleAction = {}));
                var RuleAction = formatting.RuleAction;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleDescriptor = (function () {
                    function RuleDescriptor(LeftTokenRange, RightTokenRange) {
                        this.LeftTokenRange = LeftTokenRange;
                        this.RightTokenRange = RightTokenRange;
                    }
                    RuleDescriptor.prototype.toString = function () {
                        return "[leftRange=" + this.LeftTokenRange + "," + "rightRange=" + this.RightTokenRange + "]";
                    };
                    RuleDescriptor.create1 = function (left, right) {
                        return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right));
                    };
                    RuleDescriptor.create2 = function (left, right) {
                        return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right));
                    };
                    RuleDescriptor.create3 = function (left, right) {
                        return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right);
                    };
                    RuleDescriptor.create4 = function (left, right) {
                        return new RuleDescriptor(left, right);
                    };
                    return RuleDescriptor;
                })();
                formatting.RuleDescriptor = RuleDescriptor;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (RuleFlags) {
                    RuleFlags[RuleFlags["None"] = 0] = "None";
                    RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
                })(formatting.RuleFlags || (formatting.RuleFlags = {}));
                var RuleFlags = formatting.RuleFlags;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleOperation = (function () {
                    function RuleOperation() {
                        this.Context = null;
                        this.Action = null;
                    }
                    RuleOperation.prototype.toString = function () {
                        return "[context=" + this.Context + "," + "action=" + this.Action + "]";
                    };
                    RuleOperation.create1 = function (action) {
                        return RuleOperation.create2(formatting.RuleOperationContext.Any, action);
                    };
                    RuleOperation.create2 = function (context, action) {
                        var result = new RuleOperation();
                        result.Context = context;
                        result.Action = action;
                        return result;
                    };
                    return RuleOperation;
                })();
                formatting.RuleOperation = RuleOperation;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleOperationContext = (function () {
                    function RuleOperationContext() {
                        var funcs = [];
                        for (var _i = 0; _i < arguments.length; _i++) {
                            funcs[_i - 0] = arguments[_i];
                        }
                        this.customContextChecks = funcs;
                    }
                    RuleOperationContext.prototype.IsAny = function () {
                        return this == RuleOperationContext.Any;
                    };
                    RuleOperationContext.prototype.InContext = function (context) {
                        if (this.IsAny()) {
                            return true;
                        }
                        for (var i = 0, len = this.customContextChecks.length; i < len; i++) {
                            if (!this.customContextChecks[i](context)) {
                                return false;
                            }
                        }
                        return true;
                    };
                    RuleOperationContext.Any = new RuleOperationContext();
                    return RuleOperationContext;
                })();
                formatting.RuleOperationContext = RuleOperationContext;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Rules = (function () {
                    function Rules() {
                        this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1));
                        this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1));
                        this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 22), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 51), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
                        this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 50), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
                        this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(51, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 2));
                        this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), 2));
                        this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2));
                        this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(15, 75), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(15, 99), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15, formatting.Shared.TokenRange.FromTokens([
                            17,
                            19,
                            23,
                            22
                        ])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(20, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(18, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments;
                        this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
                        this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([
                            64,
                            3
                        ]);
                        this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
                        this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([
                            17,
                            3,
                            74,
                            95,
                            80,
                            75
                        ]);
                        this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
                        this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(14, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2));
                        this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2));
                        this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectContext), 8));
                        this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(14, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4));
                        this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4));
                        this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
                        this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(38, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(39, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 38), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 39), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(38, 33), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(33, 33), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(33, 38), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(39, 34), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(34, 34), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(34, 39), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([
                            97,
                            93,
                            87,
                            73,
                            89,
                            96
                        ]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([
                            104,
                            69
                        ]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2));
                        this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8));
                        this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(82, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
                        this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionDeclContext), 8));
                        this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(98, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), 2));
                        this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(89, 22), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([
                            17,
                            74,
                            75,
                            66
                        ]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), 2));
                        this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([
                            95,
                            80
                        ]), 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([
                            115,
                            119
                        ]), 64), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
                        this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(113, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([
                            116,
                            117
                        ]), 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([
                            68,
                            114,
                            76,
                            77,
                            78,
                            115,
                            102,
                            84,
                            103,
                            116,
                            106,
                            108,
                            119,
                            109
                        ]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([
                            78,
                            102
                        ])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(8, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2));
                        this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(32, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(21, 64), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.FromTokens([
                            17,
                            23
                        ])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
                        this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 24), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
                        this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(17, 24), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
                        this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(24, formatting.Shared.TokenRange.TypeNames), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
                        this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 25), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
                        this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25, formatting.Shared.TokenRange.FromTokens([
                            16,
                            18,
                            25,
                            23
                        ])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
                        this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), 8));
                        this.HighPriorityCommonRules = [
                            this.IgnoreBeforeComment,
                            this.IgnoreAfterLineComment,
                            this.NoSpaceBeforeColon,
                            this.SpaceAfterColon,
                            this.NoSpaceBeforeQuestionMark,
                            this.SpaceAfterQuestionMarkInConditionalOperator,
                            this.NoSpaceAfterQuestionMark,
                            this.NoSpaceBeforeDot,
                            this.NoSpaceAfterDot,
                            this.NoSpaceAfterUnaryPrefixOperator,
                            this.NoSpaceAfterUnaryPreincrementOperator,
                            this.NoSpaceAfterUnaryPredecrementOperator,
                            this.NoSpaceBeforeUnaryPostincrementOperator,
                            this.NoSpaceBeforeUnaryPostdecrementOperator,
                            this.SpaceAfterPostincrementWhenFollowedByAdd,
                            this.SpaceAfterAddWhenFollowedByUnaryPlus,
                            this.SpaceAfterAddWhenFollowedByPreincrement,
                            this.SpaceAfterPostdecrementWhenFollowedBySubtract,
                            this.SpaceAfterSubtractWhenFollowedByUnaryMinus,
                            this.SpaceAfterSubtractWhenFollowedByPredecrement,
                            this.NoSpaceAfterCloseBrace,
                            this.SpaceAfterOpenBrace,
                            this.SpaceBeforeCloseBrace,
                            this.NewLineBeforeCloseBraceInBlockContext,
                            this.SpaceAfterCloseBrace,
                            this.SpaceBetweenCloseBraceAndElse,
                            this.SpaceBetweenCloseBraceAndWhile,
                            this.NoSpaceBetweenEmptyBraceBrackets,
                            this.SpaceAfterFunctionInFuncDecl,
                            this.NewLineAfterOpenBraceInBlockContext,
                            this.SpaceAfterGetSetInMember,
                            this.NoSpaceBetweenReturnAndSemicolon,
                            this.SpaceAfterCertainKeywords,
                            this.SpaceAfterLetConstInVariableDeclaration,
                            this.NoSpaceBeforeOpenParenInFuncCall,
                            this.SpaceBeforeBinaryKeywordOperator,
                            this.SpaceAfterBinaryKeywordOperator,
                            this.SpaceAfterVoidOperator,
                            this.NoSpaceAfterConstructor,
                            this.NoSpaceAfterModuleImport,
                            this.SpaceAfterCertainTypeScriptKeywords,
                            this.SpaceBeforeCertainTypeScriptKeywords,
                            this.SpaceAfterModuleName,
                            this.SpaceAfterArrow,
                            this.NoSpaceAfterEllipsis,
                            this.NoSpaceAfterOptionalParameters,
                            this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
                            this.NoSpaceBeforeOpenAngularBracket,
                            this.NoSpaceBetweenCloseParenAndAngularBracket,
                            this.NoSpaceAfterOpenAngularBracket,
                            this.NoSpaceBeforeCloseAngularBracket,
                            this.NoSpaceAfterCloseAngularBracket
                        ];
                        this.LowPriorityCommonRules = [
                            this.NoSpaceBeforeSemicolon,
                            this.SpaceBeforeOpenBraceInControl,
                            this.SpaceBeforeOpenBraceInFunction,
                            this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
                            this.NoSpaceBeforeComma,
                            this.NoSpaceBeforeOpenBracket,
                            this.NoSpaceAfterOpenBracket,
                            this.NoSpaceBeforeCloseBracket,
                            this.NoSpaceAfterCloseBracket,
                            this.SpaceAfterSemicolon,
                            this.NoSpaceBeforeOpenParenInFuncDecl,
                            this.SpaceBetweenStatements,
                            this.SpaceAfterTryFinally
                        ];
                        this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
                        this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8));
                        this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8));
                        this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2));
                        this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8));
                        this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
                        this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
                        this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
                        this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 2));
                        this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 8));
                        this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
                        this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(16, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
                        this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(82, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
                        this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(82, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8));
                    }
                    Rules.prototype.getRuleName = function (rule) {
                        var o = this;
                        for (var name in o) {
                            if (o[name] === rule) {
                                return name;
                            }
                        }
                        throw new Error("Unknown rule");
                    };
                    Rules.IsForContext = function (context) {
                        return context.contextNode.kind === 181;
                    };
                    Rules.IsNotForContext = function (context) {
                        return !Rules.IsForContext(context);
                    };
                    Rules.IsBinaryOpContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 167:
                            case 168:
                                return true;
                            case 203:
                            case 193:
                            case 128:
                            case 220:
                            case 130:
                            case 129:
                                return context.currentTokenSpan.kind === 52 || context.nextTokenSpan.kind === 52;
                            case 182:
                                return context.currentTokenSpan.kind === 85 || context.nextTokenSpan.kind === 85;
                            case 183:
                                return context.currentTokenSpan.kind === 124 || context.nextTokenSpan.kind === 124;
                            case 150:
                                return context.currentTokenSpan.kind === 52 || context.nextTokenSpan.kind === 52;
                        }
                        return false;
                    };
                    Rules.IsNotBinaryOpContext = function (context) {
                        return !Rules.IsBinaryOpContext(context);
                    };
                    Rules.IsConditionalOperatorContext = function (context) {
                        return context.contextNode.kind === 168;
                    };
                    Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) {
                        return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context);
                    };
                    Rules.IsBeforeMultilineBlockContext = function (context) {
                        return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
                    };
                    Rules.IsMultilineBlockContext = function (context) {
                        return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                    };
                    Rules.IsSingleLineBlockContext = function (context) {
                        return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                    };
                    Rules.IsBlockContext = function (context) {
                        return Rules.NodeIsBlockContext(context.contextNode);
                    };
                    Rules.IsBeforeBlockContext = function (context) {
                        return Rules.NodeIsBlockContext(context.nextTokenParent);
                    };
                    Rules.NodeIsBlockContext = function (node) {
                        if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) {
                            return true;
                        }
                        switch (node.kind) {
                            case 174:
                            case 202:
                            case 152:
                            case 201:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsFunctionDeclContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 195:
                            case 132:
                            case 131:
                            case 134:
                            case 135:
                            case 136:
                            case 160:
                            case 133:
                            case 161:
                            case 197:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsTypeScriptDeclWithBlockContext = function (context) {
                        return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode);
                    };
                    Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) {
                        switch (node.kind) {
                            case 196:
                            case 197:
                            case 199:
                            case 143:
                            case 200:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsAfterCodeBlockContext = function (context) {
                        switch (context.currentTokenParent.kind) {
                            case 196:
                            case 200:
                            case 199:
                            case 174:
                            case 217:
                            case 201:
                            case 188:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsControlDeclContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 178:
                            case 188:
                            case 181:
                            case 182:
                            case 183:
                            case 180:
                            case 191:
                            case 179:
                            case 187:
                            case 217:
                                return true;
                            default:
                                return false;
                        }
                    };
                    Rules.IsObjectContext = function (context) {
                        return context.contextNode.kind === 152;
                    };
                    Rules.IsFunctionCallContext = function (context) {
                        return context.contextNode.kind === 155;
                    };
                    Rules.IsNewContext = function (context) {
                        return context.contextNode.kind === 156;
                    };
                    Rules.IsFunctionCallOrNewContext = function (context) {
                        return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context);
                    };
                    Rules.IsPreviousTokenNotComma = function (context) {
                        return context.currentTokenSpan.kind !== 23;
                    };
                    Rules.IsSameLineTokenContext = function (context) {
                        return context.TokensAreOnSameLine();
                    };
                    Rules.IsStartOfVariableDeclarationList = function (context) {
                        return context.currentTokenParent.kind === 194 && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
                    };
                    Rules.IsNotFormatOnEnter = function (context) {
                        return context.formattingRequestKind != 2;
                    };
                    Rules.IsModuleDeclContext = function (context) {
                        return context.contextNode.kind === 200;
                    };
                    Rules.IsObjectTypeContext = function (context) {
                        return context.contextNode.kind === 143;
                    };
                    Rules.IsTypeArgumentOrParameter = function (token, parent) {
                        if (token.kind !== 24 && token.kind !== 25) {
                            return false;
                        }
                        switch (parent.kind) {
                            case 139:
                            case 196:
                            case 197:
                            case 195:
                            case 160:
                            case 161:
                            case 132:
                            case 131:
                            case 136:
                            case 137:
                            case 155:
                            case 156:
                                return true;
                            default:
                                return false;
                        }
                    };
                    Rules.IsTypeArgumentOrParameterContext = function (context) {
                        return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) || Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent);
                    };
                    Rules.IsVoidOpContext = function (context) {
                        return context.currentTokenSpan.kind === 98 && context.currentTokenParent.kind === 164;
                    };
                    return Rules;
                })();
                formatting.Rules = Rules;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RulesMap = (function () {
                    function RulesMap() {
                        this.map = [];
                        this.mapRowLength = 0;
                    }
                    RulesMap.create = function (rules) {
                        var result = new RulesMap();
                        result.Initialize(rules);
                        return result;
                    };
                    RulesMap.prototype.Initialize = function (rules) {
                        this.mapRowLength = 124 + 1;
                        this.map = new Array(this.mapRowLength * this.mapRowLength);
                        var rulesBucketConstructionStateList = new Array(this.map.length);
                        this.FillRules(rules, rulesBucketConstructionStateList);
                        return this.map;
                    };
                    RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) {
                        var _this = this;
                        rules.forEach(function (rule) {
                            _this.FillRule(rule, rulesBucketConstructionStateList);
                        });
                    };
                    RulesMap.prototype.GetRuleBucketIndex = function (row, column) {
                        var rulesBucketIndex = (row * this.mapRowLength) + column;
                        return rulesBucketIndex;
                    };
                    RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) {
                        var _this = this;
                        var specificRule = rule.Descriptor.LeftTokenRange != formatting.Shared.TokenRange.Any && rule.Descriptor.RightTokenRange != formatting.Shared.TokenRange.Any;
                        rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) {
                            rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) {
                                var rulesBucketIndex = _this.GetRuleBucketIndex(left, right);
                                var rulesBucket = _this.map[rulesBucketIndex];
                                if (rulesBucket == undefined) {
                                    rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket();
                                }
                                rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex);
                            });
                        });
                    };
                    RulesMap.prototype.GetRule = function (context) {
                        var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
                        var bucket = this.map[bucketIndex];
                        if (bucket != null) {
                            for (var i = 0, len = bucket.Rules().length; i < len; i++) {
                                var rule = bucket.Rules()[i];
                                if (rule.Operation.Context.InContext(context))
                                    return rule;
                            }
                        }
                        return null;
                    };
                    return RulesMap;
                })();
                formatting.RulesMap = RulesMap;
                var MaskBitSize = 5;
                var Mask = 0x1f;
                (function (RulesPosition) {
                    RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific";
                    RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny";
                    RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific";
                    RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny";
                    RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific";
                    RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny";
                })(formatting.RulesPosition || (formatting.RulesPosition = {}));
                var RulesPosition = formatting.RulesPosition;
                var RulesBucketConstructionState = (function () {
                    function RulesBucketConstructionState() {
                        this.rulesInsertionIndexBitmap = 0;
                    }
                    RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) {
                        var index = 0;
                        var pos = 0;
                        var indexBitmap = this.rulesInsertionIndexBitmap;
                        while (pos <= maskPosition) {
                            index += (indexBitmap & Mask);
                            indexBitmap >>= MaskBitSize;
                            pos += MaskBitSize;
                        }
                        return index;
                    };
                    RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) {
                        var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
                        value++;
                        ts.Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
                        var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
                        temp |= value << maskPosition;
                        this.rulesInsertionIndexBitmap = temp;
                    };
                    return RulesBucketConstructionState;
                })();
                formatting.RulesBucketConstructionState = RulesBucketConstructionState;
                var RulesBucket = (function () {
                    function RulesBucket() {
                        this.rules = [];
                    }
                    RulesBucket.prototype.Rules = function () {
                        return this.rules;
                    };
                    RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) {
                        var position;
                        if (rule.Operation.Action == 1) {
                            position = specificTokens ? 0 : RulesPosition.IgnoreRulesAny;
                        }
                        else if (!rule.Operation.Context.IsAny()) {
                            position = specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny;
                        }
                        else {
                            position = specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny;
                        }
                        var state = constructionState[rulesBucketIndex];
                        if (state === undefined) {
                            state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
                        }
                        var index = state.GetInsertionIndex(position);
                        this.rules.splice(index, 0, rule);
                        state.IncreaseInsertionIndex(position);
                    };
                    return RulesBucket;
                })();
                formatting.RulesBucket = RulesBucket;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Shared;
                (function (Shared) {
                    var TokenRangeAccess = (function () {
                        function TokenRangeAccess(from, to, except) {
                            this.tokens = [];
                            for (var token = from; token <= to; token++) {
                                if (except.indexOf(token) < 0) {
                                    this.tokens.push(token);
                                }
                            }
                        }
                        TokenRangeAccess.prototype.GetTokens = function () {
                            return this.tokens;
                        };
                        TokenRangeAccess.prototype.Contains = function (token) {
                            return this.tokens.indexOf(token) >= 0;
                        };
                        return TokenRangeAccess;
                    })();
                    Shared.TokenRangeAccess = TokenRangeAccess;
                    var TokenValuesAccess = (function () {
                        function TokenValuesAccess(tks) {
                            this.tokens = tks && tks.length ? tks : [];
                        }
                        TokenValuesAccess.prototype.GetTokens = function () {
                            return this.tokens;
                        };
                        TokenValuesAccess.prototype.Contains = function (token) {
                            return this.tokens.indexOf(token) >= 0;
                        };
                        return TokenValuesAccess;
                    })();
                    Shared.TokenValuesAccess = TokenValuesAccess;
                    var TokenSingleValueAccess = (function () {
                        function TokenSingleValueAccess(token) {
                            this.token = token;
                        }
                        TokenSingleValueAccess.prototype.GetTokens = function () {
                            return [
                                this.token
                            ];
                        };
                        TokenSingleValueAccess.prototype.Contains = function (tokenValue) {
                            return tokenValue == this.token;
                        };
                        return TokenSingleValueAccess;
                    })();
                    Shared.TokenSingleValueAccess = TokenSingleValueAccess;
                    var TokenAllAccess = (function () {
                        function TokenAllAccess() {
                        }
                        TokenAllAccess.prototype.GetTokens = function () {
                            var result = [];
                            for (var token = 0; token <= 124; token++) {
                                result.push(token);
                            }
                            return result;
                        };
                        TokenAllAccess.prototype.Contains = function (tokenValue) {
                            return true;
                        };
                        TokenAllAccess.prototype.toString = function () {
                            return "[allTokens]";
                        };
                        return TokenAllAccess;
                    })();
                    Shared.TokenAllAccess = TokenAllAccess;
                    var TokenRange = (function () {
                        function TokenRange(tokenAccess) {
                            this.tokenAccess = tokenAccess;
                        }
                        TokenRange.FromToken = function (token) {
                            return new TokenRange(new TokenSingleValueAccess(token));
                        };
                        TokenRange.FromTokens = function (tokens) {
                            return new TokenRange(new TokenValuesAccess(tokens));
                        };
                        TokenRange.FromRange = function (f, to, except) {
                            if (except === void 0) { except = []; }
                            return new TokenRange(new TokenRangeAccess(f, to, except));
                        };
                        TokenRange.AllTokens = function () {
                            return new TokenRange(new TokenAllAccess());
                        };
                        TokenRange.prototype.GetTokens = function () {
                            return this.tokenAccess.GetTokens();
                        };
                        TokenRange.prototype.Contains = function (token) {
                            return this.tokenAccess.Contains(token);
                        };
                        TokenRange.prototype.toString = function () {
                            return this.tokenAccess.toString();
                        };
                        TokenRange.Any = TokenRange.AllTokens();
                        TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([
                            3
                        ]));
                        TokenRange.Keywords = TokenRange.FromRange(65, 124);
                        TokenRange.BinaryOperators = TokenRange.FromRange(24, 63);
                        TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([
                            85,
                            86,
                            124
                        ]);
                        TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([
                            38,
                            39,
                            47,
                            46
                        ]);
                        TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([
                            7,
                            64,
                            16,
                            18,
                            14,
                            92,
                            87
                        ]);
                        TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([
                            64,
                            16,
                            92,
                            87
                        ]);
                        TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([
                            64,
                            17,
                            19,
                            87
                        ]);
                        TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([
                            64,
                            16,
                            92,
                            87
                        ]);
                        TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([
                            64,
                            17,
                            19,
                            87
                        ]);
                        TokenRange.Comments = TokenRange.FromTokens([
                            2,
                            3
                        ]);
                        TokenRange.TypeNames = TokenRange.FromTokens([
                            64,
                            118,
                            120,
                            112,
                            121,
                            98,
                            111
                        ]);
                        return TokenRange;
                    })();
                    Shared.TokenRange = TokenRange;
                })(Shared = formatting.Shared || (formatting.Shared = {}));
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RulesProvider = (function () {
                    function RulesProvider() {
                        this.globalRules = new formatting.Rules();
                    }
                    RulesProvider.prototype.getRuleName = function (rule) {
                        return this.globalRules.getRuleName(rule);
                    };
                    RulesProvider.prototype.getRuleByName = function (name) {
                        return this.globalRules[name];
                    };
                    RulesProvider.prototype.getRulesMap = function () {
                        return this.rulesMap;
                    };
                    RulesProvider.prototype.ensureUpToDate = function (options) {
                        if (this.options == null || !ts.compareDataObjects(this.options, options)) {
                            var activeRules = this.createActiveRules(options);
                            var rulesMap = formatting.RulesMap.create(activeRules);
                            this.activeRules = activeRules;
                            this.rulesMap = rulesMap;
                            this.options = ts.clone(options);
                        }
                    };
                    RulesProvider.prototype.createActiveRules = function (options) {
                        var rules = this.globalRules.HighPriorityCommonRules.slice(0);
                        if (options.InsertSpaceAfterCommaDelimiter) {
                            rules.push(this.globalRules.SpaceAfterComma);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterComma);
                        }
                        if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
                            rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
                        }
                        if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
                            rules.push(this.globalRules.SpaceAfterKeywordInControl);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
                        }
                        if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
                            rules.push(this.globalRules.SpaceAfterOpenParen);
                            rules.push(this.globalRules.SpaceBeforeCloseParen);
                            rules.push(this.globalRules.NoSpaceBetweenParens);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterOpenParen);
                            rules.push(this.globalRules.NoSpaceBeforeCloseParen);
                            rules.push(this.globalRules.NoSpaceBetweenParens);
                        }
                        if (options.InsertSpaceAfterSemicolonInForStatements) {
                            rules.push(this.globalRules.SpaceAfterSemicolonInFor);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
                        }
                        if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
                            rules.push(this.globalRules.SpaceBeforeBinaryOperator);
                            rules.push(this.globalRules.SpaceAfterBinaryOperator);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceBeforeBinaryOperator);
                            rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
                        }
                        if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
                        }
                        if (options.PlaceOpenBraceOnNewLineForFunctions) {
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
                        }
                        rules = rules.concat(this.globalRules.LowPriorityCommonRules);
                        return rules;
                    };
                    return RulesProvider;
                })();
                formatting.RulesProvider = RulesProvider;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Constants;
                (function (Constants) {
                    Constants[Constants["Unknown"] = -1] = "Unknown";
                })(Constants || (Constants = {}));
                function formatOnEnter(position, sourceFile, rulesProvider, options) {
                    var line = sourceFile.getLineAndCharacterOfPosition(position).line;
                    if (line === 0) {
                        return [];
                    }
                    var span = {
                        pos: ts.getStartPositionOfLine(line - 1, sourceFile),
                        end: ts.getEndLinePosition(line, sourceFile) + 1
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 2);
                }
                formatting.formatOnEnter = formatOnEnter;
                function formatOnSemicolon(position, sourceFile, rulesProvider, options) {
                    return formatOutermostParent(position, 22, sourceFile, options, rulesProvider, 3);
                }
                formatting.formatOnSemicolon = formatOnSemicolon;
                function formatOnClosingCurly(position, sourceFile, rulesProvider, options) {
                    return formatOutermostParent(position, 15, sourceFile, options, rulesProvider, 4);
                }
                formatting.formatOnClosingCurly = formatOnClosingCurly;
                function formatDocument(sourceFile, rulesProvider, options) {
                    var span = {
                        pos: 0,
                        end: sourceFile.text.length
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 0);
                }
                formatting.formatDocument = formatDocument;
                function formatSelection(start, end, sourceFile, rulesProvider, options) {
                    var span = {
                        pos: ts.getLineStartPositionForPosition(start, sourceFile),
                        end: end
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 1);
                }
                formatting.formatSelection = formatSelection;
                function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) {
                    var parent = findOutermostParent(position, expectedLastToken, sourceFile);
                    if (!parent) {
                        return [];
                    }
                    var span = {
                        pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile),
                        end: parent.end
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, requestKind);
                }
                function findOutermostParent(position, expectedTokenKind, sourceFile) {
                    var precedingToken = ts.findPrecedingToken(position, sourceFile);
                    if (!precedingToken || precedingToken.kind !== expectedTokenKind || position !== precedingToken.getEnd()) {
                        return undefined;
                    }
                    var current = precedingToken;
                    while (current && current.parent && current.parent.end === precedingToken.end && !isListElement(current.parent, current)) {
                        current = current.parent;
                    }
                    return current;
                }
                function isListElement(parent, node) {
                    switch (parent.kind) {
                        case 196:
                        case 197:
                            return ts.rangeContainsRange(parent.members, node);
                        case 200:
                            var body = parent.body;
                            return body && body.kind === 174 && ts.rangeContainsRange(body.statements, node);
                        case 221:
                        case 174:
                        case 201:
                            return ts.rangeContainsRange(parent.statements, node);
                        case 217:
                            return ts.rangeContainsRange(parent.block.statements, node);
                    }
                    return false;
                }
                function findEnclosingNode(range, sourceFile) {
                    return find(sourceFile);
                    function find(n) {
                        var candidate = ts.forEachChild(n, function (c) {
                            return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c;
                        });
                        if (candidate) {
                            var result = find(candidate);
                            if (result) {
                                return result;
                            }
                        }
                        return n;
                    }
                }
                function prepareRangeContainsErrorFunction(errors, originalRange) {
                    if (!errors.length) {
                        return rangeHasNoErrors;
                    }
                    var sorted = errors.filter(function (d) {
                        return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length);
                    }).sort(function (e1, e2) {
                        return e1.start - e2.start;
                    });
                    if (!sorted.length) {
                        return rangeHasNoErrors;
                    }
                    var index = 0;
                    return function (r) {
                        while (true) {
                            if (index >= sorted.length) {
                                return false;
                            }
                            var error = sorted[index];
                            if (r.end <= error.start) {
                                return false;
                            }
                            if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
                                return true;
                            }
                            index++;
                        }
                    };
                    function rangeHasNoErrors(r) {
                        return false;
                    }
                }
                function getScanStartPosition(enclosingNode, originalRange, sourceFile) {
                    var start = enclosingNode.getStart(sourceFile);
                    if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
                        return start;
                    }
                    var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile);
                    if (!precedingToken) {
                        return enclosingNode.pos;
                    }
                    if (precedingToken.end >= originalRange.pos) {
                        return enclosingNode.pos;
                    }
                    return precedingToken.end;
                }
                function getOwnOrInheritedDelta(n, options, sourceFile) {
                    var previousLine = -1;
                    var childKind = 0;
                    while (n) {
                        var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
                        if (previousLine !== -1 && line !== previousLine) {
                            break;
                        }
                        if (formatting.SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
                            return options.IndentSize;
                        }
                        previousLine = line;
                        childKind = n.kind;
                        n = n.parent;
                    }
                    return 0;
                }
                function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) {
                    var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
                    var formattingContext = new formatting.FormattingContext(sourceFile, requestKind);
                    var enclosingNode = findEnclosingNode(originalRange, sourceFile);
                    var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
                    var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
                    var previousRangeHasError;
                    var previousRange;
                    var previousParent;
                    var previousRangeStartLine;
                    var edits = [];
                    formattingScanner.advance();
                    if (formattingScanner.isOnToken()) {
                        var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
                        var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
                        processNode(enclosingNode, enclosingNode, startLine, initialIndentation, delta);
                    }
                    formattingScanner.close();
                    return edits;
                    function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) {
                        if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos)) {
                            if (inheritedIndentation !== -1) {
                                return inheritedIndentation;
                            }
                        }
                        else {
                            var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
                            var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile);
                            var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
                            if (startLine !== parentStartLine || startPos === column) {
                                return column;
                            }
                        }
                        return -1;
                    }
                    function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) {
                        var indentation = inheritedIndentation;
                        if (indentation === -1) {
                            if (isSomeBlock(node.kind)) {
                                if (isSomeBlock(parent.kind) || parent.kind === 221 || parent.kind === 214 || parent.kind === 215) {
                                    indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
                                }
                                else {
                                    indentation = parentDynamicIndentation.getIndentation();
                                }
                            }
                            else {
                                if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
                                    indentation = parentDynamicIndentation.getIndentation();
                                }
                                else {
                                    indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
                                }
                            }
                        }
                        var delta = formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0) ? options.IndentSize : 0;
                        if (effectiveParentStartLine === startLine) {
                            indentation = parentDynamicIndentation.getIndentation();
                            delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
                        }
                        return {
                            indentation: indentation,
                            delta: delta
                        };
                    }
                    function getDynamicIndentation(node, nodeStartLine, indentation, delta) {
                        return {
                            getIndentationForComment: function (kind) {
                                switch (kind) {
                                    case 15:
                                    case 19:
                                        return indentation + delta;
                                }
                                return indentation;
                            },
                            getIndentationForToken: function (line, kind) {
                                switch (kind) {
                                    case 14:
                                    case 15:
                                    case 18:
                                    case 19:
                                    case 75:
                                    case 99:
                                        return indentation;
                                    default:
                                        return nodeStartLine !== line ? indentation + delta : indentation;
                                }
                            },
                            getIndentation: function () {
                                return indentation;
                            },
                            getDelta: function () {
                                return delta;
                            },
                            recomputeIndentation: function (lineAdded) {
                                if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
                                    if (lineAdded) {
                                        indentation += options.IndentSize;
                                    }
                                    else {
                                        indentation -= options.IndentSize;
                                    }
                                    if (formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0)) {
                                        delta = options.IndentSize;
                                    }
                                    else {
                                        delta = 0;
                                    }
                                }
                            }
                        };
                    }
                    function processNode(node, contextNode, nodeStartLine, indentation, delta) {
                        if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
                            return;
                        }
                        var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
                        var childContextNode = contextNode;
                        ts.forEachChild(node, function (child) {
                            processChildNode(child, -1, node, nodeDynamicIndentation, nodeStartLine, false);
                        }, function (nodes) {
                            processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
                        });
                        while (formattingScanner.isOnToken()) {
                            var tokenInfo = formattingScanner.readTokenInfo(node);
                            if (tokenInfo.token.end > node.end) {
                                break;
                            }
                            consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation);
                        }
                        function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, isListItem) {
                            var childStartPos = child.getStart(sourceFile);
                            var childStart = sourceFile.getLineAndCharacterOfPosition(childStartPos);
                            var childIndentationAmount = -1;
                            if (isListItem) {
                                childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
                                if (childIndentationAmount !== -1) {
                                    inheritedIndentation = childIndentationAmount;
                                }
                            }
                            if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
                                return inheritedIndentation;
                            }
                            if (child.getFullWidth() === 0) {
                                return inheritedIndentation;
                            }
                            while (formattingScanner.isOnToken()) {
                                var tokenInfo = formattingScanner.readTokenInfo(node);
                                if (tokenInfo.token.end > childStartPos) {
                                    break;
                                }
                                consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
                            }
                            if (!formattingScanner.isOnToken()) {
                                return inheritedIndentation;
                            }
                            if (ts.isToken(child)) {
                                var tokenInfo = formattingScanner.readTokenInfo(child);
                                ts.Debug.assert(tokenInfo.token.end === child.end);
                                consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
                                return inheritedIndentation;
                            }
                            var childIndentation = computeIndentation(child, childStart.line, childIndentationAmount, node, parentDynamicIndentation, parentStartLine);
                            processNode(child, childContextNode, childStart.line, childIndentation.indentation, childIndentation.delta);
                            childContextNode = node;
                            return inheritedIndentation;
                        }
                        function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) {
                            var listStartToken = getOpenTokenForList(parent, nodes);
                            var listEndToken = getCloseTokenForOpenToken(listStartToken);
                            var listDynamicIndentation = parentDynamicIndentation;
                            var startLine = parentStartLine;
                            if (listStartToken !== 0) {
                                while (formattingScanner.isOnToken()) {
                                    var tokenInfo = formattingScanner.readTokenInfo(parent);
                                    if (tokenInfo.token.end > nodes.pos) {
                                        break;
                                    }
                                    else if (tokenInfo.token.kind === listStartToken) {
                                        startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
                                        var indentation = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, startLine);
                                        listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation.indentation, indentation.delta);
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
                                    }
                                    else {
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation);
                                    }
                                }
                            }
                            var inheritedIndentation = -1;
                            for (var i = 0, len = nodes.length; i < len; ++i) {
                                inheritedIndentation = processChildNode(nodes[i], inheritedIndentation, node, listDynamicIndentation, startLine, true);
                            }
                            if (listEndToken !== 0) {
                                if (formattingScanner.isOnToken()) {
                                    var tokenInfo = formattingScanner.readTokenInfo(parent);
                                    if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) {
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
                                    }
                                }
                            }
                        }
                        function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation) {
                            ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token));
                            var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
                            var indentToken = false;
                            if (currentTokenInfo.leadingTrivia) {
                                processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
                            }
                            var lineAdded;
                            var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token);
                            var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
                            if (isTokenInRange) {
                                var rangeHasError = rangeContainsError(currentTokenInfo.token);
                                var prevStartLine = previousRangeStartLine;
                                lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
                                if (rangeHasError) {
                                    indentToken = false;
                                }
                                else {
                                    if (lineAdded !== undefined) {
                                        indentToken = lineAdded;
                                    }
                                    else {
                                        indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine;
                                    }
                                }
                            }
                            if (currentTokenInfo.trailingTrivia) {
                                processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
                            }
                            if (indentToken) {
                                var indentNextTokenOrTrivia = true;
                                if (currentTokenInfo.leadingTrivia) {
                                    for (var i = 0, len = currentTokenInfo.leadingTrivia.length; i < len; ++i) {
                                        var triviaItem = currentTokenInfo.leadingTrivia[i];
                                        if (!ts.rangeContainsRange(originalRange, triviaItem)) {
                                            continue;
                                        }
                                        var triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
                                        switch (triviaItem.kind) {
                                            case 3:
                                                var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
                                                indentMultilineComment(triviaItem, commentIndentation, !indentNextTokenOrTrivia);
                                                indentNextTokenOrTrivia = false;
                                                break;
                                            case 2:
                                                if (indentNextTokenOrTrivia) {
                                                    var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
                                                    insertIndentation(triviaItem.pos, commentIndentation, false);
                                                    indentNextTokenOrTrivia = false;
                                                }
                                                break;
                                            case 4:
                                                indentNextTokenOrTrivia = true;
                                                break;
                                        }
                                    }
                                }
                                if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
                                    var tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
                                    insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
                                }
                            }
                            formattingScanner.advance();
                            childContextNode = parent;
                        }
                    }
                    function processTrivia(trivia, parent, contextNode, dynamicIndentation) {
                        for (var i = 0, len = trivia.length; i < len; ++i) {
                            var triviaItem = trivia[i];
                            if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) {
                                var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
                                processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
                            }
                        }
                    }
                    function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) {
                        var rangeHasError = rangeContainsError(range);
                        var lineAdded;
                        if (!rangeHasError && !previousRangeHasError) {
                            if (!previousRange) {
                                var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
                                trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
                            }
                            else {
                                lineAdded = processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation);
                            }
                        }
                        previousRange = range;
                        previousParent = parent;
                        previousRangeStartLine = rangeStart.line;
                        previousRangeHasError = rangeHasError;
                        return lineAdded;
                    }
                    function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) {
                        formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
                        var rule = rulesProvider.getRulesMap().GetRule(formattingContext);
                        var trimTrailingWhitespaces;
                        var lineAdded;
                        if (rule) {
                            applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
                            if (rule.Operation.Action & (2 | 8) && currentStartLine !== previousStartLine) {
                                lineAdded = false;
                                if (currentParent.getStart(sourceFile) === currentItem.pos) {
                                    dynamicIndentation.recomputeIndentation(false);
                                }
                            }
                            else if (rule.Operation.Action & 4 && currentStartLine === previousStartLine) {
                                lineAdded = true;
                                if (currentParent.getStart(sourceFile) === currentItem.pos) {
                                    dynamicIndentation.recomputeIndentation(true);
                                }
                            }
                            trimTrailingWhitespaces = (rule.Operation.Action & (4 | 2)) && rule.Flag !== 1;
                        }
                        else {
                            trimTrailingWhitespaces = true;
                        }
                        if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
                            trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
                        }
                        return lineAdded;
                    }
                    function insertIndentation(pos, indentation, lineAdded) {
                        var indentationString = getIndentationString(indentation, options);
                        if (lineAdded) {
                            recordReplace(pos, 0, indentationString);
                        }
                        else {
                            var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
                            if (indentation !== tokenStart.character) {
                                var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile);
                                recordReplace(startLinePosition, tokenStart.character, indentationString);
                            }
                        }
                    }
                    function indentMultilineComment(commentRange, indentation, firstLineIsIndented) {
                        var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
                        var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
                        if (startLine === endLine) {
                            if (!firstLineIsIndented) {
                                insertIndentation(commentRange.pos, indentation, false);
                            }
                            return;
                        }
                        else {
                            var parts = [];
                            var startPos = commentRange.pos;
                            for (var line = startLine; line < endLine; ++line) {
                                var endOfLine = ts.getEndLinePosition(line, sourceFile);
                                parts.push({
                                    pos: startPos,
                                    end: endOfLine
                                });
                                startPos = ts.getStartPositionOfLine(line + 1, sourceFile);
                            }
                            parts.push({
                                pos: startPos,
                                end: commentRange.end
                            });
                        }
                        var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
                        var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
                        if (indentation === nonWhitespaceColumnInFirstPart.column) {
                            return;
                        }
                        var startIndex = 0;
                        if (firstLineIsIndented) {
                            startIndex = 1;
                            startLine++;
                        }
                        var delta = indentation - nonWhitespaceColumnInFirstPart.column;
                        for (var i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
                            var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
                            var nonWhitespaceCharacterAndColumn = i === 0 ? nonWhitespaceColumnInFirstPart : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
                            var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
                            if (newIndentation > 0) {
                                var indentationString = getIndentationString(newIndentation, options);
                                recordReplace(startLinePos, nonWhitespaceCharacterAndColumn.character, indentationString);
                            }
                            else {
                                recordDelete(startLinePos, nonWhitespaceCharacterAndColumn.character);
                            }
                        }
                    }
                    function trimTrailingWhitespacesForLines(line1, line2, range) {
                        for (var line = line1; line < line2; ++line) {
                            var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile);
                            var lineEndPosition = ts.getEndLinePosition(line, sourceFile);
                            if (range && ts.isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
                                continue;
                            }
                            var pos = lineEndPosition;
                            while (pos >= lineStartPosition && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
                                pos--;
                            }
                            if (pos !== lineEndPosition) {
                                ts.Debug.assert(pos === lineStartPosition || !ts.isWhiteSpace(sourceFile.text.charCodeAt(pos)));
                                recordDelete(pos + 1, lineEndPosition - pos);
                            }
                        }
                    }
                    function newTextChange(start, len, newText) {
                        return {
                            span: ts.createTextSpan(start, len),
                            newText: newText
                        };
                    }
                    function recordDelete(start, len) {
                        if (len) {
                            edits.push(newTextChange(start, len, ""));
                        }
                    }
                    function recordReplace(start, len, newText) {
                        if (len || newText) {
                            edits.push(newTextChange(start, len, newText));
                        }
                    }
                    function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) {
                        var between;
                        switch (rule.Operation.Action) {
                            case 1:
                                return;
                            case 8:
                                if (previousRange.end !== currentRange.pos) {
                                    recordDelete(previousRange.end, currentRange.pos - previousRange.end);
                                }
                                break;
                            case 4:
                                if (rule.Flag !== 1 && previousStartLine !== currentStartLine) {
                                    return;
                                }
                                var lineDelta = currentStartLine - previousStartLine;
                                if (lineDelta !== 1) {
                                    recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
                                }
                                break;
                            case 2:
                                if (rule.Flag !== 1 && previousStartLine !== currentStartLine) {
                                    return;
                                }
                                var posDelta = currentRange.pos - previousRange.end;
                                if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32) {
                                    recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
                                }
                                break;
                        }
                    }
                }
                function isSomeBlock(kind) {
                    switch (kind) {
                        case 174:
                        case 201:
                            return true;
                    }
                    return false;
                }
                function getOpenTokenForList(node, list) {
                    switch (node.kind) {
                        case 133:
                        case 195:
                        case 160:
                        case 132:
                        case 131:
                        case 161:
                            if (node.typeParameters === list) {
                                return 24;
                            }
                            else if (node.parameters === list) {
                                return 16;
                            }
                            break;
                        case 155:
                        case 156:
                            if (node.typeArguments === list) {
                                return 24;
                            }
                            else if (node.arguments === list) {
                                return 16;
                            }
                            break;
                        case 139:
                            if (node.typeArguments === list) {
                                return 24;
                            }
                    }
                    return 0;
                }
                function getCloseTokenForOpenToken(kind) {
                    switch (kind) {
                        case 16:
                            return 17;
                        case 24:
                            return 25;
                    }
                    return 0;
                }
                var internedTabsIndentation;
                var internedSpacesIndentation;
                function getIndentationString(indentation, options) {
                    if (!options.ConvertTabsToSpaces) {
                        var tabs = Math.floor(indentation / options.TabSize);
                        var spaces = indentation - tabs * options.TabSize;
                        var tabString;
                        if (!internedTabsIndentation) {
                            internedTabsIndentation = [];
                        }
                        if (internedTabsIndentation[tabs] === undefined) {
                            internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
                        }
                        else {
                            tabString = internedTabsIndentation[tabs];
                        }
                        return spaces ? tabString + repeat(" ", spaces) : tabString;
                    }
                    else {
                        var spacesString;
                        var quotient = Math.floor(indentation / options.IndentSize);
                        var remainder = indentation % options.IndentSize;
                        if (!internedSpacesIndentation) {
                            internedSpacesIndentation = [];
                        }
                        if (internedSpacesIndentation[quotient] === undefined) {
                            spacesString = repeat(" ", options.IndentSize * quotient);
                            internedSpacesIndentation[quotient] = spacesString;
                        }
                        else {
                            spacesString = internedSpacesIndentation[quotient];
                        }
                        return remainder ? spacesString + repeat(" ", remainder) : spacesString;
                    }
                    function repeat(value, count) {
                        var s = "";
                        for (var i = 0; i < count; ++i) {
                            s += value;
                        }
                        return s;
                    }
                }
                formatting.getIndentationString = getIndentationString;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var SmartIndenter;
                (function (SmartIndenter) {
                    var Value;
                    (function (Value) {
                        Value[Value["Unknown"] = -1] = "Unknown";
                    })(Value || (Value = {}));
                    function getIndentation(position, sourceFile, options) {
                        if (position > sourceFile.text.length) {
                            return 0;
                        }
                        var precedingToken = ts.findPrecedingToken(position, sourceFile);
                        if (!precedingToken) {
                            return 0;
                        }
                        var precedingTokenIsLiteral = precedingToken.kind === 8 || precedingToken.kind === 9 || precedingToken.kind === 10 || precedingToken.kind === 11 || precedingToken.kind === 12 || precedingToken.kind === 13;
                        if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) {
                            return 0;
                        }
                        var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
                        if (precedingToken.kind === 23 && precedingToken.parent.kind !== 167) {
                            var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
                            if (actualIndentation !== -1) {
                                return actualIndentation;
                            }
                        }
                        var previous;
                        var current = precedingToken;
                        var currentStart;
                        var indentationDelta;
                        while (current) {
                            if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : 0)) {
                                currentStart = getStartLineAndCharacterForNode(current, sourceFile);
                                if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
                                    indentationDelta = 0;
                                }
                                else {
                                    indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
                                }
                                break;
                            }
                            var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
                            if (actualIndentation !== -1) {
                                return actualIndentation;
                            }
                            previous = current;
                            current = current.parent;
                        }
                        if (!current) {
                            return 0;
                        }
                        return getIndentationForNodeWorker(current, currentStart, undefined, indentationDelta, sourceFile, options);
                    }
                    SmartIndenter.getIndentation = getIndentation;
                    function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) {
                        var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
                        return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, 0, sourceFile, options);
                    }
                    SmartIndenter.getIndentationForNode = getIndentationForNode;
                    function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) {
                        var parent = current.parent;
                        var parentStart;
                        while (parent) {
                            var useActualIndentation = true;
                            if (ignoreActualIndentationRange) {
                                var start = current.getStart(sourceFile);
                                useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
                            }
                            if (useActualIndentation) {
                                var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
                                if (actualIndentation !== -1) {
                                    return actualIndentation + indentationDelta;
                                }
                            }
                            parentStart = getParentStart(parent, current, sourceFile);
                            var parentAndChildShareLine = parentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
                            if (useActualIndentation) {
                                var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
                                if (actualIndentation !== -1) {
                                    return actualIndentation + indentationDelta;
                                }
                            }
                            if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
                                indentationDelta += options.IndentSize;
                            }
                            current = parent;
                            currentStart = parentStart;
                            parent = current.parent;
                        }
                        return indentationDelta;
                    }
                    function getParentStart(parent, child, sourceFile) {
                        var containingList = getContainingList(child, sourceFile);
                        if (containingList) {
                            return sourceFile.getLineAndCharacterOfPosition(containingList.pos);
                        }
                        return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile));
                    }
                    function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) {
                        var commaItemInfo = ts.findListItemInfo(commaToken);
                        if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
                            return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
                        }
                        else {
                            return -1;
                        }
                    }
                    function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) {
                        var useActualIndentation = (ts.isDeclaration(current) || ts.isStatement(current)) && (parent.kind === 221 || !parentAndChildShareLine);
                        if (!useActualIndentation) {
                            return -1;
                        }
                        return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
                    }
                    function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) {
                        var nextToken = ts.findNextToken(precedingToken, current);
                        if (!nextToken) {
                            return false;
                        }
                        if (nextToken.kind === 14) {
                            return true;
                        }
                        else if (nextToken.kind === 15) {
                            var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
                            return lineAtPosition === nextTokenStartLine;
                        }
                        return false;
                    }
                    function getStartLineAndCharacterForNode(n, sourceFile) {
                        return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
                    }
                    function positionBelongsToNode(candidate, position, sourceFile) {
                        return candidate.end > position || !isCompletedNode(candidate, sourceFile);
                    }
                    function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) {
                        if (parent.kind === 178 && parent.elseStatement === child) {
                            var elseKeyword = ts.findChildOfKind(parent, 75, sourceFile);
                            ts.Debug.assert(elseKeyword !== undefined);
                            var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
                            return elseKeywordStartLine === childStartLine;
                        }
                        return false;
                    }
                    SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement;
                    function getContainingList(node, sourceFile) {
                        if (node.parent) {
                            switch (node.parent.kind) {
                                case 139:
                                    if (node.parent.typeArguments && ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) {
                                        return node.parent.typeArguments;
                                    }
                                    break;
                                case 152:
                                    return node.parent.properties;
                                case 151:
                                    return node.parent.elements;
                                case 195:
                                case 160:
                                case 161:
                                case 132:
                                case 131:
                                case 136:
                                case 137:
                                    var start = node.getStart(sourceFile);
                                    if (node.parent.typeParameters && ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) {
                                        return node.parent.typeParameters;
                                    }
                                    if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) {
                                        return node.parent.parameters;
                                    }
                                    break;
                                case 156:
                                case 155:
                                    var start = node.getStart(sourceFile);
                                    if (node.parent.typeArguments && ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) {
                                        return node.parent.typeArguments;
                                    }
                                    if (node.parent.arguments && ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) {
                                        return node.parent.arguments;
                                    }
                                    break;
                            }
                        }
                        return undefined;
                    }
                    function getActualIndentationForListItem(node, sourceFile, options) {
                        var containingList = getContainingList(node, sourceFile);
                        return containingList ? getActualIndentationFromList(containingList) : -1;
                        function getActualIndentationFromList(list) {
                            var index = ts.indexOf(list, node);
                            return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1;
                        }
                    }
                    function deriveActualIndentationFromList(list, index, sourceFile, options) {
                        ts.Debug.assert(index >= 0 && index < list.length);
                        var node = list[index];
                        var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
                        for (var i = index - 1; i >= 0; --i) {
                            if (list[i].kind === 23) {
                                continue;
                            }
                            var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
                            if (prevEndLine !== lineAndCharacter.line) {
                                return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
                            }
                            lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
                        }
                        return -1;
                    }
                    function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) {
                        var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
                        return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
                    }
                    function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) {
                        var character = 0;
                        var column = 0;
                        for (var pos = startPos; pos < endPos; ++pos) {
                            var ch = sourceFile.text.charCodeAt(pos);
                            if (!ts.isWhiteSpace(ch)) {
                                break;
                            }
                            if (ch === 9) {
                                column += options.TabSize + (column % options.TabSize);
                            }
                            else {
                                column++;
                            }
                            character++;
                        }
                        return {
                            column: column,
                            character: character
                        };
                    }
                    SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn;
                    function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) {
                        return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
                    }
                    SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn;
                    function nodeContentIsAlwaysIndented(kind) {
                        switch (kind) {
                            case 196:
                            case 197:
                            case 199:
                            case 151:
                            case 174:
                            case 201:
                            case 152:
                            case 143:
                            case 202:
                            case 215:
                            case 214:
                            case 159:
                            case 155:
                            case 156:
                            case 175:
                            case 193:
                            case 209:
                            case 186:
                            case 168:
                                return true;
                        }
                        return false;
                    }
                    function shouldIndentChildNode(parent, child) {
                        if (nodeContentIsAlwaysIndented(parent)) {
                            return true;
                        }
                        switch (parent) {
                            case 179:
                            case 180:
                            case 182:
                            case 183:
                            case 181:
                            case 178:
                            case 195:
                            case 160:
                            case 132:
                            case 131:
                            case 161:
                            case 133:
                            case 134:
                            case 135:
                                return child !== 174;
                            default:
                                return false;
                        }
                    }
                    SmartIndenter.shouldIndentChildNode = shouldIndentChildNode;
                    function nodeEndsWith(n, expectedLastToken, sourceFile) {
                        var children = n.getChildren(sourceFile);
                        if (children.length) {
                            var last = children[children.length - 1];
                            if (last.kind === expectedLastToken) {
                                return true;
                            }
                            else if (last.kind === 22 && children.length !== 1) {
                                return children[children.length - 2].kind === expectedLastToken;
                            }
                        }
                        return false;
                    }
                    function isCompletedNode(n, sourceFile) {
                        if (n.getFullWidth() === 0) {
                            return false;
                        }
                        switch (n.kind) {
                            case 196:
                            case 197:
                            case 199:
                            case 152:
                            case 174:
                            case 201:
                            case 202:
                                return nodeEndsWith(n, 15, sourceFile);
                            case 217:
                                return isCompletedNode(n.block, sourceFile);
                            case 159:
                            case 136:
                            case 155:
                            case 137:
                                return nodeEndsWith(n, 17, sourceFile);
                            case 195:
                            case 160:
                            case 132:
                            case 131:
                            case 161:
                                return !n.body || isCompletedNode(n.body, sourceFile);
                            case 200:
                                return n.body && isCompletedNode(n.body, sourceFile);
                            case 178:
                                if (n.elseStatement) {
                                    return isCompletedNode(n.elseStatement, sourceFile);
                                }
                                return isCompletedNode(n.thenStatement, sourceFile);
                            case 177:
                                return isCompletedNode(n.expression, sourceFile);
                            case 151:
                                return nodeEndsWith(n, 19, sourceFile);
                            case 214:
                            case 215:
                                return false;
                            case 181:
                                return isCompletedNode(n.statement, sourceFile);
                            case 182:
                                return isCompletedNode(n.statement, sourceFile);
                            case 183:
                                return isCompletedNode(n.statement, sourceFile);
                            case 180:
                                return isCompletedNode(n.statement, sourceFile);
                            case 179:
                                var hasWhileKeyword = ts.findChildOfKind(n, 99, sourceFile);
                                if (hasWhileKeyword) {
                                    return nodeEndsWith(n, 17, sourceFile);
                                }
                                return isCompletedNode(n.statement, sourceFile);
                            default:
                                return true;
                        }
                    }
                })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {}));
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        var __extends = this.__extends || function (d, b) {
            for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            function __() { this.constructor = d; }
            __.prototype = b.prototype;
            d.prototype = new __();
        };
        var ts;
        (function (ts) {
            ts.servicesVersion = "0.4";
            var ScriptSnapshot;
            (function (ScriptSnapshot) {
                var StringScriptSnapshot = (function () {
                    function StringScriptSnapshot(text) {
                        this.text = text;
                        this._lineStartPositions = undefined;
                    }
                    StringScriptSnapshot.prototype.getText = function (start, end) {
                        return this.text.substring(start, end);
                    };
                    StringScriptSnapshot.prototype.getLength = function () {
                        return this.text.length;
                    };
                    StringScriptSnapshot.prototype.getChangeRange = function (oldSnapshot) {
                        return undefined;
                    };
                    return StringScriptSnapshot;
                })();
                function fromString(text) {
                    return new StringScriptSnapshot(text);
                }
                ScriptSnapshot.fromString = fromString;
            })(ScriptSnapshot = ts.ScriptSnapshot || (ts.ScriptSnapshot = {}));
            var scanner = ts.createScanner(2, true);
            var emptyArray = [];
            function createNode(kind, pos, end, flags, parent) {
                var node = new (ts.getNodeConstructor(kind))();
                node.pos = pos;
                node.end = end;
                node.flags = flags;
                node.parent = parent;
                return node;
            }
            var NodeObject = (function () {
                function NodeObject() {
                }
                NodeObject.prototype.getSourceFile = function () {
                    return ts.getSourceFileOfNode(this);
                };
                NodeObject.prototype.getStart = function (sourceFile) {
                    return ts.getTokenPosOfNode(this, sourceFile);
                };
                NodeObject.prototype.getFullStart = function () {
                    return this.pos;
                };
                NodeObject.prototype.getEnd = function () {
                    return this.end;
                };
                NodeObject.prototype.getWidth = function (sourceFile) {
                    return this.getEnd() - this.getStart(sourceFile);
                };
                NodeObject.prototype.getFullWidth = function () {
                    return this.end - this.getFullStart();
                };
                NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) {
                    return this.getStart(sourceFile) - this.pos;
                };
                NodeObject.prototype.getFullText = function (sourceFile) {
                    return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
                };
                NodeObject.prototype.getText = function (sourceFile) {
                    return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
                };
                NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end) {
                    scanner.setTextPos(pos);
                    while (pos < end) {
                        var token = scanner.scan();
                        var textPos = scanner.getTextPos();
                        nodes.push(createNode(token, pos, textPos, 1024, this));
                        pos = textPos;
                    }
                    return pos;
                };
                NodeObject.prototype.createSyntaxList = function (nodes) {
                    var list = createNode(222, nodes.pos, nodes.end, 1024, this);
                    list._children = [];
                    var pos = nodes.pos;
                    for (var i = 0, len = nodes.length; i < len; i++) {
                        var node = nodes[i];
                        if (pos < node.pos) {
                            pos = this.addSyntheticNodes(list._children, pos, node.pos);
                        }
                        list._children.push(node);
                        pos = node.end;
                    }
                    if (pos < nodes.end) {
                        this.addSyntheticNodes(list._children, pos, nodes.end);
                    }
                    return list;
                };
                NodeObject.prototype.createChildren = function (sourceFile) {
                    var _this = this;
                    if (this.kind >= 125) {
                        scanner.setText((sourceFile || this.getSourceFile()).text);
                        var children = [];
                        var pos = this.pos;
                        var processNode = function (node) {
                            if (pos < node.pos) {
                                pos = _this.addSyntheticNodes(children, pos, node.pos);
                            }
                            children.push(node);
                            pos = node.end;
                        };
                        var processNodes = function (nodes) {
                            if (pos < nodes.pos) {
                                pos = _this.addSyntheticNodes(children, pos, nodes.pos);
                            }
                            children.push(_this.createSyntaxList(nodes));
                            pos = nodes.end;
                        };
                        ts.forEachChild(this, processNode, processNodes);
                        if (pos < this.end) {
                            this.addSyntheticNodes(children, pos, this.end);
                        }
                        scanner.setText(undefined);
                    }
                    this._children = children || emptyArray;
                };
                NodeObject.prototype.getChildCount = function (sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children.length;
                };
                NodeObject.prototype.getChildAt = function (index, sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children[index];
                };
                NodeObject.prototype.getChildren = function (sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children;
                };
                NodeObject.prototype.getFirstToken = function (sourceFile) {
                    var children = this.getChildren();
                    for (var i = 0; i < children.length; i++) {
                        var child = children[i];
                        if (child.kind < 125) {
                            return child;
                        }
                        return child.getFirstToken(sourceFile);
                    }
                };
                NodeObject.prototype.getLastToken = function (sourceFile) {
                    var children = this.getChildren(sourceFile);
                    for (var i = children.length - 1; i >= 0; i--) {
                        var child = children[i];
                        if (child.kind < 125) {
                            return child;
                        }
                        return child.getLastToken(sourceFile);
                    }
                };
                return NodeObject;
            })();
            var SymbolObject = (function () {
                function SymbolObject(flags, name) {
                    this.flags = flags;
                    this.name = name;
                }
                SymbolObject.prototype.getFlags = function () {
                    return this.flags;
                };
                SymbolObject.prototype.getName = function () {
                    return this.name;
                };
                SymbolObject.prototype.getDeclarations = function () {
                    return this.declarations;
                };
                SymbolObject.prototype.getDocumentationComment = function () {
                    if (this.documentationComment === undefined) {
                        this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4));
                    }
                    return this.documentationComment;
                };
                return SymbolObject;
            })();
            function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) {
                var documentationComment = [];
                var docComments = getJsDocCommentsSeparatedByNewLines();
                ts.forEach(docComments, function (docComment) {
                    if (documentationComment.length) {
                        documentationComment.push(ts.lineBreakPart());
                    }
                    documentationComment.push(docComment);
                });
                return documentationComment;
                function getJsDocCommentsSeparatedByNewLines() {
                    var paramTag = "@param";
                    var jsDocCommentParts = [];
                    ts.forEach(declarations, function (declaration, indexOfDeclaration) {
                        if (ts.indexOf(declarations, declaration) === indexOfDeclaration) {
                            var sourceFileOfDeclaration = ts.getSourceFileOfNode(declaration);
                            if (canUseParsedParamTagComments && declaration.kind === 128) {
                                ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
                                    var cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
                                    if (cleanedParamJsDocComment) {
                                        jsDocCommentParts.push.apply(jsDocCommentParts, cleanedParamJsDocComment);
                                    }
                                });
                            }
                            if (declaration.kind === 200 && declaration.body.kind === 200) {
                                return;
                            }
                            while (declaration.kind === 200 && declaration.parent.kind === 200) {
                                declaration = declaration.parent;
                            }
                            ts.forEach(getJsDocCommentTextRange(declaration.kind === 193 ? declaration.parent.parent : declaration, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
                                var cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
                                if (cleanedJsDocComment) {
                                    jsDocCommentParts.push.apply(jsDocCommentParts, cleanedJsDocComment);
                                }
                            });
                        }
                    });
                    return jsDocCommentParts;
                    function getJsDocCommentTextRange(node, sourceFile) {
                        return ts.map(ts.getJsDocComments(node, sourceFile), function (jsDocComment) {
                            return {
                                pos: jsDocComment.pos + "/*".length,
                                end: jsDocComment.end - "*/".length
                            };
                        });
                    }
                    function consumeWhiteSpacesOnTheLine(pos, end, sourceFile, maxSpacesToRemove) {
                        if (maxSpacesToRemove !== undefined) {
                            end = Math.min(end, pos + maxSpacesToRemove);
                        }
                        for (; pos < end; pos++) {
                            var ch = sourceFile.text.charCodeAt(pos);
                            if (!ts.isWhiteSpace(ch) || ts.isLineBreak(ch)) {
                                return pos;
                            }
                        }
                        return end;
                    }
                    function consumeLineBreaks(pos, end, sourceFile) {
                        while (pos < end && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                            pos++;
                        }
                        return pos;
                    }
                    function isName(pos, end, sourceFile, name) {
                        return pos + name.length < end && sourceFile.text.substr(pos, name.length) === name && (ts.isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) || ts.isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
                    }
                    function isParamTag(pos, end, sourceFile) {
                        return isName(pos, end, sourceFile, paramTag);
                    }
                    function pushDocCommentLineText(docComments, text, blankLineCount) {
                        while (blankLineCount--)
                            docComments.push(ts.textPart(""));
                        docComments.push(ts.textPart(text));
                    }
                    function getCleanedJsDocComment(pos, end, sourceFile) {
                        var spacesToRemoveAfterAsterisk;
                        var docComments = [];
                        var blankLineCount = 0;
                        var isInParamTag = false;
                        while (pos < end) {
                            var docCommentTextOfLine = "";
                            pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile);
                            if (pos < end && sourceFile.text.charCodeAt(pos) === 42) {
                                var lineStartPos = pos + 1;
                                pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk);
                                if (spacesToRemoveAfterAsterisk === undefined && pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                                    spacesToRemoveAfterAsterisk = pos - lineStartPos;
                                }
                            }
                            else if (spacesToRemoveAfterAsterisk === undefined) {
                                spacesToRemoveAfterAsterisk = 0;
                            }
                            while (pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                                var ch = sourceFile.text.charAt(pos);
                                if (ch === "@") {
                                    if (isParamTag(pos, end, sourceFile)) {
                                        isInParamTag = true;
                                        pos += paramTag.length;
                                        continue;
                                    }
                                    else {
                                        isInParamTag = false;
                                    }
                                }
                                if (!isInParamTag) {
                                    docCommentTextOfLine += ch;
                                }
                                pos++;
                            }
                            pos = consumeLineBreaks(pos, end, sourceFile);
                            if (docCommentTextOfLine) {
                                pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
                                blankLineCount = 0;
                            }
                            else if (!isInParamTag && docComments.length) {
                                blankLineCount++;
                            }
                        }
                        return docComments;
                    }
                    function getCleanedParamJsDocComment(pos, end, sourceFile) {
                        var paramHelpStringMargin;
                        var paramDocComments = [];
                        while (pos < end) {
                            if (isParamTag(pos, end, sourceFile)) {
                                var blankLineCount = 0;
                                var recordedParamTag = false;
                                pos = consumeWhiteSpaces(pos + paramTag.length);
                                if (pos >= end) {
                                    break;
                                }
                                if (sourceFile.text.charCodeAt(pos) === 123) {
                                    pos++;
                                    for (var curlies = 1; pos < end; pos++) {
                                        var charCode = sourceFile.text.charCodeAt(pos);
                                        if (charCode === 123) {
                                            curlies++;
                                            continue;
                                        }
                                        if (charCode === 125) {
                                            curlies--;
                                            if (curlies === 0) {
                                                pos++;
                                                break;
                                            }
                                            else {
                                                continue;
                                            }
                                        }
                                        if (charCode === 64) {
                                            break;
                                        }
                                    }
                                    pos = consumeWhiteSpaces(pos);
                                    if (pos >= end) {
                                        break;
                                    }
                                }
                                if (isName(pos, end, sourceFile, name)) {
                                    pos = consumeWhiteSpaces(pos + name.length);
                                    if (pos >= end) {
                                        break;
                                    }
                                    var paramHelpString = "";
                                    var firstLineParamHelpStringPos = pos;
                                    while (pos < end) {
                                        var ch = sourceFile.text.charCodeAt(pos);
                                        if (ts.isLineBreak(ch)) {
                                            if (paramHelpString) {
                                                pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
                                                paramHelpString = "";
                                                blankLineCount = 0;
                                                recordedParamTag = true;
                                            }
                                            else if (recordedParamTag) {
                                                blankLineCount++;
                                            }
                                            setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos);
                                            continue;
                                        }
                                        if (ch === 64) {
                                            break;
                                        }
                                        paramHelpString += sourceFile.text.charAt(pos);
                                        pos++;
                                    }
                                    if (paramHelpString) {
                                        pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
                                    }
                                    paramHelpStringMargin = undefined;
                                }
                                if (sourceFile.text.charCodeAt(pos) === 64) {
                                    continue;
                                }
                            }
                            pos++;
                        }
                        return paramDocComments;
                        function consumeWhiteSpaces(pos) {
                            while (pos < end && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
                                pos++;
                            }
                            return pos;
                        }
                        function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos) {
                            pos = consumeLineBreaks(pos, end, sourceFile);
                            if (pos >= end) {
                                return;
                            }
                            if (paramHelpStringMargin === undefined) {
                                paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character;
                            }
                            var startOfLinePos = pos;
                            pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin);
                            if (pos >= end) {
                                return;
                            }
                            var consumedSpaces = pos - startOfLinePos;
                            if (consumedSpaces < paramHelpStringMargin) {
                                var ch = sourceFile.text.charCodeAt(pos);
                                if (ch === 42) {
                                    pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1);
                                }
                            }
                        }
                    }
                }
            }
            var TypeObject = (function () {
                function TypeObject(checker, flags) {
                    this.checker = checker;
                    this.flags = flags;
                }
                TypeObject.prototype.getFlags = function () {
                    return this.flags;
                };
                TypeObject.prototype.getSymbol = function () {
                    return this.symbol;
                };
                TypeObject.prototype.getProperties = function () {
                    return this.checker.getPropertiesOfType(this);
                };
                TypeObject.prototype.getProperty = function (propertyName) {
                    return this.checker.getPropertyOfType(this, propertyName);
                };
                TypeObject.prototype.getApparentProperties = function () {
                    return this.checker.getAugmentedPropertiesOfType(this);
                };
                TypeObject.prototype.getCallSignatures = function () {
                    return this.checker.getSignaturesOfType(this, 0);
                };
                TypeObject.prototype.getConstructSignatures = function () {
                    return this.checker.getSignaturesOfType(this, 1);
                };
                TypeObject.prototype.getStringIndexType = function () {
                    return this.checker.getIndexTypeOfType(this, 0);
                };
                TypeObject.prototype.getNumberIndexType = function () {
                    return this.checker.getIndexTypeOfType(this, 1);
                };
                return TypeObject;
            })();
            var SignatureObject = (function () {
                function SignatureObject(checker) {
                    this.checker = checker;
                }
                SignatureObject.prototype.getDeclaration = function () {
                    return this.declaration;
                };
                SignatureObject.prototype.getTypeParameters = function () {
                    return this.typeParameters;
                };
                SignatureObject.prototype.getParameters = function () {
                    return this.parameters;
                };
                SignatureObject.prototype.getReturnType = function () {
                    return this.checker.getReturnTypeOfSignature(this);
                };
                SignatureObject.prototype.getDocumentationComment = function () {
                    if (this.documentationComment === undefined) {
                        this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations([
                            this.declaration
                        ], undefined, false) : [];
                    }
                    return this.documentationComment;
                };
                return SignatureObject;
            })();
            var SourceFileObject = (function (_super) {
                __extends(SourceFileObject, _super);
                function SourceFileObject() {
                    _super.apply(this, arguments);
                }
                SourceFileObject.prototype.update = function (newText, textChangeRange) {
                    return ts.updateSourceFile(this, newText, textChangeRange);
                };
                SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) {
                    return ts.getLineAndCharacterOfPosition(this, position);
                };
                SourceFileObject.prototype.getLineStarts = function () {
                    return ts.getLineStarts(this);
                };
                SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) {
                    return ts.getPositionOfLineAndCharacter(this, line, character);
                };
                SourceFileObject.prototype.getNamedDeclarations = function () {
                    if (!this.namedDeclarations) {
                        var sourceFile = this;
                        var namedDeclarations = [];
                        ts.forEachChild(sourceFile, function visit(node) {
                            switch (node.kind) {
                                case 195:
                                case 132:
                                case 131:
                                    var functionDeclaration = node;
                                    if (functionDeclaration.name && functionDeclaration.name.getFullWidth() > 0) {
                                        var lastDeclaration = namedDeclarations.length > 0 ? namedDeclarations[namedDeclarations.length - 1] : undefined;
                                        if (lastDeclaration && functionDeclaration.symbol === lastDeclaration.symbol) {
                                            if (functionDeclaration.body && !lastDeclaration.body) {
                                                namedDeclarations[namedDeclarations.length - 1] = functionDeclaration;
                                            }
                                        }
                                        else {
                                            namedDeclarations.push(functionDeclaration);
                                        }
                                        ts.forEachChild(node, visit);
                                    }
                                    break;
                                case 196:
                                case 197:
                                case 198:
                                case 199:
                                case 200:
                                case 203:
                                case 212:
                                case 208:
                                case 203:
                                case 205:
                                case 206:
                                case 134:
                                case 135:
                                case 143:
                                    if (node.name) {
                                        namedDeclarations.push(node);
                                    }
                                case 133:
                                case 175:
                                case 194:
                                case 148:
                                case 149:
                                case 201:
                                    ts.forEachChild(node, visit);
                                    break;
                                case 174:
                                    if (ts.isFunctionBlock(node)) {
                                        ts.forEachChild(node, visit);
                                    }
                                    break;
                                case 128:
                                    if (!(node.flags & 112)) {
                                        break;
                                    }
                                case 193:
                                case 150:
                                    if (ts.isBindingPattern(node.name)) {
                                        ts.forEachChild(node.name, visit);
                                        break;
                                    }
                                case 220:
                                case 130:
                                case 129:
                                    namedDeclarations.push(node);
                                    break;
                                case 210:
                                    if (node.exportClause) {
                                        ts.forEach(node.exportClause.elements, visit);
                                    }
                                    break;
                                case 204:
                                    var importClause = node.importClause;
                                    if (importClause) {
                                        if (importClause.name) {
                                            namedDeclarations.push(importClause);
                                        }
                                        if (importClause.namedBindings) {
                                            if (importClause.namedBindings.kind === 206) {
                                                namedDeclarations.push(importClause.namedBindings);
                                            }
                                            else {
                                                ts.forEach(importClause.namedBindings.elements, visit);
                                            }
                                        }
                                    }
                                    break;
                            }
                        });
                        this.namedDeclarations = namedDeclarations;
                    }
                    return this.namedDeclarations;
                };
                return SourceFileObject;
            })(NodeObject);
            var TextChange = (function () {
                function TextChange() {
                }
                return TextChange;
            })();
            ts.TextChange = TextChange;
            (function (SymbolDisplayPartKind) {
                SymbolDisplayPartKind[SymbolDisplayPartKind["aliasName"] = 0] = "aliasName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["className"] = 1] = "className";
                SymbolDisplayPartKind[SymbolDisplayPartKind["enumName"] = 2] = "enumName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["fieldName"] = 3] = "fieldName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["interfaceName"] = 4] = "interfaceName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["keyword"] = 5] = "keyword";
                SymbolDisplayPartKind[SymbolDisplayPartKind["lineBreak"] = 6] = "lineBreak";
                SymbolDisplayPartKind[SymbolDisplayPartKind["numericLiteral"] = 7] = "numericLiteral";
                SymbolDisplayPartKind[SymbolDisplayPartKind["stringLiteral"] = 8] = "stringLiteral";
                SymbolDisplayPartKind[SymbolDisplayPartKind["localName"] = 9] = "localName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["methodName"] = 10] = "methodName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["moduleName"] = 11] = "moduleName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["operator"] = 12] = "operator";
                SymbolDisplayPartKind[SymbolDisplayPartKind["parameterName"] = 13] = "parameterName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["propertyName"] = 14] = "propertyName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["punctuation"] = 15] = "punctuation";
                SymbolDisplayPartKind[SymbolDisplayPartKind["space"] = 16] = "space";
                SymbolDisplayPartKind[SymbolDisplayPartKind["text"] = 17] = "text";
                SymbolDisplayPartKind[SymbolDisplayPartKind["typeParameterName"] = 18] = "typeParameterName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["enumMemberName"] = 19] = "enumMemberName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["functionName"] = 20] = "functionName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["regularExpressionLiteral"] = 21] = "regularExpressionLiteral";
            })(ts.SymbolDisplayPartKind || (ts.SymbolDisplayPartKind = {}));
            var SymbolDisplayPartKind = ts.SymbolDisplayPartKind;
            (function (OutputFileType) {
                OutputFileType[OutputFileType["JavaScript"] = 0] = "JavaScript";
                OutputFileType[OutputFileType["SourceMap"] = 1] = "SourceMap";
                OutputFileType[OutputFileType["Declaration"] = 2] = "Declaration";
            })(ts.OutputFileType || (ts.OutputFileType = {}));
            var OutputFileType = ts.OutputFileType;
            (function (EndOfLineState) {
                EndOfLineState[EndOfLineState["Start"] = 0] = "Start";
                EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia";
                EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral";
                EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral";
                EndOfLineState[EndOfLineState["InTemplateHeadOrNoSubstitutionTemplate"] = 4] = "InTemplateHeadOrNoSubstitutionTemplate";
                EndOfLineState[EndOfLineState["InTemplateMiddleOrTail"] = 5] = "InTemplateMiddleOrTail";
                EndOfLineState[EndOfLineState["InTemplateSubstitutionPosition"] = 6] = "InTemplateSubstitutionPosition";
            })(ts.EndOfLineState || (ts.EndOfLineState = {}));
            var EndOfLineState = ts.EndOfLineState;
            (function (TokenClass) {
                TokenClass[TokenClass["Punctuation"] = 0] = "Punctuation";
                TokenClass[TokenClass["Keyword"] = 1] = "Keyword";
                TokenClass[TokenClass["Operator"] = 2] = "Operator";
                TokenClass[TokenClass["Comment"] = 3] = "Comment";
                TokenClass[TokenClass["Whitespace"] = 4] = "Whitespace";
                TokenClass[TokenClass["Identifier"] = 5] = "Identifier";
                TokenClass[TokenClass["NumberLiteral"] = 6] = "NumberLiteral";
                TokenClass[TokenClass["StringLiteral"] = 7] = "StringLiteral";
                TokenClass[TokenClass["RegExpLiteral"] = 8] = "RegExpLiteral";
            })(ts.TokenClass || (ts.TokenClass = {}));
            var TokenClass = ts.TokenClass;
            var ScriptElementKind = (function () {
                function ScriptElementKind() {
                }
                ScriptElementKind.unknown = "";
                ScriptElementKind.keyword = "keyword";
                ScriptElementKind.scriptElement = "script";
                ScriptElementKind.moduleElement = "module";
                ScriptElementKind.classElement = "class";
                ScriptElementKind.interfaceElement = "interface";
                ScriptElementKind.typeElement = "type";
                ScriptElementKind.enumElement = "enum";
                ScriptElementKind.variableElement = "var";
                ScriptElementKind.localVariableElement = "local var";
                ScriptElementKind.functionElement = "function";
                ScriptElementKind.localFunctionElement = "local function";
                ScriptElementKind.memberFunctionElement = "method";
                ScriptElementKind.memberGetAccessorElement = "getter";
                ScriptElementKind.memberSetAccessorElement = "setter";
                ScriptElementKind.memberVariableElement = "property";
                ScriptElementKind.constructorImplementationElement = "constructor";
                ScriptElementKind.callSignatureElement = "call";
                ScriptElementKind.indexSignatureElement = "index";
                ScriptElementKind.constructSignatureElement = "construct";
                ScriptElementKind.parameterElement = "parameter";
                ScriptElementKind.typeParameterElement = "type parameter";
                ScriptElementKind.primitiveType = "primitive type";
                ScriptElementKind.label = "label";
                ScriptElementKind.alias = "alias";
                ScriptElementKind.constElement = "const";
                ScriptElementKind.letElement = "let";
                return ScriptElementKind;
            })();
            ts.ScriptElementKind = ScriptElementKind;
            var ScriptElementKindModifier = (function () {
                function ScriptElementKindModifier() {
                }
                ScriptElementKindModifier.none = "";
                ScriptElementKindModifier.publicMemberModifier = "public";
                ScriptElementKindModifier.privateMemberModifier = "private";
                ScriptElementKindModifier.protectedMemberModifier = "protected";
                ScriptElementKindModifier.exportedModifier = "export";
                ScriptElementKindModifier.ambientModifier = "declare";
                ScriptElementKindModifier.staticModifier = "static";
                return ScriptElementKindModifier;
            })();
            ts.ScriptElementKindModifier = ScriptElementKindModifier;
            var ClassificationTypeNames = (function () {
                function ClassificationTypeNames() {
                }
                ClassificationTypeNames.comment = "comment";
                ClassificationTypeNames.identifier = "identifier";
                ClassificationTypeNames.keyword = "keyword";
                ClassificationTypeNames.numericLiteral = "number";
                ClassificationTypeNames.operator = "operator";
                ClassificationTypeNames.stringLiteral = "string";
                ClassificationTypeNames.whiteSpace = "whitespace";
                ClassificationTypeNames.text = "text";
                ClassificationTypeNames.punctuation = "punctuation";
                ClassificationTypeNames.className = "class name";
                ClassificationTypeNames.enumName = "enum name";
                ClassificationTypeNames.interfaceName = "interface name";
                ClassificationTypeNames.moduleName = "module name";
                ClassificationTypeNames.typeParameterName = "type parameter name";
                ClassificationTypeNames.typeAlias = "type alias name";
                return ClassificationTypeNames;
            })();
            ts.ClassificationTypeNames = ClassificationTypeNames;
            function displayPartsToString(displayParts) {
                if (displayParts) {
                    return ts.map(displayParts, function (displayPart) {
                        return displayPart.text;
                    }).join("");
                }
                return "";
            }
            ts.displayPartsToString = displayPartsToString;
            function isLocalVariableOrFunction(symbol) {
                if (symbol.parent) {
                    return false;
                }
                return ts.forEach(symbol.declarations, function (declaration) {
                    if (declaration.kind === 160) {
                        return true;
                    }
                    if (declaration.kind !== 193 && declaration.kind !== 195) {
                        return false;
                    }
                    for (var parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) {
                        if (parent.kind === 221 || parent.kind === 201) {
                            return false;
                        }
                    }
                    return true;
                });
            }
            function getDefaultCompilerOptions() {
                return {
                    target: 1,
                    module: 0
                };
            }
            ts.getDefaultCompilerOptions = getDefaultCompilerOptions;
            var OperationCanceledException = (function () {
                function OperationCanceledException() {
                }
                return OperationCanceledException;
            })();
            ts.OperationCanceledException = OperationCanceledException;
            var CancellationTokenObject = (function () {
                function CancellationTokenObject(cancellationToken) {
                    this.cancellationToken = cancellationToken;
                }
                CancellationTokenObject.prototype.isCancellationRequested = function () {
                    return this.cancellationToken && this.cancellationToken.isCancellationRequested();
                };
                CancellationTokenObject.prototype.throwIfCancellationRequested = function () {
                    if (this.isCancellationRequested()) {
                        throw new OperationCanceledException();
                    }
                };
                CancellationTokenObject.None = new CancellationTokenObject(null);
                return CancellationTokenObject;
            })();
            ts.CancellationTokenObject = CancellationTokenObject;
            var HostCache = (function () {
                function HostCache(host) {
                    this.host = host;
                    this.fileNameToEntry = {};
                    var rootFileNames = host.getScriptFileNames();
                    for (var i = 0, n = rootFileNames.length; i < n; i++) {
                        this.createEntry(rootFileNames[i]);
                    }
                    this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
                }
                HostCache.prototype.compilationSettings = function () {
                    return this._compilationSettings;
                };
                HostCache.prototype.createEntry = function (fileName) {
                    var entry;
                    var scriptSnapshot = this.host.getScriptSnapshot(fileName);
                    if (scriptSnapshot) {
                        entry = {
                            hostFileName: fileName,
                            version: this.host.getScriptVersion(fileName),
                            scriptSnapshot: scriptSnapshot
                        };
                    }
                    return this.fileNameToEntry[ts.normalizeSlashes(fileName)] = entry;
                };
                HostCache.prototype.getEntry = function (fileName) {
                    return ts.lookUp(this.fileNameToEntry, ts.normalizeSlashes(fileName));
                };
                HostCache.prototype.contains = function (fileName) {
                    return ts.hasProperty(this.fileNameToEntry, ts.normalizeSlashes(fileName));
                };
                HostCache.prototype.getOrCreateEntry = function (fileName) {
                    if (this.contains(fileName)) {
                        return this.getEntry(fileName);
                    }
                    return this.createEntry(fileName);
                };
                HostCache.prototype.getRootFileNames = function () {
                    var _this = this;
                    var fileNames = [];
                    ts.forEachKey(this.fileNameToEntry, function (key) {
                        if (ts.hasProperty(_this.fileNameToEntry, key) && _this.fileNameToEntry[key])
                            fileNames.push(key);
                    });
                    return fileNames;
                };
                HostCache.prototype.getVersion = function (fileName) {
                    var file = this.getEntry(fileName);
                    return file && file.version;
                };
                HostCache.prototype.getScriptSnapshot = function (fileName) {
                    var file = this.getEntry(fileName);
                    return file && file.scriptSnapshot;
                };
                return HostCache;
            })();
            var SyntaxTreeCache = (function () {
                function SyntaxTreeCache(host) {
                    this.host = host;
                }
                SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) {
                    var scriptSnapshot = this.host.getScriptSnapshot(fileName);
                    if (!scriptSnapshot) {
                        throw new Error("Could not find file: '" + fileName + "'.");
                    }
                    var version = this.host.getScriptVersion(fileName);
                    var sourceFile;
                    if (this.currentFileName !== fileName) {
                        sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2, version, true);
                    }
                    else if (this.currentFileVersion !== version) {
                        var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
                        sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
                    }
                    if (sourceFile) {
                        this.currentFileVersion = version;
                        this.currentFileName = fileName;
                        this.currentFileScriptSnapshot = scriptSnapshot;
                        this.currentSourceFile = sourceFile;
                    }
                    return this.currentSourceFile;
                };
                return SyntaxTreeCache;
            })();
            function setSourceFileFields(sourceFile, scriptSnapshot, version) {
                sourceFile.version = version;
                sourceFile.scriptSnapshot = scriptSnapshot;
            }
            function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) {
                var sourceFile = ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), scriptTarget, setNodeParents);
                setSourceFileFields(sourceFile, scriptSnapshot, version);
                sourceFile.nameTable = sourceFile.identifiers;
                return sourceFile;
            }
            ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile;
            ts.disableIncrementalParsing = false;
            function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) {
                if (textChangeRange) {
                    if (version !== sourceFile.version) {
                        if (!ts.disableIncrementalParsing) {
                            var newSourceFile = ts.updateSourceFile(sourceFile, scriptSnapshot.getText(0, scriptSnapshot.getLength()), textChangeRange, aggressiveChecks);
                            setSourceFileFields(newSourceFile, scriptSnapshot, version);
                            newSourceFile.nameTable = undefined;
                            return newSourceFile;
                        }
                    }
                }
                return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true);
            }
            ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile;
            function createDocumentRegistry() {
                var buckets = {};
                function getKeyFromCompilationSettings(settings) {
                    return "_" + settings.target;
                }
                function getBucketForCompilationSettings(settings, createIfMissing) {
                    var key = getKeyFromCompilationSettings(settings);
                    var bucket = ts.lookUp(buckets, key);
                    if (!bucket && createIfMissing) {
                        buckets[key] = bucket = {};
                    }
                    return bucket;
                }
                function reportStats() {
                    var bucketInfoArray = Object.keys(buckets).filter(function (name) {
                        return name && name.charAt(0) === '_';
                    }).map(function (name) {
                        var entries = ts.lookUp(buckets, name);
                        var sourceFiles = [];
                        for (var i in entries) {
                            var entry = entries[i];
                            sourceFiles.push({
                                name: i,
                                refCount: entry.languageServiceRefCount,
                                references: entry.owners.slice(0)
                            });
                        }
                        sourceFiles.sort(function (x, y) {
                            return y.refCount - x.refCount;
                        });
                        return {
                            bucket: name,
                            sourceFiles: sourceFiles
                        };
                    });
                    return JSON.stringify(bucketInfoArray, null, 2);
                }
                function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) {
                    return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, true);
                }
                function updateDocument(fileName, compilationSettings, scriptSnapshot, version) {
                    return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, false);
                }
                function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) {
                    var bucket = getBucketForCompilationSettings(compilationSettings, true);
                    var entry = ts.lookUp(bucket, fileName);
                    if (!entry) {
                        ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
                        var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, false);
                        bucket[fileName] = entry = {
                            sourceFile: sourceFile,
                            languageServiceRefCount: 0,
                            owners: []
                        };
                    }
                    else {
                        if (entry.sourceFile.version !== version) {
                            entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
                        }
                    }
                    if (acquiring) {
                        entry.languageServiceRefCount++;
                    }
                    return entry.sourceFile;
                }
                function releaseDocument(fileName, compilationSettings) {
                    var bucket = getBucketForCompilationSettings(compilationSettings, false);
                    ts.Debug.assert(bucket !== undefined);
                    var entry = ts.lookUp(bucket, fileName);
                    entry.languageServiceRefCount--;
                    ts.Debug.assert(entry.languageServiceRefCount >= 0);
                    if (entry.languageServiceRefCount === 0) {
                        delete bucket[fileName];
                    }
                }
                return {
                    acquireDocument: acquireDocument,
                    updateDocument: updateDocument,
                    releaseDocument: releaseDocument,
                    reportStats: reportStats
                };
            }
            ts.createDocumentRegistry = createDocumentRegistry;
            function preProcessFile(sourceText, readImportFiles) {
                if (readImportFiles === void 0) { readImportFiles = true; }
                var referencedFiles = [];
                var importedFiles = [];
                var isNoDefaultLib = false;
                function processTripleSlashDirectives() {
                    var commentRanges = ts.getLeadingCommentRanges(sourceText, 0);
                    ts.forEach(commentRanges, function (commentRange) {
                        var comment = sourceText.substring(commentRange.pos, commentRange.end);
                        var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, commentRange);
                        if (referencePathMatchResult) {
                            isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
                            var fileReference = referencePathMatchResult.fileReference;
                            if (fileReference) {
                                referencedFiles.push(fileReference);
                            }
                        }
                    });
                }
                function recordModuleName() {
                    var importPath = scanner.getTokenValue();
                    var pos = scanner.getTokenPos();
                    importedFiles.push({
                        fileName: importPath,
                        pos: pos,
                        end: pos + importPath.length
                    });
                }
                function processImport() {
                    scanner.setText(sourceText);
                    var token = scanner.scan();
                    while (token !== 1) {
                        if (token === 84) {
                            token = scanner.scan();
                            if (token === 8) {
                                recordModuleName();
                                continue;
                            }
                            else {
                                if (token === 64) {
                                    token = scanner.scan();
                                    if (token === 123) {
                                        token = scanner.scan();
                                        if (token === 8) {
                                            recordModuleName();
                                            continue;
                                        }
                                    }
                                    else if (token === 52) {
                                        token = scanner.scan();
                                        if (token === 117) {
                                            token = scanner.scan();
                                            if (token === 16) {
                                                token = scanner.scan();
                                                if (token === 8) {
                                                    recordModuleName();
                                                    continue;
                                                }
                                            }
                                        }
                                    }
                                    else if (token === 23) {
                                        token = scanner.scan();
                                    }
                                    else {
                                        continue;
                                    }
                                }
                                if (token === 14) {
                                    token = scanner.scan();
                                    while (token !== 15) {
                                        token = scanner.scan();
                                    }
                                    if (token === 15) {
                                        token = scanner.scan();
                                        if (token === 123) {
                                            token = scanner.scan();
                                            if (token === 8) {
                                                recordModuleName();
                                            }
                                        }
                                    }
                                }
                                else if (token === 35) {
                                    token = scanner.scan();
                                    if (token === 101) {
                                        token = scanner.scan();
                                        if (token === 64) {
                                            token = scanner.scan();
                                            if (token === 123) {
                                                token = scanner.scan();
                                                if (token === 8) {
                                                    recordModuleName();
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else if (token === 77) {
                            token = scanner.scan();
                            if (token === 14) {
                                token = scanner.scan();
                                while (token !== 15) {
                                    token = scanner.scan();
                                }
                                if (token === 15) {
                                    token = scanner.scan();
                                    if (token === 123) {
                                        token = scanner.scan();
                                        if (token === 8) {
                                            recordModuleName();
                                        }
                                    }
                                }
                            }
                            else if (token === 35) {
                                token = scanner.scan();
                                if (token === 123) {
                                    token = scanner.scan();
                                    if (token === 8) {
                                        recordModuleName();
                                    }
                                }
                            }
                        }
                        token = scanner.scan();
                    }
                    scanner.setText(undefined);
                }
                if (readImportFiles) {
                    processImport();
                }
                processTripleSlashDirectives();
                return {
                    referencedFiles: referencedFiles,
                    importedFiles: importedFiles,
                    isLibFile: isNoDefaultLib
                };
            }
            ts.preProcessFile = preProcessFile;
            function getTargetLabel(referenceNode, labelName) {
                while (referenceNode) {
                    if (referenceNode.kind === 189 && referenceNode.label.text === labelName) {
                        return referenceNode.label;
                    }
                    referenceNode = referenceNode.parent;
                }
                return undefined;
            }
            function isJumpStatementTarget(node) {
                return node.kind === 64 && (node.parent.kind === 185 || node.parent.kind === 184) && node.parent.label === node;
            }
            function isLabelOfLabeledStatement(node) {
                return node.kind === 64 && node.parent.kind === 189 && node.parent.label === node;
            }
            function isLabeledBy(node, labelName) {
                for (var owner = node.parent; owner.kind === 189; owner = owner.parent) {
                    if (owner.label.text === labelName) {
                        return true;
                    }
                }
                return false;
            }
            function isLabelName(node) {
                return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node);
            }
            function isRightSideOfQualifiedName(node) {
                return node.parent.kind === 125 && node.parent.right === node;
            }
            function isRightSideOfPropertyAccess(node) {
                return node && node.parent && node.parent.kind === 153 && node.parent.name === node;
            }
            function isCallExpressionTarget(node) {
                if (isRightSideOfPropertyAccess(node)) {
                    node = node.parent;
                }
                return node && node.parent && node.parent.kind === 155 && node.parent.expression === node;
            }
            function isNewExpressionTarget(node) {
                if (isRightSideOfPropertyAccess(node)) {
                    node = node.parent;
                }
                return node && node.parent && node.parent.kind === 156 && node.parent.expression === node;
            }
            function isNameOfModuleDeclaration(node) {
                return node.parent.kind === 200 && node.parent.name === node;
            }
            function isNameOfFunctionDeclaration(node) {
                return node.kind === 64 && ts.isFunctionLike(node.parent) && node.parent.name === node;
            }
            function isNameOfPropertyAssignment(node) {
                return (node.kind === 64 || node.kind === 8 || node.kind === 7) && (node.parent.kind === 218 || node.parent.kind === 219) && node.parent.name === node;
            }
            function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) {
                if (node.kind === 8 || node.kind === 7) {
                    switch (node.parent.kind) {
                        case 130:
                        case 129:
                        case 218:
                        case 220:
                        case 132:
                        case 131:
                        case 134:
                        case 135:
                        case 200:
                            return node.parent.name === node;
                        case 154:
                            return node.parent.argumentExpression === node;
                    }
                }
                return false;
            }
            function isNameOfExternalModuleImportOrDeclaration(node) {
                if (node.kind === 8) {
                    return isNameOfModuleDeclaration(node) || (ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node);
                }
                return false;
            }
            function isInsideComment(sourceFile, token, position) {
                return position <= token.getStart(sourceFile) && (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart())));
                function isInsideCommentRange(comments) {
                    return ts.forEach(comments, function (comment) {
                        if (comment.pos < position && position < comment.end) {
                            return true;
                        }
                        else if (position === comment.end) {
                            var text = sourceFile.text;
                            var width = comment.end - comment.pos;
                            if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47) {
                                return true;
                            }
                            else {
                                return !(text.charCodeAt(comment.end - 1) === 47 && text.charCodeAt(comment.end - 2) === 42);
                            }
                        }
                        return false;
                    });
                }
            }
            var SemanticMeaning;
            (function (SemanticMeaning) {
                SemanticMeaning[SemanticMeaning["None"] = 0] = "None";
                SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value";
                SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type";
                SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace";
                SemanticMeaning[SemanticMeaning["All"] = 7] = "All";
            })(SemanticMeaning || (SemanticMeaning = {}));
            var BreakContinueSearchType;
            (function (BreakContinueSearchType) {
                BreakContinueSearchType[BreakContinueSearchType["None"] = 0] = "None";
                BreakContinueSearchType[BreakContinueSearchType["Unlabeled"] = 1] = "Unlabeled";
                BreakContinueSearchType[BreakContinueSearchType["Labeled"] = 2] = "Labeled";
                BreakContinueSearchType[BreakContinueSearchType["All"] = 3] = "All";
            })(BreakContinueSearchType || (BreakContinueSearchType = {}));
            var keywordCompletions = [];
            for (var i = 65; i <= 124; i++) {
                keywordCompletions.push({
                    name: ts.tokenToString(i),
                    kind: ScriptElementKind.keyword,
                    kindModifiers: ScriptElementKindModifier.none
                });
            }
            function getContainerNode(node) {
                while (true) {
                    node = node.parent;
                    if (!node) {
                        return undefined;
                    }
                    switch (node.kind) {
                        case 221:
                        case 132:
                        case 131:
                        case 195:
                        case 160:
                        case 134:
                        case 135:
                        case 196:
                        case 197:
                        case 199:
                        case 200:
                            return node;
                    }
                }
            }
            ts.getContainerNode = getContainerNode;
            function getNodeKind(node) {
                switch (node.kind) {
                    case 200:
                        return ScriptElementKind.moduleElement;
                    case 196:
                        return ScriptElementKind.classElement;
                    case 197:
                        return ScriptElementKind.interfaceElement;
                    case 198:
                        return ScriptElementKind.typeElement;
                    case 199:
                        return ScriptElementKind.enumElement;
                    case 193:
                        return ts.isConst(node) ? ScriptElementKind.constElement : ts.isLet(node) ? ScriptElementKind.letElement : ScriptElementKind.variableElement;
                    case 195:
                        return ScriptElementKind.functionElement;
                    case 134:
                        return ScriptElementKind.memberGetAccessorElement;
                    case 135:
                        return ScriptElementKind.memberSetAccessorElement;
                    case 132:
                    case 131:
                        return ScriptElementKind.memberFunctionElement;
                    case 130:
                    case 129:
                        return ScriptElementKind.memberVariableElement;
                    case 138:
                        return ScriptElementKind.indexSignatureElement;
                    case 137:
                        return ScriptElementKind.constructSignatureElement;
                    case 136:
                        return ScriptElementKind.callSignatureElement;
                    case 133:
                        return ScriptElementKind.constructorImplementationElement;
                    case 127:
                        return ScriptElementKind.typeParameterElement;
                    case 220:
                        return ScriptElementKind.variableElement;
                    case 128:
                        return (node.flags & 112) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
                    case 203:
                    case 208:
                    case 205:
                    case 212:
                    case 206:
                        return ScriptElementKind.alias;
                }
                return ScriptElementKind.unknown;
            }
            ts.getNodeKind = getNodeKind;
            function createLanguageService(host, documentRegistry) {
                if (documentRegistry === void 0) { documentRegistry = createDocumentRegistry(); }
                var syntaxTreeCache = new SyntaxTreeCache(host);
                var ruleProvider;
                var program;
                var typeInfoResolver;
                var useCaseSensitivefileNames = false;
                var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
                var activeCompletionSession;
                if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
                    ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
                }
                function log(message) {
                    if (host.log) {
                        host.log(message);
                    }
                }
                function getCanonicalFileName(fileName) {
                    return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
                }
                function getValidSourceFile(fileName) {
                    fileName = ts.normalizeSlashes(fileName);
                    var sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
                    if (!sourceFile) {
                        throw new Error("Could not find file: '" + fileName + "'.");
                    }
                    return sourceFile;
                }
                function getRuleProvider(options) {
                    if (!ruleProvider) {
                        ruleProvider = new ts.formatting.RulesProvider();
                    }
                    ruleProvider.ensureUpToDate(options);
                    return ruleProvider;
                }
                function synchronizeHostData() {
                    var hostCache = new HostCache(host);
                    if (programUpToDate()) {
                        return;
                    }
                    var oldSettings = program && program.getCompilerOptions();
                    var newSettings = hostCache.compilationSettings();
                    var changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target;
                    var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, {
                        getSourceFile: getOrCreateSourceFile,
                        getCancellationToken: function () {
                            return cancellationToken;
                        },
                        getCanonicalFileName: function (fileName) {
                            return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
                        },
                        useCaseSensitiveFileNames: function () {
                            return useCaseSensitivefileNames;
                        },
                        getNewLine: function () {
                            return host.getNewLine ? host.getNewLine() : "\r\n";
                        },
                        getDefaultLibFileName: function (options) {
                            return host.getDefaultLibFileName(options);
                        },
                        writeFile: function (fileName, data, writeByteOrderMark) {
                        },
                        getCurrentDirectory: function () {
                            return host.getCurrentDirectory();
                        }
                    });
                    if (program) {
                        var oldSourceFiles = program.getSourceFiles();
                        for (var i = 0, n = oldSourceFiles.length; i < n; i++) {
                            var fileName = oldSourceFiles[i].fileName;
                            if (!newProgram.getSourceFile(fileName) || changesInCompilationSettingsAffectSyntax) {
                                documentRegistry.releaseDocument(fileName, oldSettings);
                            }
                        }
                    }
                    program = newProgram;
                    typeInfoResolver = program.getTypeChecker();
                    return;
                    function getOrCreateSourceFile(fileName) {
                        var hostFileInformation = hostCache.getOrCreateEntry(fileName);
                        if (!hostFileInformation) {
                            return undefined;
                        }
                        if (!changesInCompilationSettingsAffectSyntax) {
                            var oldSourceFile = program && program.getSourceFile(fileName);
                            if (oldSourceFile) {
                                return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
                            }
                        }
                        return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
                    }
                    function sourceFileUpToDate(sourceFile) {
                        return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.fileName);
                    }
                    function programUpToDate() {
                        if (!program) {
                            return false;
                        }
                        var rootFileNames = hostCache.getRootFileNames();
                        if (program.getSourceFiles().length !== rootFileNames.length) {
                            return false;
                        }
                        for (var i = 0, n = rootFileNames.length; i < n; i++) {
                            if (!sourceFileUpToDate(program.getSourceFile(rootFileNames[i]))) {
                                return false;
                            }
                        }
                        return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
                    }
                }
                function getProgram() {
                    synchronizeHostData();
                    return program;
                }
                function cleanupSemanticCache() {
                    if (program) {
                        typeInfoResolver = program.getTypeChecker();
                    }
                }
                function dispose() {
                    if (program) {
                        ts.forEach(program.getSourceFiles(), function (f) {
                            return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions());
                        });
                    }
                }
                function getSyntacticDiagnostics(fileName) {
                    synchronizeHostData();
                    return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
                }
                function getSemanticDiagnostics(fileName) {
                    synchronizeHostData();
                    var targetSourceFile = getValidSourceFile(fileName);
                    var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile);
                    if (!program.getCompilerOptions().declaration) {
                        return semanticDiagnostics;
                    }
                    var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile);
                    return semanticDiagnostics.concat(declarationDiagnostics);
                }
                function getCompilerOptionsDiagnostics() {
                    synchronizeHostData();
                    return program.getGlobalDiagnostics();
                }
                function getValidCompletionEntryDisplayName(symbol, target) {
                    var displayName = symbol.getName();
                    if (displayName && displayName.length > 0) {
                        var firstCharCode = displayName.charCodeAt(0);
                        if ((symbol.flags & 1536) && (firstCharCode === 39 || firstCharCode === 34)) {
                            return undefined;
                        }
                        if (displayName && displayName.length >= 2 && firstCharCode === displayName.charCodeAt(displayName.length - 1) && (firstCharCode === 39 || firstCharCode === 34)) {
                            displayName = displayName.substring(1, displayName.length - 1);
                        }
                        var isValid = ts.isIdentifierStart(displayName.charCodeAt(0), target);
                        for (var i = 1, n = displayName.length; isValid && i < n; i++) {
                            isValid = ts.isIdentifierPart(displayName.charCodeAt(i), target);
                        }
                        if (isValid) {
                            return ts.unescapeIdentifier(displayName);
                        }
                    }
                    return undefined;
                }
                function createCompletionEntry(symbol, typeChecker, location) {
                    var displayName = getValidCompletionEntryDisplayName(symbol, program.getCompilerOptions().target);
                    if (!displayName) {
                        return undefined;
                    }
                    return {
                        name: displayName,
                        kind: getSymbolKind(symbol, typeChecker, location),
                        kindModifiers: getSymbolModifiers(symbol)
                    };
                }
                function getCompletionsAtPosition(fileName, position) {
                    synchronizeHostData();
                    var syntacticStart = new Date().getTime();
                    var sourceFile = getValidSourceFile(fileName);
                    var start = new Date().getTime();
                    var currentToken = ts.getTokenAtPosition(sourceFile, position);
                    log("getCompletionsAtPosition: Get current token: " + (new Date().getTime() - start));
                    var start = new Date().getTime();
                    var insideComment = isInsideComment(sourceFile, currentToken, position);
                    log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
                    if (insideComment) {
                        log("Returning an empty list because completion was inside a comment.");
                        return undefined;
                    }
                    var start = new Date().getTime();
                    var previousToken = ts.findPrecedingToken(position, sourceFile);
                    log("getCompletionsAtPosition: Get previous token 1: " + (new Date().getTime() - start));
                    if (previousToken && position <= previousToken.end && previousToken.kind === 64) {
                        var start = new Date().getTime();
                        previousToken = ts.findPrecedingToken(previousToken.pos, sourceFile);
                        log("getCompletionsAtPosition: Get previous token 2: " + (new Date().getTime() - start));
                    }
                    if (previousToken && isCompletionListBlocker(previousToken)) {
                        log("Returning an empty list because completion was requested in an invalid position.");
                        return undefined;
                    }
                    var node;
                    var isRightOfDot;
                    if (previousToken && previousToken.kind === 20 && previousToken.parent.kind === 153) {
                        node = previousToken.parent.expression;
                        isRightOfDot = true;
                    }
                    else if (previousToken && previousToken.kind === 20 && previousToken.parent.kind === 125) {
                        node = previousToken.parent.left;
                        isRightOfDot = true;
                    }
                    else {
                        node = currentToken;
                        isRightOfDot = false;
                    }
                    activeCompletionSession = {
                        fileName: fileName,
                        position: position,
                        entries: [],
                        symbols: {},
                        typeChecker: typeInfoResolver
                    };
                    log("getCompletionsAtPosition: Syntactic work: " + (new Date().getTime() - syntacticStart));
                    var location = ts.getTouchingPropertyName(sourceFile, position);
                    var semanticStart = new Date().getTime();
                    if (isRightOfDot) {
                        var symbols = [];
                        var isMemberCompletion = true;
                        var isNewIdentifierLocation = false;
                        if (node.kind === 64 || node.kind === 125 || node.kind === 153) {
                            var symbol = typeInfoResolver.getSymbolAtLocation(node);
                            if (symbol && symbol.flags & 8388608) {
                                symbol = typeInfoResolver.getAliasedSymbol(symbol);
                            }
                            if (symbol && symbol.flags & 1952) {
                                ts.forEachValue(symbol.exports, function (symbol) {
                                    if (typeInfoResolver.isValidPropertyAccess((node.parent), symbol.name)) {
                                        symbols.push(symbol);
                                    }
                                });
                            }
                        }
                        var type = typeInfoResolver.getTypeAtLocation(node);
                        if (type) {
                            ts.forEach(type.getApparentProperties(), function (symbol) {
                                if (typeInfoResolver.isValidPropertyAccess((node.parent), symbol.name)) {
                                    symbols.push(symbol);
                                }
                            });
                        }
                        getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
                    }
                    else {
                        var containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(previousToken);
                        if (containingObjectLiteral) {
                            isMemberCompletion = true;
                            isNewIdentifierLocation = true;
                            var contextualType = typeInfoResolver.getContextualType(containingObjectLiteral);
                            if (!contextualType) {
                                return undefined;
                            }
                            var contextualTypeMembers = typeInfoResolver.getPropertiesOfType(contextualType);
                            if (contextualTypeMembers && contextualTypeMembers.length > 0) {
                                var filteredMembers = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
                                getCompletionEntriesFromSymbols(filteredMembers, activeCompletionSession);
                            }
                        }
                        else if (ts.getAncestor(previousToken, 205)) {
                            isMemberCompletion = true;
                            isNewIdentifierLocation = true;
                            if (showCompletionsInImportsClause(previousToken)) {
                                var importDeclaration = ts.getAncestor(previousToken, 204);
                                ts.Debug.assert(importDeclaration !== undefined);
                                var exports = typeInfoResolver.getExportsOfExternalModule(importDeclaration);
                                var filteredExports = filterModuleExports(exports, importDeclaration);
                                getCompletionEntriesFromSymbols(filteredExports, activeCompletionSession);
                            }
                        }
                        else {
                            isMemberCompletion = false;
                            isNewIdentifierLocation = isNewIdentifierDefinitionLocation(previousToken);
                            var symbolMeanings = 793056 | 107455 | 1536 | 8388608;
                            var symbols = typeInfoResolver.getSymbolsInScope(node, symbolMeanings);
                            getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
                        }
                    }
                    if (!isMemberCompletion) {
                        Array.prototype.push.apply(activeCompletionSession.entries, keywordCompletions);
                    }
                    log("getCompletionsAtPosition: Semantic work: " + (new Date().getTime() - semanticStart));
                    return {
                        isMemberCompletion: isMemberCompletion,
                        isNewIdentifierLocation: isNewIdentifierLocation,
                        isBuilder: isNewIdentifierDefinitionLocation,
                        entries: activeCompletionSession.entries
                    };
                    function getCompletionEntriesFromSymbols(symbols, session) {
                        var start = new Date().getTime();
                        ts.forEach(symbols, function (symbol) {
                            var entry = createCompletionEntry(symbol, session.typeChecker, location);
                            if (entry) {
                                var id = ts.escapeIdentifier(entry.name);
                                if (!ts.lookUp(session.symbols, id)) {
                                    session.entries.push(entry);
                                    session.symbols[id] = symbol;
                                }
                            }
                        });
                        log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
                    }
                    function isCompletionListBlocker(previousToken) {
                        var start = new Date().getTime();
                        var result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) || isIdentifierDefinitionLocation(previousToken) || isRightOfIllegalDot(previousToken);
                        log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
                        return result;
                    }
                    function showCompletionsInImportsClause(node) {
                        if (node) {
                            if (node.kind === 14 || node.kind === 23) {
                                return node.parent.kind === 207;
                            }
                        }
                        return false;
                    }
                    function isNewIdentifierDefinitionLocation(previousToken) {
                        if (previousToken) {
                            var containingNodeKind = previousToken.parent.kind;
                            switch (previousToken.kind) {
                                case 23:
                                    return containingNodeKind === 155 || containingNodeKind === 133 || containingNodeKind === 156 || containingNodeKind === 151 || containingNodeKind === 167;
                                case 16:
                                    return containingNodeKind === 155 || containingNodeKind === 133 || containingNodeKind === 156 || containingNodeKind === 159;
                                case 18:
                                    return containingNodeKind === 151;
                                case 116:
                                    return true;
                                case 20:
                                    return containingNodeKind === 200;
                                case 14:
                                    return containingNodeKind === 196;
                                case 52:
                                    return containingNodeKind === 193 || containingNodeKind === 167;
                                case 11:
                                    return containingNodeKind === 169;
                                case 12:
                                    return containingNodeKind === 173;
                                case 108:
                                case 106:
                                case 107:
                                    return containingNodeKind === 130;
                            }
                            switch (previousToken.getText()) {
                                case "public":
                                case "protected":
                                case "private":
                                    return true;
                            }
                        }
                        return false;
                    }
                    function isInStringOrRegularExpressionOrTemplateLiteral(previousToken) {
                        if (previousToken.kind === 8 || previousToken.kind === 9 || ts.isTemplateLiteralKind(previousToken.kind)) {
                            var start = previousToken.getStart();
                            var end = previousToken.getEnd();
                            if (start < position && position < end) {
                                return true;
                            }
                            else if (position === end) {
                                return !!previousToken.isUnterminated;
                            }
                        }
                        return false;
                    }
                    function getContainingObjectLiteralApplicableForCompletion(previousToken) {
                        if (previousToken) {
                            var parent = previousToken.parent;
                            switch (previousToken.kind) {
                                case 14:
                                case 23:
                                    if (parent && parent.kind === 152) {
                                        return parent;
                                    }
                                    break;
                            }
                        }
                        return undefined;
                    }
                    function isFunction(kind) {
                        switch (kind) {
                            case 160:
                            case 161:
                            case 195:
                            case 132:
                            case 131:
                            case 134:
                            case 135:
                            case 136:
                            case 137:
                            case 138:
                                return true;
                        }
                        return false;
                    }
                    function isIdentifierDefinitionLocation(previousToken) {
                        if (previousToken) {
                            var containingNodeKind = previousToken.parent.kind;
                            switch (previousToken.kind) {
                                case 23:
                                    return containingNodeKind === 193 || containingNodeKind === 194 || containingNodeKind === 175 || containingNodeKind === 199 || isFunction(containingNodeKind) || containingNodeKind === 196 || containingNodeKind === 195 || containingNodeKind === 197 || containingNodeKind === 149 || containingNodeKind === 148;
                                case 20:
                                    return containingNodeKind === 149;
                                case 18:
                                    return containingNodeKind === 149;
                                case 16:
                                    return containingNodeKind === 217 || isFunction(containingNodeKind);
                                case 14:
                                    return containingNodeKind === 199 || containingNodeKind === 197 || containingNodeKind === 143 || containingNodeKind === 148;
                                case 22:
                                    return containingNodeKind === 129 && (previousToken.parent.parent.kind === 197 || previousToken.parent.parent.kind === 143);
                                case 24:
                                    return containingNodeKind === 196 || containingNodeKind === 195 || containingNodeKind === 197 || isFunction(containingNodeKind);
                                case 109:
                                    return containingNodeKind === 130;
                                case 21:
                                    return containingNodeKind === 128 || containingNodeKind === 133 || (previousToken.parent.parent.kind === 149);
                                case 108:
                                case 106:
                                case 107:
                                    return containingNodeKind === 128;
                                case 68:
                                case 76:
                                case 103:
                                case 82:
                                case 97:
                                case 115:
                                case 119:
                                case 84:
                                case 104:
                                case 69:
                                case 110:
                                    return true;
                            }
                            switch (previousToken.getText()) {
                                case "class":
                                case "interface":
                                case "enum":
                                case "function":
                                case "var":
                                case "static":
                                case "let":
                                case "const":
                                case "yield":
                                    return true;
                            }
                        }
                        return false;
                    }
                    function isRightOfIllegalDot(previousToken) {
                        if (previousToken && previousToken.kind === 7) {
                            var text = previousToken.getFullText();
                            return text.charAt(text.length - 1) === ".";
                        }
                        return false;
                    }
                    function filterModuleExports(exports, importDeclaration) {
                        var exisingImports = {};
                        if (!importDeclaration.importClause) {
                            return exports;
                        }
                        if (importDeclaration.importClause.namedBindings && importDeclaration.importClause.namedBindings.kind === 207) {
                            ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) {
                                var name = el.propertyName || el.name;
                                exisingImports[name.text] = true;
                            });
                        }
                        if (ts.isEmpty(exisingImports)) {
                            return exports;
                        }
                        return ts.filter(exports, function (e) {
                            return !ts.lookUp(exisingImports, e.name);
                        });
                    }
                    function filterContextualMembersList(contextualMemberSymbols, existingMembers) {
                        if (!existingMembers || existingMembers.length === 0) {
                            return contextualMemberSymbols;
                        }
                        var existingMemberNames = {};
                        ts.forEach(existingMembers, function (m) {
                            if (m.kind !== 218 && m.kind !== 219) {
                                return;
                            }
                            if (m.getStart() <= position && position <= m.getEnd()) {
                                return;
                            }
                            existingMemberNames[m.name.text] = true;
                        });
                        var filteredMembers = [];
                        ts.forEach(contextualMemberSymbols, function (s) {
                            if (!existingMemberNames[s.name]) {
                                filteredMembers.push(s);
                            }
                        });
                        return filteredMembers;
                    }
                }
                function getCompletionEntryDetails(fileName, position, entryName) {
                    var sourceFile = getValidSourceFile(fileName);
                    var session = activeCompletionSession;
                    if (!session || session.fileName !== fileName || session.position !== position) {
                        return undefined;
                    }
                    var symbol = ts.lookUp(activeCompletionSession.symbols, ts.escapeIdentifier(entryName));
                    if (symbol) {
                        var location = ts.getTouchingPropertyName(sourceFile, position);
                        var completionEntry = createCompletionEntry(symbol, session.typeChecker, location);
                        ts.Debug.assert(session.typeChecker.getTypeOfSymbolAtLocation(symbol, location) !== undefined, "Could not find type for symbol");
                        var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, session.typeChecker, location, 7);
                        return {
                            name: entryName,
                            kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
                            kindModifiers: completionEntry.kindModifiers,
                            displayParts: displayPartsDocumentationsAndSymbolKind.displayParts,
                            documentation: displayPartsDocumentationsAndSymbolKind.documentation
                        };
                    }
                    else {
                        return {
                            name: entryName,
                            kind: ScriptElementKind.keyword,
                            kindModifiers: ScriptElementKindModifier.none,
                            displayParts: [
                                ts.displayPart(entryName, 5)
                            ],
                            documentation: undefined
                        };
                    }
                }
                function getSymbolKind(symbol, typeResolver, location) {
                    var flags = symbol.getFlags();
                    if (flags & 32)
                        return ScriptElementKind.classElement;
                    if (flags & 384)
                        return ScriptElementKind.enumElement;
                    if (flags & 524288)
                        return ScriptElementKind.typeElement;
                    if (flags & 64)
                        return ScriptElementKind.interfaceElement;
                    if (flags & 262144)
                        return ScriptElementKind.typeParameterElement;
                    var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location);
                    if (result === ScriptElementKind.unknown) {
                        if (flags & 262144)
                            return ScriptElementKind.typeParameterElement;
                        if (flags & 8)
                            return ScriptElementKind.variableElement;
                        if (flags & 8388608)
                            return ScriptElementKind.alias;
                        if (flags & 1536)
                            return ScriptElementKind.moduleElement;
                    }
                    return result;
                }
                function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location) {
                    if (typeResolver.isUndefinedSymbol(symbol)) {
                        return ScriptElementKind.variableElement;
                    }
                    if (typeResolver.isArgumentsSymbol(symbol)) {
                        return ScriptElementKind.localVariableElement;
                    }
                    if (flags & 3) {
                        if (ts.isFirstDeclarationOfSymbolParameter(symbol)) {
                            return ScriptElementKind.parameterElement;
                        }
                        else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) {
                            return ScriptElementKind.constElement;
                        }
                        else if (ts.forEach(symbol.declarations, ts.isLet)) {
                            return ScriptElementKind.letElement;
                        }
                        return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
                    }
                    if (flags & 16)
                        return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
                    if (flags & 32768)
                        return ScriptElementKind.memberGetAccessorElement;
                    if (flags & 65536)
                        return ScriptElementKind.memberSetAccessorElement;
                    if (flags & 8192)
                        return ScriptElementKind.memberFunctionElement;
                    if (flags & 16384)
                        return ScriptElementKind.constructorImplementationElement;
                    if (flags & 4) {
                        if (flags & 268435456) {
                            var unionPropertyKind = ts.forEach(typeInfoResolver.getRootSymbols(symbol), function (rootSymbol) {
                                var rootSymbolFlags = rootSymbol.getFlags();
                                if (rootSymbolFlags & (98308 | 3)) {
                                    return ScriptElementKind.memberVariableElement;
                                }
                                ts.Debug.assert(!!(rootSymbolFlags & 8192));
                            });
                            if (!unionPropertyKind) {
                                var typeOfUnionProperty = typeInfoResolver.getTypeOfSymbolAtLocation(symbol, location);
                                if (typeOfUnionProperty.getCallSignatures().length) {
                                    return ScriptElementKind.memberFunctionElement;
                                }
                                return ScriptElementKind.memberVariableElement;
                            }
                            return unionPropertyKind;
                        }
                        return ScriptElementKind.memberVariableElement;
                    }
                    return ScriptElementKind.unknown;
                }
                function getTypeKind(type) {
                    var flags = type.getFlags();
                    if (flags & 128)
                        return ScriptElementKind.enumElement;
                    if (flags & 1024)
                        return ScriptElementKind.classElement;
                    if (flags & 2048)
                        return ScriptElementKind.interfaceElement;
                    if (flags & 512)
                        return ScriptElementKind.typeParameterElement;
                    if (flags & 1048703)
                        return ScriptElementKind.primitiveType;
                    if (flags & 256)
                        return ScriptElementKind.primitiveType;
                    return ScriptElementKind.unknown;
                }
                function getSymbolModifiers(symbol) {
                    return symbol && symbol.declarations && symbol.declarations.length > 0 ? ts.getNodeModifiers(symbol.declarations[0]) : ScriptElementKindModifier.none;
                }
                function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, enclosingDeclaration, typeResolver, location, semanticMeaning) {
                    if (semanticMeaning === void 0) { semanticMeaning = getMeaningFromLocation(location); }
                    var displayParts = [];
                    var documentation;
                    var symbolFlags = symbol.flags;
                    var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver, location);
                    var hasAddedSymbolInfo;
                    if (symbolKind !== ScriptElementKind.unknown || symbolFlags & 32 || symbolFlags & 8388608) {
                        if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) {
                            symbolKind = ScriptElementKind.memberVariableElement;
                        }
                        var type = typeResolver.getTypeOfSymbolAtLocation(symbol, location);
                        if (type) {
                            if (location.parent && location.parent.kind === 153) {
                                var right = location.parent.name;
                                if (right === location || (right && right.getFullWidth() === 0)) {
                                    location = location.parent;
                                }
                            }
                            var callExpression;
                            if (location.kind === 155 || location.kind === 156) {
                                callExpression = location;
                            }
                            else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
                                callExpression = location.parent;
                            }
                            if (callExpression) {
                                var candidateSignatures = [];
                                signature = typeResolver.getResolvedSignature(callExpression, candidateSignatures);
                                if (!signature && candidateSignatures.length) {
                                    signature = candidateSignatures[0];
                                }
                                var useConstructSignatures = callExpression.kind === 156 || callExpression.expression.kind === 90;
                                var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
                                if (!ts.contains(allSignatures, signature.target || signature)) {
                                    signature = allSignatures.length ? allSignatures[0] : undefined;
                                }
                                if (signature) {
                                    if (useConstructSignatures && (symbolFlags & 32)) {
                                        symbolKind = ScriptElementKind.constructorImplementationElement;
                                        addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
                                    }
                                    else if (symbolFlags & 8388608) {
                                        symbolKind = ScriptElementKind.alias;
                                        displayParts.push(ts.punctuationPart(16));
                                        displayParts.push(ts.textPart(symbolKind));
                                        displayParts.push(ts.punctuationPart(17));
                                        displayParts.push(ts.spacePart());
                                        if (useConstructSignatures) {
                                            displayParts.push(ts.keywordPart(87));
                                            displayParts.push(ts.spacePart());
                                        }
                                        addFullSymbolName(symbol);
                                    }
                                    else {
                                        addPrefixForAnyFunctionOrVar(symbol, symbolKind);
                                    }
                                    switch (symbolKind) {
                                        case ScriptElementKind.memberVariableElement:
                                        case ScriptElementKind.variableElement:
                                        case ScriptElementKind.constElement:
                                        case ScriptElementKind.letElement:
                                        case ScriptElementKind.parameterElement:
                                        case ScriptElementKind.localVariableElement:
                                            displayParts.push(ts.punctuationPart(51));
                                            displayParts.push(ts.spacePart());
                                            if (useConstructSignatures) {
                                                displayParts.push(ts.keywordPart(87));
                                                displayParts.push(ts.spacePart());
                                            }
                                            if (!(type.flags & 32768)) {
                                                displayParts.push.apply(displayParts, ts.symbolToDisplayParts(typeResolver, type.symbol, enclosingDeclaration, undefined, 1));
                                            }
                                            addSignatureDisplayParts(signature, allSignatures, 8);
                                            break;
                                        default:
                                            addSignatureDisplayParts(signature, allSignatures);
                                    }
                                    hasAddedSymbolInfo = true;
                                }
                            }
                            else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304)) || (location.kind === 113 && location.parent.kind === 133)) {
                                var signature;
                                var functionDeclaration = location.parent;
                                var allSignatures = functionDeclaration.kind === 133 ? type.getConstructSignatures() : type.getCallSignatures();
                                if (!typeResolver.isImplementationOfOverload(functionDeclaration)) {
                                    signature = typeResolver.getSignatureFromDeclaration(functionDeclaration);
                                }
                                else {
                                    signature = allSignatures[0];
                                }
                                if (functionDeclaration.kind === 133) {
                                    symbolKind = ScriptElementKind.constructorImplementationElement;
                                    addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
                                }
                                else {
                                    addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 136 && !(type.symbol.flags & 2048 || type.symbol.flags & 4096) ? type.symbol : symbol, symbolKind);
                                }
                                addSignatureDisplayParts(signature, allSignatures);
                                hasAddedSymbolInfo = true;
                            }
                        }
                    }
                    if (symbolFlags & 32 && !hasAddedSymbolInfo) {
                        displayParts.push(ts.keywordPart(68));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        writeTypeParametersOfSymbol(symbol, sourceFile);
                    }
                    if ((symbolFlags & 64) && (semanticMeaning & 2)) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(103));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        writeTypeParametersOfSymbol(symbol, sourceFile);
                    }
                    if (symbolFlags & 524288) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(122));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        displayParts.push(ts.spacePart());
                        displayParts.push(ts.operatorPart(52));
                        displayParts.push(ts.spacePart());
                        displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeResolver, typeResolver.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
                    }
                    if (symbolFlags & 384) {
                        addNewLineIfDisplayPartsExist();
                        if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) {
                            displayParts.push(ts.keywordPart(69));
                            displayParts.push(ts.spacePart());
                        }
                        displayParts.push(ts.keywordPart(76));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                    }
                    if (symbolFlags & 1536) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(116));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                    }
                    if ((symbolFlags & 262144) && (semanticMeaning & 2)) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.punctuationPart(16));
                        displayParts.push(ts.textPart("type parameter"));
                        displayParts.push(ts.punctuationPart(17));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        displayParts.push(ts.spacePart());
                        displayParts.push(ts.keywordPart(85));
                        displayParts.push(ts.spacePart());
                        if (symbol.parent) {
                            addFullSymbolName(symbol.parent, enclosingDeclaration);
                            writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
                        }
                        else {
                            var signatureDeclaration = ts.getDeclarationOfKind(symbol, 127).parent;
                            var signature = typeResolver.getSignatureFromDeclaration(signatureDeclaration);
                            if (signatureDeclaration.kind === 137) {
                                displayParts.push(ts.keywordPart(87));
                                displayParts.push(ts.spacePart());
                            }
                            else if (signatureDeclaration.kind !== 136 && signatureDeclaration.name) {
                                addFullSymbolName(signatureDeclaration.symbol);
                            }
                            displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeResolver, signature, sourceFile, 32));
                        }
                    }
                    if (symbolFlags & 8) {
                        addPrefixForAnyFunctionOrVar(symbol, "enum member");
                        var declaration = symbol.declarations[0];
                        if (declaration.kind === 220) {
                            var constantValue = typeResolver.getConstantValue(declaration);
                            if (constantValue !== undefined) {
                                displayParts.push(ts.spacePart());
                                displayParts.push(ts.operatorPart(52));
                                displayParts.push(ts.spacePart());
                                displayParts.push(ts.displayPart(constantValue.toString(), 7));
                            }
                        }
                    }
                    if (symbolFlags & 8388608) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(84));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        ts.forEach(symbol.declarations, function (declaration) {
                            if (declaration.kind === 203) {
                                var importEqualsDeclaration = declaration;
                                if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
                                    displayParts.push(ts.spacePart());
                                    displayParts.push(ts.operatorPart(52));
                                    displayParts.push(ts.spacePart());
                                    displayParts.push(ts.keywordPart(117));
                                    displayParts.push(ts.punctuationPart(16));
                                    displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), 8));
                                    displayParts.push(ts.punctuationPart(17));
                                }
                                else {
                                    var internalAliasSymbol = typeResolver.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
                                    if (internalAliasSymbol) {
                                        displayParts.push(ts.spacePart());
                                        displayParts.push(ts.operatorPart(52));
                                        displayParts.push(ts.spacePart());
                                        addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
                                    }
                                }
                                return true;
                            }
                        });
                    }
                    if (!hasAddedSymbolInfo) {
                        if (symbolKind !== ScriptElementKind.unknown) {
                            if (type) {
                                addPrefixForAnyFunctionOrVar(symbol, symbolKind);
                                if (symbolKind === ScriptElementKind.memberVariableElement || symbolFlags & 3 || symbolKind === ScriptElementKind.localVariableElement) {
                                    displayParts.push(ts.punctuationPart(51));
                                    displayParts.push(ts.spacePart());
                                    if (type.symbol && type.symbol.flags & 262144) {
                                        var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                                            typeResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration);
                                        });
                                        displayParts.push.apply(displayParts, typeParameterParts);
                                    }
                                    else {
                                        displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeResolver, type, enclosingDeclaration));
                                    }
                                }
                                else if (symbolFlags & 16 || symbolFlags & 8192 || symbolFlags & 16384 || symbolFlags & 131072 || symbolFlags & 98304 || symbolKind === ScriptElementKind.memberFunctionElement) {
                                    var allSignatures = type.getCallSignatures();
                                    addSignatureDisplayParts(allSignatures[0], allSignatures);
                                }
                            }
                        }
                        else {
                            symbolKind = getSymbolKind(symbol, typeResolver, location);
                        }
                    }
                    if (!documentation) {
                        documentation = symbol.getDocumentationComment();
                    }
                    return {
                        displayParts: displayParts,
                        documentation: documentation,
                        symbolKind: symbolKind
                    };
                    function addNewLineIfDisplayPartsExist() {
                        if (displayParts.length) {
                            displayParts.push(ts.lineBreakPart());
                        }
                    }
                    function addFullSymbolName(symbol, enclosingDeclaration) {
                        var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeResolver, symbol, enclosingDeclaration || sourceFile, undefined, 1 | 2);
                        displayParts.push.apply(displayParts, fullSymbolDisplayParts);
                    }
                    function addPrefixForAnyFunctionOrVar(symbol, symbolKind) {
                        addNewLineIfDisplayPartsExist();
                        if (symbolKind) {
                            displayParts.push(ts.punctuationPart(16));
                            displayParts.push(ts.textPart(symbolKind));
                            displayParts.push(ts.punctuationPart(17));
                            displayParts.push(ts.spacePart());
                            addFullSymbolName(symbol);
                        }
                    }
                    function addSignatureDisplayParts(signature, allSignatures, flags) {
                        displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeResolver, signature, enclosingDeclaration, flags | 32));
                        if (allSignatures.length > 1) {
                            displayParts.push(ts.spacePart());
                            displayParts.push(ts.punctuationPart(16));
                            displayParts.push(ts.operatorPart(33));
                            displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), 7));
                            displayParts.push(ts.spacePart());
                            displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads"));
                            displayParts.push(ts.punctuationPart(17));
                        }
                        documentation = signature.getDocumentationComment();
                    }
                    function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) {
                        var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                            typeResolver.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration);
                        });
                        displayParts.push.apply(displayParts, typeParameterParts);
                    }
                }
                function getQuickInfoAtPosition(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    var symbol = typeInfoResolver.getSymbolAtLocation(node);
                    if (!symbol) {
                        switch (node.kind) {
                            case 64:
                            case 153:
                            case 125:
                            case 92:
                            case 90:
                                var type = typeInfoResolver.getTypeAtLocation(node);
                                if (type) {
                                    return {
                                        kind: ScriptElementKind.unknown,
                                        kindModifiers: ScriptElementKindModifier.none,
                                        textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                                        displayParts: ts.typeToDisplayParts(typeInfoResolver, type, getContainerNode(node)),
                                        documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined
                                    };
                                }
                        }
                        return undefined;
                    }
                    var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), typeInfoResolver, node);
                    return {
                        kind: displayPartsDocumentationsAndKind.symbolKind,
                        kindModifiers: getSymbolModifiers(symbol),
                        textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                        displayParts: displayPartsDocumentationsAndKind.displayParts,
                        documentation: displayPartsDocumentationsAndKind.documentation
                    };
                }
                function getDefinitionAtPosition(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    if (isJumpStatementTarget(node)) {
                        var labelName = node.text;
                        var label = getTargetLabel(node.parent, node.text);
                        return label ? [
                            getDefinitionInfo(label, ScriptElementKind.label, labelName, undefined)
                        ] : undefined;
                    }
                    var comment = ts.forEach(sourceFile.referencedFiles, function (r) {
                        return (r.pos <= position && position < r.end) ? r : undefined;
                    });
                    if (comment) {
                        var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment);
                        if (referenceFile) {
                            return [
                                {
                                    fileName: referenceFile.fileName,
                                    textSpan: ts.createTextSpanFromBounds(0, 0),
                                    kind: ScriptElementKind.scriptElement,
                                    name: comment.fileName,
                                    containerName: undefined,
                                    containerKind: undefined
                                }
                            ];
                        }
                        return undefined;
                    }
                    var symbol = typeInfoResolver.getSymbolAtLocation(node);
                    if (!symbol) {
                        return undefined;
                    }
                    if (symbol.flags & 8388608) {
                        var declaration = symbol.declarations[0];
                        if (node.kind === 64 && node.parent === declaration) {
                            symbol = typeInfoResolver.getAliasedSymbol(symbol);
                        }
                    }
                    var result = [];
                    if (node.parent.kind === 219) {
                        var shorthandSymbol = typeInfoResolver.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
                        var shorthandDeclarations = shorthandSymbol.getDeclarations();
                        var shorthandSymbolKind = getSymbolKind(shorthandSymbol, typeInfoResolver, node);
                        var shorthandSymbolName = typeInfoResolver.symbolToString(shorthandSymbol);
                        var shorthandContainerName = typeInfoResolver.symbolToString(symbol.parent, node);
                        ts.forEach(shorthandDeclarations, function (declaration) {
                            result.push(getDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName));
                        });
                        return result;
                    }
                    var declarations = symbol.getDeclarations();
                    var symbolName = typeInfoResolver.symbolToString(symbol);
                    var symbolKind = getSymbolKind(symbol, typeInfoResolver, node);
                    var containerSymbol = symbol.parent;
                    var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";
                    if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
                        ts.forEach(declarations, function (declaration) {
                            result.push(getDefinitionInfo(declaration, symbolKind, symbolName, containerName));
                        });
                    }
                    return result;
                    function getDefinitionInfo(node, symbolKind, symbolName, containerName) {
                        return {
                            fileName: node.getSourceFile().fileName,
                            textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()),
                            kind: symbolKind,
                            name: symbolName,
                            containerKind: undefined,
                            containerName: containerName
                        };
                    }
                    function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) {
                        var declarations = [];
                        var definition;
                        ts.forEach(signatureDeclarations, function (d) {
                            if ((selectConstructors && d.kind === 133) || (!selectConstructors && (d.kind === 195 || d.kind === 132 || d.kind === 131))) {
                                declarations.push(d);
                                if (d.body)
                                    definition = d;
                            }
                        });
                        if (definition) {
                            result.push(getDefinitionInfo(definition, symbolKind, symbolName, containerName));
                            return true;
                        }
                        else if (declarations.length) {
                            result.push(getDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
                            return true;
                        }
                        return false;
                    }
                    function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) {
                        if (isNewExpressionTarget(location) || location.kind === 113) {
                            if (symbol.flags & 32) {
                                var classDeclaration = symbol.getDeclarations()[0];
                                ts.Debug.assert(classDeclaration && classDeclaration.kind === 196);
                                return tryAddSignature(classDeclaration.members, true, symbolKind, symbolName, containerName, result);
                            }
                        }
                        return false;
                    }
                    function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) {
                        if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) {
                            return tryAddSignature(symbol.declarations, false, symbolKind, symbolName, containerName, result);
                        }
                        return false;
                    }
                }
                function getOccurrencesAtPosition(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingWord(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    if (node.kind === 64 || node.kind === 92 || node.kind === 90 || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
                        return getReferencesForNode(node, [
                            sourceFile
                        ], true, false, false);
                    }
                    switch (node.kind) {
                        case 83:
                        case 75:
                            if (hasKind(node.parent, 178)) {
                                return getIfElseOccurrences(node.parent);
                            }
                            break;
                        case 89:
                            if (hasKind(node.parent, 186)) {
                                return getReturnOccurrences(node.parent);
                            }
                            break;
                        case 93:
                            if (hasKind(node.parent, 190)) {
                                return getThrowOccurrences(node.parent);
                            }
                            break;
                        case 67:
                            if (hasKind(parent(parent(node)), 191)) {
                                return getTryCatchFinallyOccurrences(node.parent.parent);
                            }
                            break;
                        case 95:
                        case 80:
                            if (hasKind(parent(node), 191)) {
                                return getTryCatchFinallyOccurrences(node.parent);
                            }
                            break;
                        case 91:
                            if (hasKind(node.parent, 188)) {
                                return getSwitchCaseDefaultOccurrences(node.parent);
                            }
                            break;
                        case 66:
                        case 72:
                            if (hasKind(parent(parent(parent(node))), 188)) {
                                return getSwitchCaseDefaultOccurrences(node.parent.parent.parent);
                            }
                            break;
                        case 65:
                        case 70:
                            if (hasKind(node.parent, 185) || hasKind(node.parent, 184)) {
                                return getBreakOrContinueStatementOccurences(node.parent);
                            }
                            break;
                        case 81:
                            if (hasKind(node.parent, 181) || hasKind(node.parent, 182) || hasKind(node.parent, 183)) {
                                return getLoopBreakContinueOccurrences(node.parent);
                            }
                            break;
                        case 99:
                        case 74:
                            if (hasKind(node.parent, 180) || hasKind(node.parent, 179)) {
                                return getLoopBreakContinueOccurrences(node.parent);
                            }
                            break;
                        case 113:
                            if (hasKind(node.parent, 133)) {
                                return getConstructorOccurrences(node.parent);
                            }
                            break;
                        case 115:
                        case 119:
                            if (hasKind(node.parent, 134) || hasKind(node.parent, 135)) {
                                return getGetAndSetOccurrences(node.parent);
                            }
                        default:
                            if (ts.isModifier(node.kind) && node.parent && (ts.isDeclaration(node.parent) || node.parent.kind === 175)) {
                                return getModifierOccurrences(node.kind, node.parent);
                            }
                    }
                    return undefined;
                    function getIfElseOccurrences(ifStatement) {
                        var keywords = [];
                        while (hasKind(ifStatement.parent, 178) && ifStatement.parent.elseStatement === ifStatement) {
                            ifStatement = ifStatement.parent;
                        }
                        while (ifStatement) {
                            var children = ifStatement.getChildren();
                            pushKeywordIf(keywords, children[0], 83);
                            for (var i = children.length - 1; i >= 0; i--) {
                                if (pushKeywordIf(keywords, children[i], 75)) {
                                    break;
                                }
                            }
                            if (!hasKind(ifStatement.elseStatement, 178)) {
                                break;
                            }
                            ifStatement = ifStatement.elseStatement;
                        }
                        var result = [];
                        for (var i = 0; i < keywords.length; i++) {
                            if (keywords[i].kind === 75 && i < keywords.length - 1) {
                                var elseKeyword = keywords[i];
                                var ifKeyword = keywords[i + 1];
                                var shouldHighlightNextKeyword = true;
                                for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
                                    if (!ts.isWhiteSpace(sourceFile.text.charCodeAt(j))) {
                                        shouldHighlightNextKeyword = false;
                                        break;
                                    }
                                }
                                if (shouldHighlightNextKeyword) {
                                    result.push({
                                        fileName: fileName,
                                        textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
                                        isWriteAccess: false
                                    });
                                    i++;
                                    continue;
                                }
                            }
                            result.push(getReferenceEntryFromNode(keywords[i]));
                        }
                        return result;
                    }
                    function getReturnOccurrences(returnStatement) {
                        var func = ts.getContainingFunction(returnStatement);
                        if (!(func && hasKind(func.body, 174))) {
                            return undefined;
                        }
                        var keywords = [];
                        ts.forEachReturnStatement(func.body, function (returnStatement) {
                            pushKeywordIf(keywords, returnStatement.getFirstToken(), 89);
                        });
                        ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) {
                            pushKeywordIf(keywords, throwStatement.getFirstToken(), 93);
                        });
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function getThrowOccurrences(throwStatement) {
                        var owner = getThrowStatementOwner(throwStatement);
                        if (!owner) {
                            return undefined;
                        }
                        var keywords = [];
                        ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) {
                            pushKeywordIf(keywords, throwStatement.getFirstToken(), 93);
                        });
                        if (ts.isFunctionBlock(owner)) {
                            ts.forEachReturnStatement(owner, function (returnStatement) {
                                pushKeywordIf(keywords, returnStatement.getFirstToken(), 89);
                            });
                        }
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function aggregateOwnedThrowStatements(node) {
                        var statementAccumulator = [];
                        aggregate(node);
                        return statementAccumulator;
                        function aggregate(node) {
                            if (node.kind === 190) {
                                statementAccumulator.push(node);
                            }
                            else if (node.kind === 191) {
                                var tryStatement = node;
                                if (tryStatement.catchClause) {
                                    aggregate(tryStatement.catchClause);
                                }
                                else {
                                    aggregate(tryStatement.tryBlock);
                                }
                                if (tryStatement.finallyBlock) {
                                    aggregate(tryStatement.finallyBlock);
                                }
                            }
                            else if (!ts.isFunctionLike(node)) {
                                ts.forEachChild(node, aggregate);
                            }
                        }
                        ;
                    }
                    function getThrowStatementOwner(throwStatement) {
                        var child = throwStatement;
                        while (child.parent) {
                            var parent = child.parent;
                            if (ts.isFunctionBlock(parent) || parent.kind === 221) {
                                return parent;
                            }
                            if (parent.kind === 191) {
                                var tryStatement = parent;
                                if (tryStatement.tryBlock === child && tryStatement.catchClause) {
                                    return child;
                                }
                            }
                            child = parent;
                        }
                        return undefined;
                    }
                    function getTryCatchFinallyOccurrences(tryStatement) {
                        var keywords = [];
                        pushKeywordIf(keywords, tryStatement.getFirstToken(), 95);
                        if (tryStatement.catchClause) {
                            pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 67);
                        }
                        if (tryStatement.finallyBlock) {
                            var finallyKeyword = ts.findChildOfKind(tryStatement, 80, sourceFile);
                            pushKeywordIf(keywords, finallyKeyword, 80);
                        }
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function getLoopBreakContinueOccurrences(loopNode) {
                        var keywords = [];
                        if (pushKeywordIf(keywords, loopNode.getFirstToken(), 81, 99, 74)) {
                            if (loopNode.kind === 179) {
                                var loopTokens = loopNode.getChildren();
                                for (var i = loopTokens.length - 1; i >= 0; i--) {
                                    if (pushKeywordIf(keywords, loopTokens[i], 99)) {
                                        break;
                                    }
                                }
                            }
                        }
                        var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
                        ts.forEach(breaksAndContinues, function (statement) {
                            if (ownsBreakOrContinueStatement(loopNode, statement)) {
                                pushKeywordIf(keywords, statement.getFirstToken(), 65, 70);
                            }
                        });
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function getSwitchCaseDefaultOccurrences(switchStatement) {
                        var keywords = [];
                        pushKeywordIf(keywords, switchStatement.getFirstToken(), 91);
                        ts.forEach(switchStatement.caseBlock.clauses, function (clause) {
                            pushKeywordIf(keywords, clause.getFirstToken(), 66, 72);
                            var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
                            ts.forEach(breaksAndContinues, function (statement) {
                                if (ownsBreakOrContinueStatement(switchStatement, statement)) {
                                    pushKeywordIf(keywords, statement.getFirstToken(), 65);
                                }
                            });
                        });
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function getBreakOrContinueStatementOccurences(breakOrContinueStatement) {
                        var owner = getBreakOrContinueOwner(breakOrContinueStatement);
                        if (owner) {
                            switch (owner.kind) {
                                case 181:
                                case 182:
                                case 183:
                                case 179:
                                case 180:
                                    return getLoopBreakContinueOccurrences(owner);
                                case 188:
                                    return getSwitchCaseDefaultOccurrences(owner);
                            }
                        }
                        return undefined;
                    }
                    function aggregateAllBreakAndContinueStatements(node) {
                        var statementAccumulator = [];
                        aggregate(node);
                        return statementAccumulator;
                        function aggregate(node) {
                            if (node.kind === 185 || node.kind === 184) {
                                statementAccumulator.push(node);
                            }
                            else if (!ts.isFunctionLike(node)) {
                                ts.forEachChild(node, aggregate);
                            }
                        }
                        ;
                    }
                    function ownsBreakOrContinueStatement(owner, statement) {
                        var actualOwner = getBreakOrContinueOwner(statement);
                        return actualOwner && actualOwner === owner;
                    }
                    function getBreakOrContinueOwner(statement) {
                        for (var node = statement.parent; node; node = node.parent) {
                            switch (node.kind) {
                                case 188:
                                    if (statement.kind === 184) {
                                        continue;
                                    }
                                case 181:
                                case 182:
                                case 183:
                                case 180:
                                case 179:
                                    if (!statement.label || isLabeledBy(node, statement.label.text)) {
                                        return node;
                                    }
                                    break;
                                default:
                                    if (ts.isFunctionLike(node)) {
                                        return undefined;
                                    }
                                    break;
                            }
                        }
                        return undefined;
                    }
                    function getConstructorOccurrences(constructorDeclaration) {
                        var declarations = constructorDeclaration.symbol.getDeclarations();
                        var keywords = [];
                        ts.forEach(declarations, function (declaration) {
                            ts.forEach(declaration.getChildren(), function (token) {
                                return pushKeywordIf(keywords, token, 113);
                            });
                        });
                        return ts.map(keywords, getReferenceEntryFromNode);
                    }
                    function getGetAndSetOccurrences(accessorDeclaration) {
                        var keywords = [];
                        tryPushAccessorKeyword(accessorDeclaration.symbol, 134);
                        tryPushAccessorKeyword(accessorDeclaration.symbol, 135);
                        return ts.map(keywords, getReferenceEntryFromNode);
                        function tryPushAccessorKeyword(accessorSymbol, accessorKind) {
                            var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind);
                            if (accessor) {
                                ts.forEach(accessor.getChildren(), function (child) {
                                    return pushKeywordIf(keywords, child, 115, 119);
                                });
                            }
                        }
                    }
                    function getModifierOccurrences(modifier, declaration) {
                        var container = declaration.parent;
                        if (declaration.flags & 112) {
                            if (!(container.kind === 196 || (declaration.kind === 128 && hasKind(container, 133)))) {
                                return undefined;
                            }
                        }
                        else if (declaration.flags & 128) {
                            if (container.kind !== 196) {
                                return undefined;
                            }
                        }
                        else if (declaration.flags & (1 | 2)) {
                            if (!(container.kind === 201 || container.kind === 221)) {
                                return undefined;
                            }
                        }
                        else {
                            return undefined;
                        }
                        var keywords = [];
                        var modifierFlag = getFlagFromModifier(modifier);
                        var nodes;
                        switch (container.kind) {
                            case 201:
                            case 221:
                                nodes = container.statements;
                                break;
                            case 133:
                                nodes = container.parameters.concat(container.parent.members);
                                break;
                            case 196:
                                nodes = container.members;
                                if (modifierFlag & 112) {
                                    var constructor = ts.forEach(container.members, function (member) {
                                        return member.kind === 133 && member;
                                    });
                                    if (constructor) {
                                        nodes = nodes.concat(constructor.parameters);
                                    }
                                }
                                break;
                            default:
                                ts.Debug.fail("Invalid container kind.");
                        }
                        ts.forEach(nodes, function (node) {
                            if (node.modifiers && node.flags & modifierFlag) {
                                ts.forEach(node.modifiers, function (child) {
                                    return pushKeywordIf(keywords, child, modifier);
                                });
                            }
                        });
                        return ts.map(keywords, getReferenceEntryFromNode);
                        function getFlagFromModifier(modifier) {
                            switch (modifier) {
                                case 108:
                                    return 16;
                                case 106:
                                    return 32;
                                case 107:
                                    return 64;
                                case 109:
                                    return 128;
                                case 77:
                                    return 1;
                                case 114:
                                    return 2;
                                default:
                                    ts.Debug.fail();
                            }
                        }
                    }
                    function hasKind(node, kind) {
                        return node !== undefined && node.kind === kind;
                    }
                    function parent(node) {
                        return node && node.parent;
                    }
                    function pushKeywordIf(keywordList, token) {
                        var expected = [];
                        for (var _i = 2; _i < arguments.length; _i++) {
                            expected[_i - 2] = arguments[_i];
                        }
                        if (token && ts.contains(expected, token.kind)) {
                            keywordList.push(token);
                            return true;
                        }
                        return false;
                    }
                }
                function findRenameLocations(fileName, position, findInStrings, findInComments) {
                    return findReferences(fileName, position, findInStrings, findInComments);
                }
                function getReferencesAtPosition(fileName, position) {
                    return findReferences(fileName, position, false, false);
                }
                function findReferences(fileName, position, findInStrings, findInComments) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    if (node.kind !== 64 && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) {
                        return undefined;
                    }
                    ts.Debug.assert(node.kind === 64 || node.kind === 7 || node.kind === 8);
                    return getReferencesForNode(node, program.getSourceFiles(), false, findInStrings, findInComments);
                }
                function getReferencesForNode(node, sourceFiles, searchOnlyInCurrentFile, findInStrings, findInComments) {
                    if (isLabelName(node)) {
                        if (isJumpStatementTarget(node)) {
                            var labelDefinition = getTargetLabel(node.parent, node.text);
                            return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : [
                                getReferenceEntryFromNode(node)
                            ];
                        }
                        else {
                            return getLabelReferencesInNode(node.parent, node);
                        }
                    }
                    if (node.kind === 92) {
                        return getReferencesForThisKeyword(node, sourceFiles);
                    }
                    if (node.kind === 90) {
                        return getReferencesForSuperKeyword(node);
                    }
                    var symbol = typeInfoResolver.getSymbolAtLocation(node);
                    if (!symbol) {
                        return [
                            getReferenceEntryFromNode(node)
                        ];
                    }
                    var declarations = symbol.declarations;
                    if (!declarations || !declarations.length) {
                        return undefined;
                    }
                    var result;
                    var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
                    var declaredName = getDeclaredName(symbol, node);
                    var scope = getSymbolScope(symbol);
                    if (scope) {
                        result = [];
                        getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
                    }
                    else {
                        if (searchOnlyInCurrentFile) {
                            ts.Debug.assert(sourceFiles.length === 1);
                            result = [];
                            getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
                        }
                        else {
                            var internedName = getInternedName(symbol, node, declarations);
                            ts.forEach(sourceFiles, function (sourceFile) {
                                cancellationToken.throwIfCancellationRequested();
                                var nameTable = getNameTable(sourceFile);
                                if (ts.lookUp(nameTable, internedName)) {
                                    result = result || [];
                                    getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
                                }
                            });
                        }
                    }
                    return result;
                    function isImportOrExportSpecifierName(location) {
                        return location.parent && (location.parent.kind === 208 || location.parent.kind === 212) && location.parent.propertyName === location;
                    }
                    function isImportOrExportSpecifierImportSymbol(symbol) {
                        return (symbol.flags & 8388608) && ts.forEach(symbol.declarations, function (declaration) {
                            return declaration.kind === 208 || declaration.kind === 212;
                        });
                    }
                    function getDeclaredName(symbol, location) {
                        var functionExpression = ts.forEach(symbol.declarations, function (d) {
                            return d.kind === 160 ? d : undefined;
                        });
                        if (functionExpression && functionExpression.name) {
                            var name = functionExpression.name.text;
                        }
                        if (isImportOrExportSpecifierName(location)) {
                            return location.getText();
                        }
                        var name = typeInfoResolver.symbolToString(symbol);
                        return stripQuotes(name);
                    }
                    function getInternedName(symbol, location, declarations) {
                        if (isImportOrExportSpecifierName(location)) {
                            return location.getText();
                        }
                        var functionExpression = ts.forEach(declarations, function (d) {
                            return d.kind === 160 ? d : undefined;
                        });
                        if (functionExpression && functionExpression.name) {
                            var name = functionExpression.name.text;
                        }
                        else {
                            var name = symbol.name;
                        }
                        return stripQuotes(name);
                    }
                    function stripQuotes(name) {
                        var length = name.length;
                        if (length >= 2 && name.charCodeAt(0) === 34 && name.charCodeAt(length - 1) === 34) {
                            return name.substring(1, length - 1);
                        }
                        ;
                        return name;
                    }
                    function getSymbolScope(symbol) {
                        if (symbol.flags & (4 | 8192)) {
                            var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) {
                                return (d.flags & 32) ? d : undefined;
                            });
                            if (privateDeclaration) {
                                return ts.getAncestor(privateDeclaration, 196);
                            }
                        }
                        if (symbol.flags & 8388608) {
                            return undefined;
                        }
                        if (symbol.parent || (symbol.flags & 268435456)) {
                            return undefined;
                        }
                        var scope = undefined;
                        var declarations = symbol.getDeclarations();
                        if (declarations) {
                            for (var i = 0, n = declarations.length; i < n; i++) {
                                var container = getContainerNode(declarations[i]);
                                if (!container) {
                                    return undefined;
                                }
                                if (scope && scope !== container) {
                                    return undefined;
                                }
                                if (container.kind === 221 && !ts.isExternalModule(container)) {
                                    return undefined;
                                }
                                scope = container;
                            }
                        }
                        return scope;
                    }
                    function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) {
                        var positions = [];
                        if (!symbolName || !symbolName.length) {
                            return positions;
                        }
                        var text = sourceFile.text;
                        var sourceLength = text.length;
                        var symbolNameLength = symbolName.length;
                        var position = text.indexOf(symbolName, start);
                        while (position >= 0) {
                            cancellationToken.throwIfCancellationRequested();
                            if (position > end)
                                break;
                            var endPosition = position + symbolNameLength;
                            if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2)) && (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2))) {
                                positions.push(position);
                            }
                            position = text.indexOf(symbolName, position + symbolNameLength + 1);
                        }
                        return positions;
                    }
                    function getLabelReferencesInNode(container, targetLabel) {
                        var result = [];
                        var sourceFile = container.getSourceFile();
                        var labelName = targetLabel.text;
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd());
                        ts.forEach(possiblePositions, function (position) {
                            cancellationToken.throwIfCancellationRequested();
                            var node = ts.getTouchingWord(sourceFile, position);
                            if (!node || node.getWidth() !== labelName.length) {
                                return;
                            }
                            if (node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) {
                                result.push(getReferenceEntryFromNode(node));
                            }
                        });
                        return result;
                    }
                    function isValidReferencePosition(node, searchSymbolName) {
                        if (node) {
                            switch (node.kind) {
                                case 64:
                                    return node.getWidth() === searchSymbolName.length;
                                case 8:
                                    if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
                                        return node.getWidth() === searchSymbolName.length + 2;
                                    }
                                    break;
                                case 7:
                                    if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
                                        return node.getWidth() === searchSymbolName.length;
                                    }
                                    break;
                            }
                        }
                        return false;
                    }
                    function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result) {
                        var sourceFile = container.getSourceFile();
                        var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
                        if (possiblePositions.length) {
                            var searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation);
                            ts.forEach(possiblePositions, function (position) {
                                cancellationToken.throwIfCancellationRequested();
                                var referenceLocation = ts.getTouchingPropertyName(sourceFile, position);
                                if (!isValidReferencePosition(referenceLocation, searchText)) {
                                    if ((findInStrings && isInString(position)) || (findInComments && isInComment(position))) {
                                        result.push({
                                            fileName: sourceFile.fileName,
                                            textSpan: ts.createTextSpan(position, searchText.length),
                                            isWriteAccess: false
                                        });
                                    }
                                    return;
                                }
                                if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
                                    return;
                                }
                                var referenceSymbol = typeInfoResolver.getSymbolAtLocation(referenceLocation);
                                if (referenceSymbol) {
                                    var referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
                                    var shorthandValueSymbol = typeInfoResolver.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
                                    if (isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation)) {
                                        result.push(getReferenceEntryFromNode(referenceLocation));
                                    }
                                    else if (!(referenceSymbol.flags & 67108864) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
                                        result.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
                                    }
                                }
                            });
                        }
                        function isInString(position) {
                            var token = ts.getTokenAtPosition(sourceFile, position);
                            return token && token.kind === 8 && position > token.getStart();
                        }
                        function isInComment(position) {
                            var token = ts.getTokenAtPosition(sourceFile, position);
                            if (token && position < token.getStart()) {
                                var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos);
                                return ts.forEach(commentRanges, function (c) {
                                    if (c.pos < position && position < c.end) {
                                        var commentText = sourceFile.text.substring(c.pos, c.end);
                                        if (!tripleSlashDirectivePrefixRegex.test(commentText)) {
                                            return true;
                                        }
                                    }
                                });
                            }
                            return false;
                        }
                    }
                    function getReferencesForSuperKeyword(superKeyword) {
                        var searchSpaceNode = ts.getSuperContainer(superKeyword, false);
                        if (!searchSpaceNode) {
                            return undefined;
                        }
                        var staticFlag = 128;
                        switch (searchSpaceNode.kind) {
                            case 130:
                            case 129:
                            case 132:
                            case 131:
                            case 133:
                            case 134:
                            case 135:
                                staticFlag &= searchSpaceNode.flags;
                                searchSpaceNode = searchSpaceNode.parent;
                                break;
                            default:
                                return undefined;
                        }
                        var result = [];
                        var sourceFile = searchSpaceNode.getSourceFile();
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
                        ts.forEach(possiblePositions, function (position) {
                            cancellationToken.throwIfCancellationRequested();
                            var node = ts.getTouchingWord(sourceFile, position);
                            if (!node || node.kind !== 90) {
                                return;
                            }
                            var container = ts.getSuperContainer(node, false);
                            if (container && (128 & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
                                result.push(getReferenceEntryFromNode(node));
                            }
                        });
                        return result;
                    }
                    function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) {
                        var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, false);
                        var staticFlag = 128;
                        switch (searchSpaceNode.kind) {
                            case 132:
                            case 131:
                                if (ts.isObjectLiteralMethod(searchSpaceNode)) {
                                    break;
                                }
                            case 130:
                            case 129:
                            case 133:
                            case 134:
                            case 135:
                                staticFlag &= searchSpaceNode.flags;
                                searchSpaceNode = searchSpaceNode.parent;
                                break;
                            case 221:
                                if (ts.isExternalModule(searchSpaceNode)) {
                                    return undefined;
                                }
                            case 195:
                            case 160:
                                break;
                            default:
                                return undefined;
                        }
                        var result = [];
                        if (searchSpaceNode.kind === 221) {
                            ts.forEach(sourceFiles, function (sourceFile) {
                                var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd());
                                getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, result);
                            });
                        }
                        else {
                            var sourceFile = searchSpaceNode.getSourceFile();
                            var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
                            getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result);
                        }
                        return result;
                        function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) {
                            ts.forEach(possiblePositions, function (position) {
                                cancellationToken.throwIfCancellationRequested();
                                var node = ts.getTouchingWord(sourceFile, position);
                                if (!node || node.kind !== 92) {
                                    return;
                                }
                                var container = ts.getThisContainer(node, false);
                                switch (searchSpaceNode.kind) {
                                    case 160:
                                    case 195:
                                        if (searchSpaceNode.symbol === container.symbol) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 132:
                                    case 131:
                                        if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 196:
                                        if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & 128) === staticFlag) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 221:
                                        if (container.kind === 221 && !ts.isExternalModule(container)) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                }
                            });
                        }
                    }
                    function populateSearchSymbolSet(symbol, location) {
                        var result = [
                            symbol
                        ];
                        if (isImportOrExportSpecifierImportSymbol(symbol)) {
                            result.push(typeInfoResolver.getAliasedSymbol(symbol));
                        }
                        if (isNameOfPropertyAssignment(location)) {
                            ts.forEach(getPropertySymbolsFromContextualType(location), function (contextualSymbol) {
                                result.push.apply(result, typeInfoResolver.getRootSymbols(contextualSymbol));
                            });
                            var shorthandValueSymbol = typeInfoResolver.getShorthandAssignmentValueSymbol(location.parent);
                            if (shorthandValueSymbol) {
                                result.push(shorthandValueSymbol);
                            }
                        }
                        ts.forEach(typeInfoResolver.getRootSymbols(symbol), function (rootSymbol) {
                            if (rootSymbol !== symbol) {
                                result.push(rootSymbol);
                            }
                            if (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64)) {
                                getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
                            }
                        });
                        return result;
                    }
                    function getPropertySymbolsFromBaseTypes(symbol, propertyName, result) {
                        if (symbol && symbol.flags & (32 | 64)) {
                            ts.forEach(symbol.getDeclarations(), function (declaration) {
                                if (declaration.kind === 196) {
                                    getPropertySymbolFromTypeReference(ts.getClassBaseTypeNode(declaration));
                                    ts.forEach(ts.getClassImplementedTypeNodes(declaration), getPropertySymbolFromTypeReference);
                                }
                                else if (declaration.kind === 197) {
                                    ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference);
                                }
                            });
                        }
                        return;
                        function getPropertySymbolFromTypeReference(typeReference) {
                            if (typeReference) {
                                var type = typeInfoResolver.getTypeAtLocation(typeReference);
                                if (type) {
                                    var propertySymbol = typeInfoResolver.getPropertyOfType(type, propertyName);
                                    if (propertySymbol) {
                                        result.push(propertySymbol);
                                    }
                                    getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result);
                                }
                            }
                        }
                    }
                    function isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation) {
                        if (searchSymbols.indexOf(referenceSymbol) >= 0) {
                            return true;
                        }
                        if (isImportOrExportSpecifierImportSymbol(referenceSymbol) && searchSymbols.indexOf(typeInfoResolver.getAliasedSymbol(referenceSymbol)) >= 0) {
                            return true;
                        }
                        if (isNameOfPropertyAssignment(referenceLocation)) {
                            return ts.forEach(getPropertySymbolsFromContextualType(referenceLocation), function (contextualSymbol) {
                                return ts.forEach(typeInfoResolver.getRootSymbols(contextualSymbol), function (s) {
                                    return searchSymbols.indexOf(s) >= 0;
                                });
                            });
                        }
                        return ts.forEach(typeInfoResolver.getRootSymbols(referenceSymbol), function (rootSymbol) {
                            if (searchSymbols.indexOf(rootSymbol) >= 0) {
                                return true;
                            }
                            if (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64)) {
                                var result = [];
                                getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
                                return ts.forEach(result, function (s) {
                                    return searchSymbols.indexOf(s) >= 0;
                                });
                            }
                            return false;
                        });
                    }
                    function getPropertySymbolsFromContextualType(node) {
                        if (isNameOfPropertyAssignment(node)) {
                            var objectLiteral = node.parent.parent;
                            var contextualType = typeInfoResolver.getContextualType(objectLiteral);
                            var name = node.text;
                            if (contextualType) {
                                if (contextualType.flags & 16384) {
                                    var unionProperty = contextualType.getProperty(name);
                                    if (unionProperty) {
                                        return [
                                            unionProperty
                                        ];
                                    }
                                    else {
                                        var result = [];
                                        ts.forEach(contextualType.types, function (t) {
                                            var symbol = t.getProperty(name);
                                            if (symbol) {
                                                result.push(symbol);
                                            }
                                        });
                                        return result;
                                    }
                                }
                                else {
                                    var symbol = contextualType.getProperty(name);
                                    if (symbol) {
                                        return [
                                            symbol
                                        ];
                                    }
                                }
                            }
                        }
                        return undefined;
                    }
                    function getIntersectingMeaningFromDeclarations(meaning, declarations) {
                        if (declarations) {
                            do {
                                var lastIterationMeaning = meaning;
                                for (var i = 0, n = declarations.length; i < n; i++) {
                                    var declarationMeaning = getMeaningFromDeclaration(declarations[i]);
                                    if (declarationMeaning & meaning) {
                                        meaning |= declarationMeaning;
                                    }
                                }
                            } while (meaning !== lastIterationMeaning);
                        }
                        return meaning;
                    }
                }
                function getReferenceEntryFromNode(node) {
                    var start = node.getStart();
                    var end = node.getEnd();
                    if (node.kind === 8) {
                        start += 1;
                        end -= 1;
                    }
                    return {
                        fileName: node.getSourceFile().fileName,
                        textSpan: ts.createTextSpanFromBounds(start, end),
                        isWriteAccess: isWriteAccess(node)
                    };
                }
                function isWriteAccess(node) {
                    if (node.kind === 64 && ts.isDeclarationName(node)) {
                        return true;
                    }
                    var parent = node.parent;
                    if (parent) {
                        if (parent.kind === 166 || parent.kind === 165) {
                            return true;
                        }
                        else if (parent.kind === 167 && parent.left === node) {
                            var operator = parent.operatorToken.kind;
                            return 52 <= operator && operator <= 63;
                        }
                    }
                    return false;
                }
                function getNavigateToItems(searchValue, maxResultCount) {
                    synchronizeHostData();
                    return ts.NavigateTo.getNavigateToItems(program, cancellationToken, searchValue, maxResultCount);
                }
                function containErrors(diagnostics) {
                    return ts.forEach(diagnostics, function (diagnostic) {
                        return diagnostic.category === 1;
                    });
                }
                function getEmitOutput(fileName) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var outputFiles = [];
                    function writeFile(fileName, data, writeByteOrderMark) {
                        outputFiles.push({
                            name: fileName,
                            writeByteOrderMark: writeByteOrderMark,
                            text: data
                        });
                    }
                    var emitOutput = program.emit(sourceFile, writeFile);
                    return {
                        outputFiles: outputFiles,
                        emitSkipped: emitOutput.emitSkipped
                    };
                }
                function getMeaningFromDeclaration(node) {
                    switch (node.kind) {
                        case 128:
                        case 193:
                        case 150:
                        case 130:
                        case 129:
                        case 218:
                        case 219:
                        case 220:
                        case 132:
                        case 131:
                        case 133:
                        case 134:
                        case 135:
                        case 195:
                        case 160:
                        case 161:
                        case 217:
                            return 1;
                        case 127:
                        case 197:
                        case 198:
                        case 143:
                            return 2;
                        case 196:
                        case 199:
                            return 1 | 2;
                        case 200:
                            if (node.name.kind === 8) {
                                return 4 | 1;
                            }
                            else if (ts.getModuleInstanceState(node) === 1) {
                                return 4 | 1;
                            }
                            else {
                                return 4;
                            }
                        case 207:
                        case 208:
                        case 203:
                        case 204:
                        case 209:
                        case 210:
                            return 1 | 2 | 4;
                        case 221:
                            return 4 | 1;
                    }
                    return 1 | 2 | 4;
                    ts.Debug.fail("Unknown declaration type");
                }
                function isTypeReference(node) {
                    if (isRightSideOfQualifiedName(node)) {
                        node = node.parent;
                    }
                    return node.parent.kind === 139;
                }
                function isNamespaceReference(node) {
                    var root = node;
                    var isLastClause = true;
                    if (root.parent.kind === 125) {
                        while (root.parent && root.parent.kind === 125)
                            root = root.parent;
                        isLastClause = root.right === node;
                    }
                    return root.parent.kind === 139 && !isLastClause;
                }
                function isInRightSideOfImport(node) {
                    while (node.parent.kind === 125) {
                        node = node.parent;
                    }
                    return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node;
                }
                function getMeaningFromRightHandSideOfImportEquals(node) {
                    ts.Debug.assert(node.kind === 64);
                    if (node.parent.kind === 125 && node.parent.right === node && node.parent.parent.kind === 203) {
                        return 1 | 2 | 4;
                    }
                    return 4;
                }
                function getMeaningFromLocation(node) {
                    if (node.parent.kind === 209) {
                        return 1 | 2 | 4;
                    }
                    else if (isInRightSideOfImport(node)) {
                        return getMeaningFromRightHandSideOfImportEquals(node);
                    }
                    else if (ts.isDeclarationName(node)) {
                        return getMeaningFromDeclaration(node.parent);
                    }
                    else if (isTypeReference(node)) {
                        return 2;
                    }
                    else if (isNamespaceReference(node)) {
                        return 4;
                    }
                    else {
                        return 1;
                    }
                }
                function getSignatureHelpItems(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    return ts.SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
                }
                function getSourceFile(fileName) {
                    return syntaxTreeCache.getCurrentSourceFile(fileName);
                }
                function getNameOrDottedNameSpan(fileName, startPos, endPos) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, startPos);
                    if (!node) {
                        return;
                    }
                    switch (node.kind) {
                        case 153:
                        case 125:
                        case 8:
                        case 79:
                        case 94:
                        case 88:
                        case 90:
                        case 92:
                        case 64:
                            break;
                        default:
                            return;
                    }
                    var nodeForStartPos = node;
                    while (true) {
                        if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) {
                            nodeForStartPos = nodeForStartPos.parent;
                        }
                        else if (isNameOfModuleDeclaration(nodeForStartPos)) {
                            if (nodeForStartPos.parent.parent.kind === 200 && nodeForStartPos.parent.parent.body === nodeForStartPos.parent) {
                                nodeForStartPos = nodeForStartPos.parent.parent.name;
                            }
                            else {
                                break;
                            }
                        }
                        else {
                            break;
                        }
                    }
                    return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
                }
                function getBreakpointStatementAtPosition(fileName, position) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
                }
                function getNavigationBarItems(fileName) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.NavigationBar.getNavigationBarItems(sourceFile);
                }
                function getSemanticClassifications(fileName, span) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var result = [];
                    processNode(sourceFile);
                    return result;
                    function classifySymbol(symbol, meaningAtPosition) {
                        var flags = symbol.getFlags();
                        if (flags & 32) {
                            return ClassificationTypeNames.className;
                        }
                        else if (flags & 384) {
                            return ClassificationTypeNames.enumName;
                        }
                        else if (flags & 524288) {
                            return ClassificationTypeNames.typeAlias;
                        }
                        else if (meaningAtPosition & 2) {
                            if (flags & 64) {
                                return ClassificationTypeNames.interfaceName;
                            }
                            else if (flags & 262144) {
                                return ClassificationTypeNames.typeParameterName;
                            }
                        }
                        else if (flags & 1536) {
                            if (meaningAtPosition & 4 || (meaningAtPosition & 1 && hasValueSideModule(symbol))) {
                                return ClassificationTypeNames.moduleName;
                            }
                        }
                        return undefined;
                        function hasValueSideModule(symbol) {
                            return ts.forEach(symbol.declarations, function (declaration) {
                                return declaration.kind === 200 && ts.getModuleInstanceState(declaration) == 1;
                            });
                        }
                    }
                    function processNode(node) {
                        if (node && ts.textSpanIntersectsWith(span, node.getStart(), node.getWidth())) {
                            if (node.kind === 64 && node.getWidth() > 0) {
                                var symbol = typeInfoResolver.getSymbolAtLocation(node);
                                if (symbol) {
                                    var type = classifySymbol(symbol, getMeaningFromLocation(node));
                                    if (type) {
                                        result.push({
                                            textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                                            classificationType: type
                                        });
                                    }
                                }
                            }
                            ts.forEachChild(node, processNode);
                        }
                    }
                }
                function getSyntacticClassifications(fileName, span) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    var triviaScanner = ts.createScanner(2, false, sourceFile.text);
                    var mergeConflictScanner = ts.createScanner(2, false, sourceFile.text);
                    var result = [];
                    processElement(sourceFile);
                    return result;
                    function classifyLeadingTrivia(token) {
                        var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false);
                        if (tokenStart === token.pos) {
                            return;
                        }
                        triviaScanner.setTextPos(token.pos);
                        while (true) {
                            var start = triviaScanner.getTextPos();
                            var kind = triviaScanner.scan();
                            var end = triviaScanner.getTextPos();
                            var width = end - start;
                            if (ts.textSpanIntersectsWith(span, start, width)) {
                                if (!ts.isTrivia(kind)) {
                                    return;
                                }
                                if (ts.isComment(kind)) {
                                    result.push({
                                        textSpan: ts.createTextSpan(start, width),
                                        classificationType: ClassificationTypeNames.comment
                                    });
                                    continue;
                                }
                                if (kind === 6) {
                                    var text = sourceFile.text;
                                    var ch = text.charCodeAt(start);
                                    if (ch === 60 || ch === 62) {
                                        result.push({
                                            textSpan: ts.createTextSpan(start, width),
                                            classificationType: ClassificationTypeNames.comment
                                        });
                                        continue;
                                    }
                                    ts.Debug.assert(ch === 61);
                                    classifyDisabledMergeCode(text, start, end);
                                }
                            }
                        }
                    }
                    function classifyDisabledMergeCode(text, start, end) {
                        for (var i = start; i < end; i++) {
                            if (ts.isLineBreak(text.charCodeAt(i))) {
                                break;
                            }
                        }
                        result.push({
                            textSpan: ts.createTextSpanFromBounds(start, i),
                            classificationType: ClassificationTypeNames.comment
                        });
                        mergeConflictScanner.setTextPos(i);
                        while (mergeConflictScanner.getTextPos() < end) {
                            classifyDisabledCodeToken();
                        }
                    }
                    function classifyDisabledCodeToken() {
                        var start = mergeConflictScanner.getTextPos();
                        var tokenKind = mergeConflictScanner.scan();
                        var end = mergeConflictScanner.getTextPos();
                        var type = classifyTokenType(tokenKind);
                        if (type) {
                            result.push({
                                textSpan: ts.createTextSpanFromBounds(start, end),
                                classificationType: type
                            });
                        }
                    }
                    function classifyToken(token) {
                        classifyLeadingTrivia(token);
                        if (token.getWidth() > 0) {
                            var type = classifyTokenType(token.kind, token);
                            if (type) {
                                result.push({
                                    textSpan: ts.createTextSpan(token.getStart(), token.getWidth()),
                                    classificationType: type
                                });
                            }
                        }
                    }
                    function classifyTokenType(tokenKind, token) {
                        if (ts.isKeyword(tokenKind)) {
                            return ClassificationTypeNames.keyword;
                        }
                        if (tokenKind === 24 || tokenKind === 25) {
                            if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) {
                                return ClassificationTypeNames.punctuation;
                            }
                        }
                        if (ts.isPunctuation(tokenKind)) {
                            if (token) {
                                if (tokenKind === 52) {
                                    if (token.parent.kind === 193 || token.parent.kind === 130 || token.parent.kind === 128) {
                                        return ClassificationTypeNames.operator;
                                    }
                                }
                                if (token.parent.kind === 167 || token.parent.kind === 165 || token.parent.kind === 166 || token.parent.kind === 168) {
                                    return ClassificationTypeNames.operator;
                                }
                            }
                            return ClassificationTypeNames.punctuation;
                        }
                        else if (tokenKind === 7) {
                            return ClassificationTypeNames.numericLiteral;
                        }
                        else if (tokenKind === 8) {
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (tokenKind === 9) {
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (ts.isTemplateLiteralKind(tokenKind)) {
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (tokenKind === 64) {
                            if (token) {
                                switch (token.parent.kind) {
                                    case 196:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.className;
                                        }
                                        return;
                                    case 127:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.typeParameterName;
                                        }
                                        return;
                                    case 197:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.interfaceName;
                                        }
                                        return;
                                    case 199:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.enumName;
                                        }
                                        return;
                                    case 200:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.moduleName;
                                        }
                                        return;
                                }
                            }
                            return ClassificationTypeNames.text;
                        }
                    }
                    function processElement(element) {
                        if (ts.textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
                            var children = element.getChildren();
                            for (var i = 0, n = children.length; i < n; i++) {
                                var child = children[i];
                                if (ts.isToken(child)) {
                                    classifyToken(child);
                                }
                                else {
                                    processElement(child);
                                }
                            }
                        }
                    }
                }
                function getOutliningSpans(fileName) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.OutliningElementsCollector.collectElements(sourceFile);
                }
                function getBraceMatchingAtPosition(fileName, position) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    var result = [];
                    var token = ts.getTouchingToken(sourceFile, position);
                    if (token.getStart(sourceFile) === position) {
                        var matchKind = getMatchingTokenKind(token);
                        if (matchKind) {
                            var parentElement = token.parent;
                            var childNodes = parentElement.getChildren(sourceFile);
                            for (var i = 0, n = childNodes.length; i < n; i++) {
                                var current = childNodes[i];
                                if (current.kind === matchKind) {
                                    var range1 = ts.createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
                                    var range2 = ts.createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
                                    if (range1.start < range2.start) {
                                        result.push(range1, range2);
                                    }
                                    else {
                                        result.push(range2, range1);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    return result;
                    function getMatchingTokenKind(token) {
                        switch (token.kind) {
                            case 14:
                                return 15;
                            case 16:
                                return 17;
                            case 18:
                                return 19;
                            case 24:
                                return 25;
                            case 15:
                                return 14;
                            case 17:
                                return 16;
                            case 19:
                                return 18;
                            case 25:
                                return 24;
                        }
                        return undefined;
                    }
                }
                function getIndentationAtPosition(fileName, position, editorOptions) {
                    var start = new Date().getTime();
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
                    var start = new Date().getTime();
                    var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
                    log("getIndentationAtPosition: computeIndentation  : " + (new Date().getTime() - start));
                    return result;
                }
                function getFormattingEditsForRange(fileName, start, end, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
                }
                function getFormattingEditsForDocument(fileName, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options);
                }
                function getFormattingEditsAfterKeystroke(fileName, position, key, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    if (key === "}") {
                        return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
                    }
                    else if (key === ";") {
                        return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
                    }
                    else if (key === "\n") {
                        return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
                    }
                    return [];
                }
                function getTodoComments(fileName, descriptors) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    cancellationToken.throwIfCancellationRequested();
                    var fileContents = sourceFile.text;
                    var result = [];
                    if (descriptors.length > 0) {
                        var regExp = getTodoCommentsRegExp();
                        var matchArray;
                        while (matchArray = regExp.exec(fileContents)) {
                            cancellationToken.throwIfCancellationRequested();
                            var firstDescriptorCaptureIndex = 3;
                            ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
                            var preamble = matchArray[1];
                            var matchPosition = matchArray.index + preamble.length;
                            var token = ts.getTokenAtPosition(sourceFile, matchPosition);
                            if (!isInsideComment(sourceFile, token, matchPosition)) {
                                continue;
                            }
                            var descriptor = undefined;
                            for (var i = 0, n = descriptors.length; i < n; i++) {
                                if (matchArray[i + firstDescriptorCaptureIndex]) {
                                    descriptor = descriptors[i];
                                }
                            }
                            ts.Debug.assert(descriptor !== undefined);
                            if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
                                continue;
                            }
                            var message = matchArray[2];
                            result.push({
                                descriptor: descriptor,
                                message: message,
                                position: matchPosition
                            });
                        }
                    }
                    return result;
                    function escapeRegExp(str) {
                        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                    }
                    function getTodoCommentsRegExp() {
                        var singleLineCommentStart = /(?:\/\/+\s*)/.source;
                        var multiLineCommentStart = /(?:\/\*+\s*)/.source;
                        var anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
                        var preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
                        var literals = "(?:" + ts.map(descriptors, function (d) {
                            return "(" + escapeRegExp(d.text) + ")";
                        }).join("|") + ")";
                        var endOfLineOrEndOfComment = /(?:$|\*\/)/.source;
                        var messageRemainder = /(?:.*?)/.source;
                        var messagePortion = "(" + literals + messageRemainder + ")";
                        var regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
                        return new RegExp(regExpString, "gim");
                    }
                    function isLetterOrDigit(char) {
                        return (char >= 97 && char <= 122) || (char >= 65 && char <= 90) || (char >= 48 && char <= 57);
                    }
                }
                function getRenameInfo(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingWord(sourceFile, position);
                    if (node && node.kind === 64) {
                        var symbol = typeInfoResolver.getSymbolAtLocation(node);
                        if (symbol) {
                            var declarations = symbol.getDeclarations();
                            if (declarations && declarations.length > 0) {
                                var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
                                if (defaultLibFileName) {
                                    for (var i = 0; i < declarations.length; i++) {
                                        var sourceFile = declarations[i].getSourceFile();
                                        if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) {
                                            return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library.key));
                                        }
                                    }
                                }
                                var kind = getSymbolKind(symbol, typeInfoResolver, node);
                                if (kind) {
                                    return {
                                        canRename: true,
                                        localizedErrorMessage: undefined,
                                        displayName: symbol.name,
                                        fullDisplayName: typeInfoResolver.getFullyQualifiedName(symbol),
                                        kind: kind,
                                        kindModifiers: getSymbolModifiers(symbol),
                                        triggerSpan: ts.createTextSpan(node.getStart(), node.getWidth())
                                    };
                                }
                            }
                        }
                    }
                    return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element.key));
                    function getRenameInfoError(localizedErrorMessage) {
                        return {
                            canRename: false,
                            localizedErrorMessage: localizedErrorMessage,
                            displayName: undefined,
                            fullDisplayName: undefined,
                            kind: undefined,
                            kindModifiers: undefined,
                            triggerSpan: undefined
                        };
                    }
                }
                return {
                    dispose: dispose,
                    cleanupSemanticCache: cleanupSemanticCache,
                    getSyntacticDiagnostics: getSyntacticDiagnostics,
                    getSemanticDiagnostics: getSemanticDiagnostics,
                    getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics,
                    getSyntacticClassifications: getSyntacticClassifications,
                    getSemanticClassifications: getSemanticClassifications,
                    getCompletionsAtPosition: getCompletionsAtPosition,
                    getCompletionEntryDetails: getCompletionEntryDetails,
                    getSignatureHelpItems: getSignatureHelpItems,
                    getQuickInfoAtPosition: getQuickInfoAtPosition,
                    getDefinitionAtPosition: getDefinitionAtPosition,
                    getReferencesAtPosition: getReferencesAtPosition,
                    getOccurrencesAtPosition: getOccurrencesAtPosition,
                    getNameOrDottedNameSpan: getNameOrDottedNameSpan,
                    getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
                    getNavigateToItems: getNavigateToItems,
                    getRenameInfo: getRenameInfo,
                    findRenameLocations: findRenameLocations,
                    getNavigationBarItems: getNavigationBarItems,
                    getOutliningSpans: getOutliningSpans,
                    getTodoComments: getTodoComments,
                    getBraceMatchingAtPosition: getBraceMatchingAtPosition,
                    getIndentationAtPosition: getIndentationAtPosition,
                    getFormattingEditsForRange: getFormattingEditsForRange,
                    getFormattingEditsForDocument: getFormattingEditsForDocument,
                    getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke,
                    getEmitOutput: getEmitOutput,
                    getSourceFile: getSourceFile,
                    getProgram: getProgram
                };
            }
            ts.createLanguageService = createLanguageService;
            function getNameTable(sourceFile) {
                if (!sourceFile.nameTable) {
                    initializeNameTable(sourceFile);
                }
                return sourceFile.nameTable;
            }
            ts.getNameTable = getNameTable;
            function initializeNameTable(sourceFile) {
                var nameTable = {};
                walk(sourceFile);
                sourceFile.nameTable = nameTable;
                function walk(node) {
                    switch (node.kind) {
                        case 64:
                            nameTable[node.text] = node.text;
                            break;
                        case 8:
                        case 7:
                            if (ts.isDeclarationName(node) || node.parent.kind === 213 || isArgumentOfElementAccessExpression(node)) {
                                nameTable[node.text] = node.text;
                            }
                            break;
                        default:
                            ts.forEachChild(node, walk);
                    }
                }
            }
            function isArgumentOfElementAccessExpression(node) {
                return node && node.parent && node.parent.kind === 154 && node.parent.argumentExpression === node;
            }
            function createClassifier() {
                var scanner = ts.createScanner(2, false);
                var noRegexTable = [];
                noRegexTable[64] = true;
                noRegexTable[8] = true;
                noRegexTable[7] = true;
                noRegexTable[9] = true;
                noRegexTable[92] = true;
                noRegexTable[38] = true;
                noRegexTable[39] = true;
                noRegexTable[17] = true;
                noRegexTable[19] = true;
                noRegexTable[15] = true;
                noRegexTable[94] = true;
                noRegexTable[79] = true;
                var templateStack = [];
                function isAccessibilityModifier(kind) {
                    switch (kind) {
                        case 108:
                        case 106:
                        case 107:
                            return true;
                    }
                    return false;
                }
                function canFollow(keyword1, keyword2) {
                    if (isAccessibilityModifier(keyword1)) {
                        if (keyword2 === 115 || keyword2 === 119 || keyword2 === 113 || keyword2 === 109) {
                            return true;
                        }
                        return false;
                    }
                    return true;
                }
                function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) {
                    var offset = 0;
                    var token = 0;
                    var lastNonTriviaToken = 0;
                    while (templateStack.length > 0) {
                        templateStack.pop();
                    }
                    switch (lexState) {
                        case 3:
                            text = '"\\\n' + text;
                            offset = 3;
                            break;
                        case 2:
                            text = "'\\\n" + text;
                            offset = 3;
                            break;
                        case 1:
                            text = "/*\n" + text;
                            offset = 3;
                            break;
                        case 4:
                            text = "`\n" + text;
                            offset = 2;
                            break;
                        case 5:
                            text = "}\n" + text;
                            offset = 2;
                        case 6:
                            templateStack.push(11);
                            break;
                    }
                    scanner.setText(text);
                    var result = {
                        finalLexState: 0,
                        entries: []
                    };
                    var angleBracketStack = 0;
                    do {
                        token = scanner.scan();
                        if (!ts.isTrivia(token)) {
                            if ((token === 36 || token === 56) && !noRegexTable[lastNonTriviaToken]) {
                                if (scanner.reScanSlashToken() === 9) {
                                    token = 9;
                                }
                            }
                            else if (lastNonTriviaToken === 20 && isKeyword(token)) {
                                token = 64;
                            }
                            else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
                                token = 64;
                            }
                            else if (lastNonTriviaToken === 64 && token === 24) {
                                angleBracketStack++;
                            }
                            else if (token === 25 && angleBracketStack > 0) {
                                angleBracketStack--;
                            }
                            else if (token === 111 || token === 120 || token === 118 || token === 112 || token === 121) {
                                if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
                                    token = 64;
                                }
                            }
                            else if (token === 11) {
                                templateStack.push(token);
                            }
                            else if (token === 14) {
                                if (templateStack.length > 0) {
                                    templateStack.push(token);
                                }
                            }
                            else if (token === 15) {
                                if (templateStack.length > 0) {
                                    var lastTemplateStackToken = ts.lastOrUndefined(templateStack);
                                    if (lastTemplateStackToken === 11) {
                                        token = scanner.reScanTemplateToken();
                                        if (token === 13) {
                                            templateStack.pop();
                                        }
                                        else {
                                            ts.Debug.assert(token === 12, "Should have been a template middle. Was " + token);
                                        }
                                    }
                                    else {
                                        ts.Debug.assert(lastTemplateStackToken === 14, "Should have been an open brace. Was: " + token);
                                        templateStack.pop();
                                    }
                                }
                            }
                            lastNonTriviaToken = token;
                        }
                        processToken();
                    } while (token !== 1);
                    return result;
                    function processToken() {
                        var start = scanner.getTokenPos();
                        var end = scanner.getTextPos();
                        addResult(end - start, classFromKind(token));
                        if (end >= text.length) {
                            if (token === 8) {
                                var tokenText = scanner.getTokenText();
                                if (scanner.isUnterminated()) {
                                    var lastCharIndex = tokenText.length - 1;
                                    var numBackslashes = 0;
                                    while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92) {
                                        numBackslashes++;
                                    }
                                    if (numBackslashes & 1) {
                                        var quoteChar = tokenText.charCodeAt(0);
                                        result.finalLexState = quoteChar === 34 ? 3 : 2;
                                    }
                                }
                            }
                            else if (token === 3) {
                                if (scanner.isUnterminated()) {
                                    result.finalLexState = 1;
                                }
                            }
                            else if (ts.isTemplateLiteralKind(token)) {
                                if (scanner.isUnterminated()) {
                                    if (token === 13) {
                                        result.finalLexState = 5;
                                    }
                                    else if (token === 10) {
                                        result.finalLexState = 4;
                                    }
                                    else {
                                        ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
                                    }
                                }
                            }
                            else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11) {
                                result.finalLexState = 6;
                            }
                        }
                    }
                    function addResult(length, classification) {
                        if (length > 0) {
                            if (result.entries.length === 0) {
                                length -= offset;
                            }
                            result.entries.push({
                                length: length,
                                classification: classification
                            });
                        }
                    }
                }
                function isBinaryExpressionOperatorToken(token) {
                    switch (token) {
                        case 35:
                        case 36:
                        case 37:
                        case 33:
                        case 34:
                        case 40:
                        case 41:
                        case 42:
                        case 24:
                        case 25:
                        case 26:
                        case 27:
                        case 86:
                        case 85:
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                        case 43:
                        case 45:
                        case 44:
                        case 48:
                        case 49:
                        case 62:
                        case 61:
                        case 63:
                        case 58:
                        case 59:
                        case 60:
                        case 53:
                        case 54:
                        case 55:
                        case 56:
                        case 57:
                        case 52:
                        case 23:
                            return true;
                        default:
                            return false;
                    }
                }
                function isPrefixUnaryExpressionOperatorToken(token) {
                    switch (token) {
                        case 33:
                        case 34:
                        case 47:
                        case 46:
                        case 38:
                        case 39:
                            return true;
                        default:
                            return false;
                    }
                }
                function isKeyword(token) {
                    return token >= 65 && token <= 124;
                }
                function classFromKind(token) {
                    if (isKeyword(token)) {
                        return 1;
                    }
                    else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
                        return 2;
                    }
                    else if (token >= 14 && token <= 63) {
                        return 0;
                    }
                    switch (token) {
                        case 7:
                            return 6;
                        case 8:
                            return 7;
                        case 9:
                            return 8;
                        case 6:
                        case 3:
                        case 2:
                            return 3;
                        case 5:
                        case 4:
                            return 4;
                        case 64:
                        default:
                            if (ts.isTemplateLiteralKind(token)) {
                                return 7;
                            }
                            return 5;
                    }
                }
                return {
                    getClassificationsForLine: getClassificationsForLine
                };
            }
            ts.createClassifier = createClassifier;
            function getDefaultLibFilePath(options) {
                if (typeof __dirname !== "undefined") {
                    return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options);
                }
                throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
            }
            ts.getDefaultLibFilePath = getDefaultLibFilePath;
            function initializeServices() {
                ts.objectAllocator = {
                    getNodeConstructor: function (kind) {
                        function Node() {
                        }
                        var proto = kind === 221 ? new SourceFileObject() : new NodeObject();
                        proto.kind = kind;
                        proto.pos = 0;
                        proto.end = 0;
                        proto.flags = 0;
                        proto.parent = undefined;
                        Node.prototype = proto;
                        return Node;
                    },
                    getSymbolConstructor: function () {
                        return SymbolObject;
                    },
                    getTypeConstructor: function () {
                        return TypeObject;
                    },
                    getSignatureConstructor: function () {
                        return SignatureObject;
                    }
                };
            }
            initializeServices();
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            var BreakpointResolver;
            (function (BreakpointResolver) {
                function spanInSourceFileAtLocation(sourceFile, position) {
                    if (sourceFile.flags & 2048) {
                        return undefined;
                    }
                    var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position);
                    var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
                    if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
                        tokenAtLocation = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile);
                        if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
                            return undefined;
                        }
                    }
                    if (ts.isInAmbientContext(tokenAtLocation)) {
                        return undefined;
                    }
                    return spanInNode(tokenAtLocation);
                    function textSpan(startNode, endNode) {
                        return ts.createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
                    }
                    function spanInNodeIfStartsOnSameLine(node, otherwiseOnNode) {
                        if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
                            return spanInNode(node);
                        }
                        return spanInNode(otherwiseOnNode);
                    }
                    function spanInPreviousNode(node) {
                        return spanInNode(ts.findPrecedingToken(node.pos, sourceFile));
                    }
                    function spanInNextNode(node) {
                        return spanInNode(ts.findNextToken(node, node.parent));
                    }
                    function spanInNode(node) {
                        if (node) {
                            if (ts.isExpression(node)) {
                                if (node.parent.kind === 179) {
                                    return spanInPreviousNode(node);
                                }
                                if (node.parent.kind === 181) {
                                    return textSpan(node);
                                }
                                if (node.parent.kind === 167 && node.parent.operatorToken.kind === 23) {
                                    return textSpan(node);
                                }
                                if (node.parent.kind == 161 && node.parent.body == node) {
                                    return textSpan(node);
                                }
                            }
                            switch (node.kind) {
                                case 175:
                                    return spanInVariableDeclaration(node.declarationList.declarations[0]);
                                case 193:
                                case 130:
                                case 129:
                                    return spanInVariableDeclaration(node);
                                case 128:
                                    return spanInParameterDeclaration(node);
                                case 195:
                                case 132:
                                case 131:
                                case 134:
                                case 135:
                                case 133:
                                case 160:
                                case 161:
                                    return spanInFunctionDeclaration(node);
                                case 174:
                                    if (ts.isFunctionBlock(node)) {
                                        return spanInFunctionBlock(node);
                                    }
                                case 201:
                                    return spanInBlock(node);
                                case 217:
                                    return spanInBlock(node.block);
                                case 177:
                                    return textSpan(node.expression);
                                case 186:
                                    return textSpan(node.getChildAt(0), node.expression);
                                case 180:
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 179:
                                    return spanInNode(node.statement);
                                case 192:
                                    return textSpan(node.getChildAt(0));
                                case 178:
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 189:
                                    return spanInNode(node.statement);
                                case 185:
                                case 184:
                                    return textSpan(node.getChildAt(0), node.label);
                                case 181:
                                    return spanInForStatement(node);
                                case 182:
                                case 183:
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 188:
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 214:
                                case 215:
                                    return spanInNode(node.statements[0]);
                                case 191:
                                    return spanInBlock(node.tryBlock);
                                case 190:
                                    return textSpan(node, node.expression);
                                case 209:
                                    return textSpan(node, node.expression);
                                case 203:
                                    return textSpan(node, node.moduleReference);
                                case 204:
                                    return textSpan(node, node.moduleSpecifier);
                                case 210:
                                    return textSpan(node, node.moduleSpecifier);
                                case 200:
                                    if (ts.getModuleInstanceState(node) !== 1) {
                                        return undefined;
                                    }
                                case 196:
                                case 199:
                                case 220:
                                case 155:
                                case 156:
                                    return textSpan(node);
                                case 187:
                                    return spanInNode(node.statement);
                                case 197:
                                case 198:
                                    return undefined;
                                case 22:
                                case 1:
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile));
                                case 23:
                                    return spanInPreviousNode(node);
                                case 14:
                                    return spanInOpenBraceToken(node);
                                case 15:
                                    return spanInCloseBraceToken(node);
                                case 16:
                                    return spanInOpenParenToken(node);
                                case 17:
                                    return spanInCloseParenToken(node);
                                case 51:
                                    return spanInColonToken(node);
                                case 25:
                                case 24:
                                    return spanInGreaterThanOrLessThanToken(node);
                                case 99:
                                    return spanInWhileKeyword(node);
                                case 75:
                                case 67:
                                case 80:
                                    return spanInNextNode(node);
                                default:
                                    if (node.parent.kind === 218 && node.parent.name === node) {
                                        return spanInNode(node.parent.initializer);
                                    }
                                    if (node.parent.kind === 158 && node.parent.type === node) {
                                        return spanInNode(node.parent.expression);
                                    }
                                    if (ts.isFunctionLike(node.parent) && node.parent.type === node) {
                                        return spanInPreviousNode(node);
                                    }
                                    return spanInNode(node.parent);
                            }
                        }
                        function spanInVariableDeclaration(variableDeclaration) {
                            if (variableDeclaration.parent.parent.kind === 182 || variableDeclaration.parent.parent.kind === 183) {
                                return spanInNode(variableDeclaration.parent.parent);
                            }
                            var isParentVariableStatement = variableDeclaration.parent.parent.kind === 175;
                            var isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === 181 && ts.contains(variableDeclaration.parent.parent.initializer.declarations, variableDeclaration);
                            var declarations = isParentVariableStatement ? variableDeclaration.parent.parent.declarationList.declarations : isDeclarationOfForStatement ? variableDeclaration.parent.parent.initializer.declarations : undefined;
                            if (variableDeclaration.initializer || (variableDeclaration.flags & 1)) {
                                if (declarations && declarations[0] === variableDeclaration) {
                                    if (isParentVariableStatement) {
                                        return textSpan(variableDeclaration.parent, variableDeclaration);
                                    }
                                    else {
                                        ts.Debug.assert(isDeclarationOfForStatement);
                                        return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
                                    }
                                }
                                else {
                                    return textSpan(variableDeclaration);
                                }
                            }
                            else if (declarations && declarations[0] !== variableDeclaration) {
                                var indexOfCurrentDeclaration = ts.indexOf(declarations, variableDeclaration);
                                return spanInVariableDeclaration(declarations[indexOfCurrentDeclaration - 1]);
                            }
                        }
                        function canHaveSpanInParameterDeclaration(parameter) {
                            return !!parameter.initializer || parameter.dotDotDotToken !== undefined || !!(parameter.flags & 16) || !!(parameter.flags & 32);
                        }
                        function spanInParameterDeclaration(parameter) {
                            if (canHaveSpanInParameterDeclaration(parameter)) {
                                return textSpan(parameter);
                            }
                            else {
                                var functionDeclaration = parameter.parent;
                                var indexOfParameter = ts.indexOf(functionDeclaration.parameters, parameter);
                                if (indexOfParameter) {
                                    return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
                                }
                                else {
                                    return spanInNode(functionDeclaration.body);
                                }
                            }
                        }
                        function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) {
                            return !!(functionDeclaration.flags & 1) || (functionDeclaration.parent.kind === 196 && functionDeclaration.kind !== 133);
                        }
                        function spanInFunctionDeclaration(functionDeclaration) {
                            if (!functionDeclaration.body) {
                                return undefined;
                            }
                            if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) {
                                return textSpan(functionDeclaration);
                            }
                            return spanInNode(functionDeclaration.body);
                        }
                        function spanInFunctionBlock(block) {
                            var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
                            if (canFunctionHaveSpanInWholeDeclaration(block.parent)) {
                                return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
                            }
                            return spanInNode(nodeForSpanInBlock);
                        }
                        function spanInBlock(block) {
                            switch (block.parent.kind) {
                                case 200:
                                    if (ts.getModuleInstanceState(block.parent) !== 1) {
                                        return undefined;
                                    }
                                case 180:
                                case 178:
                                case 182:
                                case 183:
                                    return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
                                case 181:
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]);
                            }
                            return spanInNode(block.statements[0]);
                        }
                        function spanInForStatement(forStatement) {
                            if (forStatement.initializer) {
                                if (forStatement.initializer.kind === 194) {
                                    var variableDeclarationList = forStatement.initializer;
                                    if (variableDeclarationList.declarations.length > 0) {
                                        return spanInNode(variableDeclarationList.declarations[0]);
                                    }
                                }
                                else {
                                    return spanInNode(forStatement.initializer);
                                }
                            }
                            if (forStatement.condition) {
                                return textSpan(forStatement.condition);
                            }
                            if (forStatement.iterator) {
                                return textSpan(forStatement.iterator);
                            }
                        }
                        function spanInOpenBraceToken(node) {
                            switch (node.parent.kind) {
                                case 199:
                                    var enumDeclaration = node.parent;
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
                                case 196:
                                    var classDeclaration = node.parent;
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
                                case 202:
                                    return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInCloseBraceToken(node) {
                            switch (node.parent.kind) {
                                case 201:
                                    if (ts.getModuleInstanceState(node.parent.parent) !== 1) {
                                        return undefined;
                                    }
                                case 199:
                                case 196:
                                    return textSpan(node);
                                case 174:
                                    if (ts.isFunctionBlock(node.parent)) {
                                        return textSpan(node);
                                    }
                                case 217:
                                    return spanInNode(node.parent.statements[node.parent.statements.length - 1]);
                                    ;
                                case 202:
                                    var caseBlock = node.parent;
                                    var lastClause = caseBlock.clauses[caseBlock.clauses.length - 1];
                                    if (lastClause) {
                                        return spanInNode(lastClause.statements[lastClause.statements.length - 1]);
                                    }
                                    return undefined;
                                default:
                                    return spanInNode(node.parent);
                            }
                        }
                        function spanInOpenParenToken(node) {
                            if (node.parent.kind === 179) {
                                return spanInPreviousNode(node);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInCloseParenToken(node) {
                            switch (node.parent.kind) {
                                case 160:
                                case 195:
                                case 161:
                                case 132:
                                case 131:
                                case 134:
                                case 135:
                                case 133:
                                case 180:
                                case 179:
                                case 181:
                                    return spanInPreviousNode(node);
                                default:
                                    return spanInNode(node.parent);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInColonToken(node) {
                            if (ts.isFunctionLike(node.parent) || node.parent.kind === 218) {
                                return spanInPreviousNode(node);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInGreaterThanOrLessThanToken(node) {
                            if (node.parent.kind === 158) {
                                return spanInNode(node.parent.expression);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInWhileKeyword(node) {
                            if (node.parent.kind === 179) {
                                return textSpan(node, ts.findNextToken(node.parent.expression, node.parent));
                            }
                            return spanInNode(node.parent);
                        }
                    }
                }
                BreakpointResolver.spanInSourceFileAtLocation = spanInSourceFileAtLocation;
            })(BreakpointResolver = ts.BreakpointResolver || (ts.BreakpointResolver = {}));
        })(ts || (ts = {}));
        var debugObjectHost = this;
        var ts;
        (function (ts) {
            function logInternalError(logger, err) {
                logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
            }
            var ScriptSnapshotShimAdapter = (function () {
                function ScriptSnapshotShimAdapter(scriptSnapshotShim) {
                    this.scriptSnapshotShim = scriptSnapshotShim;
                    this.lineStartPositions = null;
                }
                ScriptSnapshotShimAdapter.prototype.getText = function (start, end) {
                    return this.scriptSnapshotShim.getText(start, end);
                };
                ScriptSnapshotShimAdapter.prototype.getLength = function () {
                    return this.scriptSnapshotShim.getLength();
                };
                ScriptSnapshotShimAdapter.prototype.getChangeRange = function (oldSnapshot) {
                    var oldSnapshotShim = oldSnapshot;
                    var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
                    if (encoded == null) {
                        return null;
                    }
                    var decoded = JSON.parse(encoded);
                    return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
                };
                return ScriptSnapshotShimAdapter;
            })();
            var LanguageServiceShimHostAdapter = (function () {
                function LanguageServiceShimHostAdapter(shimHost) {
                    this.shimHost = shimHost;
                }
                LanguageServiceShimHostAdapter.prototype.log = function (s) {
                    this.shimHost.log(s);
                };
                LanguageServiceShimHostAdapter.prototype.trace = function (s) {
                    this.shimHost.trace(s);
                };
                LanguageServiceShimHostAdapter.prototype.error = function (s) {
                    this.shimHost.error(s);
                };
                LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () {
                    var settingsJson = this.shimHost.getCompilationSettings();
                    if (settingsJson == null || settingsJson == "") {
                        throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
                        return null;
                    }
                    return JSON.parse(settingsJson);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () {
                    var encoded = this.shimHost.getScriptFileNames();
                    return this.files = JSON.parse(encoded);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) {
                    if (this.files && this.files.indexOf(fileName) < 0) {
                        return undefined;
                    }
                    var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
                    return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) {
                    return this.shimHost.getScriptVersion(fileName);
                };
                LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () {
                    var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
                    if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
                        return null;
                    }
                    try {
                        return JSON.parse(diagnosticMessagesJson);
                    }
                    catch (e) {
                        this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
                        return null;
                    }
                };
                LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () {
                    return this.shimHost.getCancellationToken();
                };
                LanguageServiceShimHostAdapter.prototype.getCurrentDirectory = function () {
                    return this.shimHost.getCurrentDirectory();
                };
                LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) {
                    try {
                        return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
                    }
                    catch (e) {
                        return "";
                    }
                };
                return LanguageServiceShimHostAdapter;
            })();
            ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter;
            function simpleForwardCall(logger, actionDescription, action) {
                logger.log(actionDescription);
                var start = Date.now();
                var result = action();
                var end = Date.now();
                logger.log(actionDescription + " completed in " + (end - start) + " msec");
                if (typeof (result) === "string") {
                    var str = result;
                    if (str.length > 128) {
                        str = str.substring(0, 128) + "...";
                    }
                    logger.log("  result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
                }
                return result;
            }
            function forwardJSONCall(logger, actionDescription, action) {
                try {
                    var result = simpleForwardCall(logger, actionDescription, action);
                    return JSON.stringify({
                        result: result
                    });
                }
                catch (err) {
                    if (err instanceof ts.OperationCanceledException) {
                        return JSON.stringify({
                            canceled: true
                        });
                    }
                    logInternalError(logger, err);
                    err.description = actionDescription;
                    return JSON.stringify({
                        error: err
                    });
                }
            }
            var ShimBase = (function () {
                function ShimBase(factory) {
                    this.factory = factory;
                    factory.registerShim(this);
                }
                ShimBase.prototype.dispose = function (dummy) {
                    this.factory.unregisterShim(this);
                };
                return ShimBase;
            })();
            var LanguageServiceShimObject = (function (_super) {
                __extends(LanguageServiceShimObject, _super);
                function LanguageServiceShimObject(factory, host, languageService) {
                    _super.call(this, factory);
                    this.host = host;
                    this.languageService = languageService;
                    this.logger = this.host;
                }
                LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
                    return forwardJSONCall(this.logger, actionDescription, action);
                };
                LanguageServiceShimObject.prototype.dispose = function (dummy) {
                    this.logger.log("dispose()");
                    this.languageService.dispose();
                    this.languageService = null;
                    if (debugObjectHost && debugObjectHost.CollectGarbage) {
                        debugObjectHost.CollectGarbage();
                        this.logger.log("CollectGarbage()");
                    }
                    this.logger = null;
                    _super.prototype.dispose.call(this, dummy);
                };
                LanguageServiceShimObject.prototype.refresh = function (throwOnError) {
                    this.forwardJSONCall("refresh(" + throwOnError + ")", function () {
                        return null;
                    });
                };
                LanguageServiceShimObject.prototype.cleanupSemanticCache = function () {
                    var _this = this;
                    this.forwardJSONCall("cleanupSemanticCache()", function () {
                        _this.languageService.cleanupSemanticCache();
                        return null;
                    });
                };
                LanguageServiceShimObject.prototype.realizeDiagnostics = function (diagnostics) {
                    var _this = this;
                    var newLine = this.getNewLine();
                    return diagnostics.map(function (d) {
                        return _this.realizeDiagnostic(d, newLine);
                    });
                };
                LanguageServiceShimObject.prototype.realizeDiagnostic = function (diagnostic, newLine) {
                    return {
                        message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine),
                        start: diagnostic.start,
                        length: diagnostic.length,
                        category: ts.DiagnosticCategory[diagnostic.category].toLowerCase(),
                        code: diagnostic.code
                    };
                };
                LanguageServiceShimObject.prototype.getSyntacticClassifications = function (fileName, start, length) {
                    var _this = this;
                    return this.forwardJSONCall("getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
                        var classifications = _this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length));
                        return classifications;
                    });
                };
                LanguageServiceShimObject.prototype.getSemanticClassifications = function (fileName, start, length) {
                    var _this = this;
                    return this.forwardJSONCall("getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
                        var classifications = _this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length));
                        return classifications;
                    });
                };
                LanguageServiceShimObject.prototype.getNewLine = function () {
                    return this.host.getNewLine ? this.host.getNewLine() : "\r\n";
                };
                LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getSyntacticDiagnostics('" + fileName + "')", function () {
                        var diagnostics = _this.languageService.getSyntacticDiagnostics(fileName);
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                LanguageServiceShimObject.prototype.getSemanticDiagnostics = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getSemanticDiagnostics('" + fileName + "')", function () {
                        var diagnostics = _this.languageService.getSemanticDiagnostics(fileName);
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                LanguageServiceShimObject.prototype.getCompilerOptionsDiagnostics = function () {
                    var _this = this;
                    return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () {
                        var diagnostics = _this.languageService.getCompilerOptionsDiagnostics();
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () {
                        var quickInfo = _this.languageService.getQuickInfoAtPosition(fileName, position);
                        return quickInfo;
                    });
                };
                LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
                    var _this = this;
                    return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () {
                        var spanInfo = _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
                        return spanInfo;
                    });
                };
                LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () {
                        var spanInfo = _this.languageService.getBreakpointStatementAtPosition(fileName, position);
                        return spanInfo;
                    });
                };
                LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () {
                        var signatureInfo = _this.languageService.getSignatureHelpItems(fileName, position);
                        return signatureInfo;
                    });
                };
                LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getDefinitionAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getRenameInfo(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.findRenameLocations = function (fileName, position, findInStrings, findInComments) {
                    var _this = this;
                    return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () {
                        return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
                    });
                };
                LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () {
                        var textRanges = _this.languageService.getBraceMatchingAtPosition(fileName, position);
                        return textRanges;
                    });
                };
                LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options) {
                    var _this = this;
                    return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () {
                        var localOptions = JSON.parse(options);
                        return _this.languageService.getIndentationAtPosition(fileName, position, localOptions);
                    });
                };
                LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getReferencesAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getOccurrencesAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getOccurrencesAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getOccurrencesAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ")", function () {
                        var completion = _this.languageService.getCompletionsAtPosition(fileName, position);
                        return completion;
                    });
                };
                LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName) {
                    var _this = this;
                    return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")", function () {
                        var details = _this.languageService.getCompletionEntryDetails(fileName, position, entryName);
                        return details;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
                        return edits;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsForDocument(fileName, localOptions);
                        return edits;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
                        return edits;
                    });
                };
                LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount) {
                    var _this = this;
                    return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ")", function () {
                        var items = _this.languageService.getNavigateToItems(searchValue, maxResultCount);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getNavigationBarItems('" + fileName + "')", function () {
                        var items = _this.languageService.getNavigationBarItems(fileName);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getOutliningSpans = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getOutliningSpans('" + fileName + "')", function () {
                        var items = _this.languageService.getOutliningSpans(fileName);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getTodoComments = function (fileName, descriptors) {
                    var _this = this;
                    return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () {
                        var items = _this.languageService.getTodoComments(fileName, JSON.parse(descriptors));
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () {
                        var output = _this.languageService.getEmitOutput(fileName);
                        output.emitOutputStatus = output.emitSkipped ? 1 : 0;
                        return output;
                    });
                };
                return LanguageServiceShimObject;
            })(ShimBase);
            var ClassifierShimObject = (function (_super) {
                __extends(ClassifierShimObject, _super);
                function ClassifierShimObject(factory) {
                    _super.call(this, factory);
                    this.classifier = ts.createClassifier();
                }
                ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) {
                    var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
                    var items = classification.entries;
                    var result = "";
                    for (var i = 0; i < items.length; i++) {
                        result += items[i].length + "\n";
                        result += items[i].classification + "\n";
                    }
                    result += classification.finalLexState;
                    return result;
                };
                return ClassifierShimObject;
            })(ShimBase);
            var CoreServicesShimObject = (function (_super) {
                __extends(CoreServicesShimObject, _super);
                function CoreServicesShimObject(factory, logger) {
                    _super.call(this, factory);
                    this.logger = logger;
                }
                CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
                    return forwardJSONCall(this.logger, actionDescription, action);
                };
                CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) {
                    return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () {
                        var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
                        var convertResult = {
                            referencedFiles: [],
                            importedFiles: [],
                            isLibFile: result.isLibFile
                        };
                        ts.forEach(result.referencedFiles, function (refFile) {
                            convertResult.referencedFiles.push({
                                path: ts.normalizePath(refFile.fileName),
                                position: refFile.pos,
                                length: refFile.end - refFile.pos
                            });
                        });
                        ts.forEach(result.importedFiles, function (importedFile) {
                            convertResult.importedFiles.push({
                                path: ts.normalizeSlashes(importedFile.fileName),
                                position: importedFile.pos,
                                length: importedFile.end - importedFile.pos
                            });
                        });
                        return convertResult;
                    });
                };
                CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () {
                    return this.forwardJSONCall("getDefaultCompilationSettings()", function () {
                        return ts.getDefaultCompilerOptions();
                    });
                };
                return CoreServicesShimObject;
            })(ShimBase);
            var TypeScriptServicesFactory = (function () {
                function TypeScriptServicesFactory() {
                    this._shims = [];
                    this.documentRegistry = ts.createDocumentRegistry();
                }
                TypeScriptServicesFactory.prototype.getServicesVersion = function () {
                    return ts.servicesVersion;
                };
                TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) {
                    try {
                        var hostAdapter = new LanguageServiceShimHostAdapter(host);
                        var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry);
                        return new LanguageServiceShimObject(this, host, languageService);
                    }
                    catch (err) {
                        logInternalError(host, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) {
                    try {
                        return new ClassifierShimObject(this);
                    }
                    catch (err) {
                        logInternalError(logger, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.createCoreServicesShim = function (logger) {
                    try {
                        return new CoreServicesShimObject(this, logger);
                    }
                    catch (err) {
                        logInternalError(logger, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.close = function () {
                    this._shims = [];
                    this.documentRegistry = ts.createDocumentRegistry();
                };
                TypeScriptServicesFactory.prototype.registerShim = function (shim) {
                    this._shims.push(shim);
                };
                TypeScriptServicesFactory.prototype.unregisterShim = function (shim) {
                    for (var i = 0, n = this._shims.length; i < n; i++) {
                        if (this._shims[i] === shim) {
                            delete this._shims[i];
                            return;
                        }
                    }
                    throw new Error("Invalid operation");
                };
                return TypeScriptServicesFactory;
            })();
            ts.TypeScriptServicesFactory = TypeScriptServicesFactory;
            if (typeof module !== "undefined" && module.exports) {
                module.exports = ts;
            }
        })(ts || (ts = {}));
        var TypeScript;
        (function (TypeScript) {
            var Services;
            (function (Services) {
                Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
            })(Services = TypeScript.Services || (TypeScript.Services = {}));
        })(TypeScript || (TypeScript = {}));
        
    • uglify2
      • ast.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function DEFNODE(type, props, methods, base) {
            if (arguments.length < 4) base = AST_Node;
            if (!props) props = [];
            else props = props.split(/\s+/);
            var self_props = props;
            if (base && base.PROPS)
                props = props.concat(base.PROPS);
            var code = "return function AST_" + type + "(props){ if (props) { ";
            for (var i = props.length; --i >= 0;) {
                code += "this." + props[i] + " = props." + props[i] + ";";
            }
            var proto = base && new base;
            if (proto && proto.initialize || (methods && methods.initialize))
                code += "this.initialize();";
            code += "}}";
            var ctor = new Function(code)();
            if (proto) {
                ctor.prototype = proto;
                ctor.BASE = base;
            }
            if (base) base.SUBCLASSES.push(ctor);
            ctor.prototype.CTOR = ctor;
            ctor.PROPS = props || null;
            ctor.SELF_PROPS = self_props;
            ctor.SUBCLASSES = [];
            if (type) {
                ctor.prototype.TYPE = ctor.TYPE = type;
            }
            if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
                if (/^\$/.test(i)) {
                    ctor[i.substr(1)] = methods[i];
                } else {
                    ctor.prototype[i] = methods[i];
                }
            }
            ctor.DEFMETHOD = function(name, method) {
                this.prototype[name] = method;
            };
            return ctor;
        };
        
        var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file", {
        }, null);
        
        var AST_Node = DEFNODE("Node", "start end", {
            clone: function() {
                return new this.CTOR(this);
            },
            $documentation: "Base class of all AST nodes",
            $propdoc: {
                start: "[AST_Token] The first token of this node",
                end: "[AST_Token] The last token of this node"
            },
            _walk: function(visitor) {
                return visitor._visit(this);
            },
            walk: function(visitor) {
                return this._walk(visitor); // not sure the indirection will be any help
            }
        }, null);
        
        AST_Node.warn_function = null;
        AST_Node.warn = function(txt, props) {
            if (AST_Node.warn_function)
                AST_Node.warn_function(string_template(txt, props));
        };
        
        /* -----[ statements ]----- */
        
        var AST_Statement = DEFNODE("Statement", null, {
            $documentation: "Base class of all statements",
        });
        
        var AST_Debugger = DEFNODE("Debugger", null, {
            $documentation: "Represents a debugger statement",
        }, AST_Statement);
        
        var AST_Directive = DEFNODE("Directive", "value scope quote", {
            $documentation: "Represents a directive, like \"use strict\";",
            $propdoc: {
                value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
                scope: "[AST_Scope/S] The scope that this directive affects",
                quote: "[string] the original quote character"
            },
        }, AST_Statement);
        
        var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
            $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
            $propdoc: {
                body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                });
            }
        }, AST_Statement);
        
        function walk_body(node, visitor) {
            if (node.body instanceof AST_Statement) {
                node.body._walk(visitor);
            }
            else node.body.forEach(function(stat){
                stat._walk(visitor);
            });
        };
        
        var AST_Block = DEFNODE("Block", "body", {
            $documentation: "A body of statements (usually bracketed)",
            $propdoc: {
                body: "[AST_Statement*] an array of statements"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    walk_body(this, visitor);
                });
            }
        }, AST_Statement);
        
        var AST_BlockStatement = DEFNODE("BlockStatement", null, {
            $documentation: "A block statement",
        }, AST_Block);
        
        var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
            $documentation: "The empty statement (empty block or simply a semicolon)",
            _walk: function(visitor) {
                return visitor._visit(this);
            }
        }, AST_Statement);
        
        var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
            $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
            $propdoc: {
                body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                });
            }
        }, AST_Statement);
        
        var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
            $documentation: "Statement with a label",
            $propdoc: {
                label: "[AST_Label] a label definition"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.label._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        var AST_IterationStatement = DEFNODE("IterationStatement", null, {
            $documentation: "Internal class.  All loops inherit from it."
        }, AST_StatementWithBody);
        
        var AST_DWLoop = DEFNODE("DWLoop", "condition", {
            $documentation: "Base class for do/while statements",
            $propdoc: {
                condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
            }
        }, AST_IterationStatement);
        
        var AST_Do = DEFNODE("Do", null, {
            $documentation: "A `do` statement",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                    this.condition._walk(visitor);
                });
            }
        }, AST_DWLoop);
        
        var AST_While = DEFNODE("While", null, {
            $documentation: "A `while` statement",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_DWLoop);
        
        var AST_For = DEFNODE("For", "init condition step", {
            $documentation: "A `for` statement",
            $propdoc: {
                init: "[AST_Node?] the `for` initialization code, or null if empty",
                condition: "[AST_Node?] the `for` termination clause, or null if empty",
                step: "[AST_Node?] the `for` update clause, or null if empty"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    if (this.init) this.init._walk(visitor);
                    if (this.condition) this.condition._walk(visitor);
                    if (this.step) this.step._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_IterationStatement);
        
        var AST_ForIn = DEFNODE("ForIn", "init name object", {
            $documentation: "A `for ... in` statement",
            $propdoc: {
                init: "[AST_Node] the `for/in` initialization code",
                name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
                object: "[AST_Node] the object that we're looping through"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.init._walk(visitor);
                    this.object._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_IterationStatement);
        
        var AST_With = DEFNODE("With", "expression", {
            $documentation: "A `with` statement",
            $propdoc: {
                expression: "[AST_Node] the `with` expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        /* -----[ scope and functions ]----- */
        
        var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
            $documentation: "Base class for all statements introducing a lexical scope",
            $propdoc: {
                directives: "[string*/S] an array of directives declared in this scope",
                variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
                functions: "[Object/S] like `variables`, but only lists function declarations",
                uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
                uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
                parent_scope: "[AST_Scope?/S] link to the parent scope",
                enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
                cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
            },
        }, AST_Block);
        
        var AST_Toplevel = DEFNODE("Toplevel", "globals", {
            $documentation: "The toplevel scope",
            $propdoc: {
                globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
            },
            wrap_enclose: function(arg_parameter_pairs) {
                var self = this;
                var args = [];
                var parameters = [];
        
                arg_parameter_pairs.forEach(function(pair) {
                    var splitAt = pair.lastIndexOf(":");
        
                    args.push(pair.substr(0, splitAt));
                    parameters.push(pair.substr(splitAt + 1));
                });
        
                var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
                wrapped_tl = parse(wrapped_tl);
                wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
                    if (node instanceof AST_Directive && node.value == "$ORIG") {
                        return MAP.splice(self.body);
                    }
                }));
                return wrapped_tl;
            },
            wrap_commonjs: function(name, export_all) {
                var self = this;
                var to_export = [];
                if (export_all) {
                    self.figure_out_scope();
                    self.walk(new TreeWalker(function(node){
                        if (node instanceof AST_SymbolDeclaration && node.definition().global) {
                            if (!find_if(function(n){ return n.name == node.name }, to_export))
                                to_export.push(node);
                        }
                    }));
                }
                var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
                wrapped_tl = parse(wrapped_tl);
                wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
                    if (node instanceof AST_SimpleStatement) {
                        node = node.body;
                        if (node instanceof AST_String) switch (node.getValue()) {
                          case "$ORIG":
                            return MAP.splice(self.body);
                          case "$EXPORTS":
                            var body = [];
                            to_export.forEach(function(sym){
                                body.push(new AST_SimpleStatement({
                                    body: new AST_Assign({
                                        left: new AST_Sub({
                                            expression: new AST_SymbolRef({ name: "exports" }),
                                            property: new AST_String({ value: sym.name }),
                                        }),
                                        operator: "=",
                                        right: new AST_SymbolRef(sym),
                                    }),
                                }));
                            });
                            return MAP.splice(body);
                        }
                    }
                }));
                return wrapped_tl;
            }
        }, AST_Scope);
        
        var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
            $documentation: "Base class for functions",
            $propdoc: {
                name: "[AST_SymbolDeclaration?] the name of this function",
                argnames: "[AST_SymbolFunarg*] array of function arguments",
                uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    if (this.name) this.name._walk(visitor);
                    this.argnames.forEach(function(arg){
                        arg._walk(visitor);
                    });
                    walk_body(this, visitor);
                });
            }
        }, AST_Scope);
        
        var AST_Accessor = DEFNODE("Accessor", null, {
            $documentation: "A setter/getter function.  The `name` property is always null."
        }, AST_Lambda);
        
        var AST_Function = DEFNODE("Function", null, {
            $documentation: "A function expression"
        }, AST_Lambda);
        
        var AST_Defun = DEFNODE("Defun", null, {
            $documentation: "A function definition"
        }, AST_Lambda);
        
        /* -----[ JUMPS ]----- */
        
        var AST_Jump = DEFNODE("Jump", null, {
            $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
        }, AST_Statement);
        
        var AST_Exit = DEFNODE("Exit", "value", {
            $documentation: "Base class for “exits” (`return` and `throw`)",
            $propdoc: {
                value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
            },
            _walk: function(visitor) {
                return visitor._visit(this, this.value && function(){
                    this.value._walk(visitor);
                });
            }
        }, AST_Jump);
        
        var AST_Return = DEFNODE("Return", null, {
            $documentation: "A `return` statement"
        }, AST_Exit);
        
        var AST_Throw = DEFNODE("Throw", null, {
            $documentation: "A `throw` statement"
        }, AST_Exit);
        
        var AST_LoopControl = DEFNODE("LoopControl", "label", {
            $documentation: "Base class for loop control statements (`break` and `continue`)",
            $propdoc: {
                label: "[AST_LabelRef?] the label, or null if none",
            },
            _walk: function(visitor) {
                return visitor._visit(this, this.label && function(){
                    this.label._walk(visitor);
                });
            }
        }, AST_Jump);
        
        var AST_Break = DEFNODE("Break", null, {
            $documentation: "A `break` statement"
        }, AST_LoopControl);
        
        var AST_Continue = DEFNODE("Continue", null, {
            $documentation: "A `continue` statement"
        }, AST_LoopControl);
        
        /* -----[ IF ]----- */
        
        var AST_If = DEFNODE("If", "condition alternative", {
            $documentation: "A `if` statement",
            $propdoc: {
                condition: "[AST_Node] the `if` condition",
                alternative: "[AST_Statement?] the `else` part, or null if not present"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.body._walk(visitor);
                    if (this.alternative) this.alternative._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        /* -----[ SWITCH ]----- */
        
        var AST_Switch = DEFNODE("Switch", "expression", {
            $documentation: "A `switch` statement",
            $propdoc: {
                expression: "[AST_Node] the `switch` “discriminant”"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_Block);
        
        var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
            $documentation: "Base class for `switch` branches",
        }, AST_Block);
        
        var AST_Default = DEFNODE("Default", null, {
            $documentation: "A `default` switch branch",
        }, AST_SwitchBranch);
        
        var AST_Case = DEFNODE("Case", "expression", {
            $documentation: "A `case` switch branch",
            $propdoc: {
                expression: "[AST_Node] the `case` expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_SwitchBranch);
        
        /* -----[ EXCEPTIONS ]----- */
        
        var AST_Try = DEFNODE("Try", "bcatch bfinally", {
            $documentation: "A `try` statement",
            $propdoc: {
                bcatch: "[AST_Catch?] the catch block, or null if not present",
                bfinally: "[AST_Finally?] the finally block, or null if not present"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    walk_body(this, visitor);
                    if (this.bcatch) this.bcatch._walk(visitor);
                    if (this.bfinally) this.bfinally._walk(visitor);
                });
            }
        }, AST_Block);
        
        var AST_Catch = DEFNODE("Catch", "argname", {
            $documentation: "A `catch` node; only makes sense as part of a `try` statement",
            $propdoc: {
                argname: "[AST_SymbolCatch] symbol for the exception"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.argname._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_Block);
        
        var AST_Finally = DEFNODE("Finally", null, {
            $documentation: "A `finally` node; only makes sense as part of a `try` statement"
        }, AST_Block);
        
        /* -----[ VAR/CONST ]----- */
        
        var AST_Definitions = DEFNODE("Definitions", "definitions", {
            $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
            $propdoc: {
                definitions: "[AST_VarDef*] array of variable definitions"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.definitions.forEach(function(def){
                        def._walk(visitor);
                    });
                });
            }
        }, AST_Statement);
        
        var AST_Var = DEFNODE("Var", null, {
            $documentation: "A `var` statement"
        }, AST_Definitions);
        
        var AST_Const = DEFNODE("Const", null, {
            $documentation: "A `const` statement"
        }, AST_Definitions);
        
        var AST_VarDef = DEFNODE("VarDef", "name value", {
            $documentation: "A variable declaration; only appears in a AST_Definitions node",
            $propdoc: {
                name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
                value: "[AST_Node?] initializer, or null of there's no initializer"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.name._walk(visitor);
                    if (this.value) this.value._walk(visitor);
                });
            }
        });
        
        /* -----[ OTHER ]----- */
        
        var AST_Call = DEFNODE("Call", "expression args", {
            $documentation: "A function call expression",
            $propdoc: {
                expression: "[AST_Node] expression to invoke as function",
                args: "[AST_Node*] array of arguments"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.args.forEach(function(arg){
                        arg._walk(visitor);
                    });
                });
            }
        });
        
        var AST_New = DEFNODE("New", null, {
            $documentation: "An object instantiation.  Derives from a function call since it has exactly the same properties"
        }, AST_Call);
        
        var AST_Seq = DEFNODE("Seq", "car cdr", {
            $documentation: "A sequence expression (two comma-separated expressions)",
            $propdoc: {
                car: "[AST_Node] first element in sequence",
                cdr: "[AST_Node] second element in sequence"
            },
            $cons: function(x, y) {
                var seq = new AST_Seq(x);
                seq.car = x;
                seq.cdr = y;
                return seq;
            },
            $from_array: function(array) {
                if (array.length == 0) return null;
                if (array.length == 1) return array[0].clone();
                var list = null;
                for (var i = array.length; --i >= 0;) {
                    list = AST_Seq.cons(array[i], list);
                }
                var p = list;
                while (p) {
                    if (p.cdr && !p.cdr.cdr) {
                        p.cdr = p.cdr.car;
                        break;
                    }
                    p = p.cdr;
                }
                return list;
            },
            to_array: function() {
                var p = this, a = [];
                while (p) {
                    a.push(p.car);
                    if (p.cdr && !(p.cdr instanceof AST_Seq)) {
                        a.push(p.cdr);
                        break;
                    }
                    p = p.cdr;
                }
                return a;
            },
            add: function(node) {
                var p = this;
                while (p) {
                    if (!(p.cdr instanceof AST_Seq)) {
                        var cell = AST_Seq.cons(p.cdr, node);
                        return p.cdr = cell;
                    }
                    p = p.cdr;
                }
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.car._walk(visitor);
                    if (this.cdr) this.cdr._walk(visitor);
                });
            }
        });
        
        var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
            $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
            $propdoc: {
                expression: "[AST_Node] the “container” expression",
                property: "[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
            }
        });
        
        var AST_Dot = DEFNODE("Dot", null, {
            $documentation: "A dotted property access expression",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                });
            }
        }, AST_PropAccess);
        
        var AST_Sub = DEFNODE("Sub", null, {
            $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.property._walk(visitor);
                });
            }
        }, AST_PropAccess);
        
        var AST_Unary = DEFNODE("Unary", "operator expression", {
            $documentation: "Base class for unary expressions",
            $propdoc: {
                operator: "[string] the operator",
                expression: "[AST_Node] expression that this unary operator applies to"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                });
            }
        });
        
        var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
            $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
        }, AST_Unary);
        
        var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
            $documentation: "Unary postfix expression, i.e. `i++`"
        }, AST_Unary);
        
        var AST_Binary = DEFNODE("Binary", "left operator right", {
            $documentation: "Binary expression, i.e. `a + b`",
            $propdoc: {
                left: "[AST_Node] left-hand side expression",
                operator: "[string] the operator",
                right: "[AST_Node] right-hand side expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.left._walk(visitor);
                    this.right._walk(visitor);
                });
            }
        });
        
        var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
            $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
            $propdoc: {
                condition: "[AST_Node]",
                consequent: "[AST_Node]",
                alternative: "[AST_Node]"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.consequent._walk(visitor);
                    this.alternative._walk(visitor);
                });
            }
        });
        
        var AST_Assign = DEFNODE("Assign", null, {
            $documentation: "An assignment expression — `a = b + 5`",
        }, AST_Binary);
        
        /* -----[ LITERALS ]----- */
        
        var AST_Array = DEFNODE("Array", "elements", {
            $documentation: "An array literal",
            $propdoc: {
                elements: "[AST_Node*] array of elements"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.elements.forEach(function(el){
                        el._walk(visitor);
                    });
                });
            }
        });
        
        var AST_Object = DEFNODE("Object", "properties", {
            $documentation: "An object literal",
            $propdoc: {
                properties: "[AST_ObjectProperty*] array of properties"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.properties.forEach(function(prop){
                        prop._walk(visitor);
                    });
                });
            }
        });
        
        var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
            $documentation: "Base class for literal object properties",
            $propdoc: {
                key: "[string] the property name converted to a string for ObjectKeyVal.  For setters and getters this is an arbitrary AST_Node.",
                value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.value._walk(visitor);
                });
            }
        });
        
        var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
            $documentation: "A key: value object property",
            $propdoc: {
                quote: "[string] the original quote character"
            }
        }, AST_ObjectProperty);
        
        var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
            $documentation: "An object setter property",
        }, AST_ObjectProperty);
        
        var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
            $documentation: "An object getter property",
        }, AST_ObjectProperty);
        
        var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
            $propdoc: {
                name: "[string] name of this symbol",
                scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
                thedef: "[SymbolDef/S] the definition of this symbol"
            },
            $documentation: "Base class for all symbols",
        });
        
        var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
            $documentation: "The name of a property accessor (setter/getter function)"
        }, AST_Symbol);
        
        var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
            $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
            $propdoc: {
                init: "[AST_Node*/S] array of initializers for this declaration."
            }
        }, AST_Symbol);
        
        var AST_SymbolVar = DEFNODE("SymbolVar", null, {
            $documentation: "Symbol defining a variable",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolConst = DEFNODE("SymbolConst", null, {
            $documentation: "A constant declaration"
        }, AST_SymbolDeclaration);
        
        var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
            $documentation: "Symbol naming a function argument",
        }, AST_SymbolVar);
        
        var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
            $documentation: "Symbol defining a function",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
            $documentation: "Symbol naming a function expression",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
            $documentation: "Symbol naming the exception in catch",
        }, AST_SymbolDeclaration);
        
        var AST_Label = DEFNODE("Label", "references", {
            $documentation: "Symbol naming a label (declaration)",
            $propdoc: {
                references: "[AST_LoopControl*] a list of nodes referring to this label"
            },
            initialize: function() {
                this.references = [];
                this.thedef = this;
            }
        }, AST_Symbol);
        
        var AST_SymbolRef = DEFNODE("SymbolRef", null, {
            $documentation: "Reference to some symbol (not definition/declaration)",
        }, AST_Symbol);
        
        var AST_LabelRef = DEFNODE("LabelRef", null, {
            $documentation: "Reference to a label symbol",
        }, AST_Symbol);
        
        var AST_This = DEFNODE("This", null, {
            $documentation: "The `this` symbol",
        }, AST_Symbol);
        
        var AST_Constant = DEFNODE("Constant", null, {
            $documentation: "Base class for all constants",
            getValue: function() {
                return this.value;
            }
        });
        
        var AST_String = DEFNODE("String", "value quote", {
            $documentation: "A string literal",
            $propdoc: {
                value: "[string] the contents of this string",
                quote: "[string] the original quote character"
            }
        }, AST_Constant);
        
        var AST_Number = DEFNODE("Number", "value", {
            $documentation: "A number literal",
            $propdoc: {
                value: "[number] the numeric value"
            }
        }, AST_Constant);
        
        var AST_RegExp = DEFNODE("RegExp", "value", {
            $documentation: "A regexp literal",
            $propdoc: {
                value: "[RegExp] the actual regexp"
            }
        }, AST_Constant);
        
        var AST_Atom = DEFNODE("Atom", null, {
            $documentation: "Base class for atoms",
        }, AST_Constant);
        
        var AST_Null = DEFNODE("Null", null, {
            $documentation: "The `null` atom",
            value: null
        }, AST_Atom);
        
        var AST_NaN = DEFNODE("NaN", null, {
            $documentation: "The impossible value",
            value: 0/0
        }, AST_Atom);
        
        var AST_Undefined = DEFNODE("Undefined", null, {
            $documentation: "The `undefined` value",
            value: (function(){}())
        }, AST_Atom);
        
        var AST_Hole = DEFNODE("Hole", null, {
            $documentation: "A hole in an array",
            value: (function(){}())
        }, AST_Atom);
        
        var AST_Infinity = DEFNODE("Infinity", null, {
            $documentation: "The `Infinity` value",
            value: 1/0
        }, AST_Atom);
        
        var AST_Boolean = DEFNODE("Boolean", null, {
            $documentation: "Base class for booleans",
        }, AST_Atom);
        
        var AST_False = DEFNODE("False", null, {
            $documentation: "The `false` atom",
            value: false
        }, AST_Boolean);
        
        var AST_True = DEFNODE("True", null, {
            $documentation: "The `true` atom",
            value: true
        }, AST_Boolean);
        
        /* -----[ TreeWalker ]----- */
        
        function TreeWalker(callback) {
            this.visit = callback;
            this.stack = [];
        };
        TreeWalker.prototype = {
            _visit: function(node, descend) {
                this.stack.push(node);
                var ret = this.visit(node, descend ? function(){
                    descend.call(node);
                } : noop);
                if (!ret && descend) {
                    descend.call(node);
                }
                this.stack.pop();
                return ret;
            },
            parent: function(n) {
                return this.stack[this.stack.length - 2 - (n || 0)];
            },
            push: function (node) {
                this.stack.push(node);
            },
            pop: function() {
                return this.stack.pop();
            },
            self: function() {
                return this.stack[this.stack.length - 1];
            },
            find_parent: function(type) {
                var stack = this.stack;
                for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof type) return x;
                }
            },
            has_directive: function(type) {
                return this.find_parent(AST_Scope).has_directive(type);
            },
            in_boolean_context: function() {
                var stack = this.stack;
                var i = stack.length, self = stack[--i];
                while (i > 0) {
                    var p = stack[--i];
                    if ((p instanceof AST_If           && p.condition === self) ||
                        (p instanceof AST_Conditional  && p.condition === self) ||
                        (p instanceof AST_DWLoop       && p.condition === self) ||
                        (p instanceof AST_For          && p.condition === self) ||
                        (p instanceof AST_UnaryPrefix  && p.operator == "!" && p.expression === self))
                    {
                        return true;
                    }
                    if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
                        return false;
                    self = p;
                }
            },
            loopcontrol_target: function(label) {
                var stack = this.stack;
                if (label) for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
                        return x.body;
                    }
                } else for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
                        return x;
                }
            }
        };
        
      • compress.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function Compressor(options, false_by_default) {
            if (!(this instanceof Compressor))
                return new Compressor(options, false_by_default);
            TreeTransformer.call(this, this.before, this.after);
            this.options = defaults(options, {
                sequences     : !false_by_default,
                properties    : !false_by_default,
                dead_code     : !false_by_default,
                drop_debugger : !false_by_default,
                unsafe        : false,
                unsafe_comps  : false,
                conditionals  : !false_by_default,
                comparisons   : !false_by_default,
                evaluate      : !false_by_default,
                booleans      : !false_by_default,
                loops         : !false_by_default,
                unused        : !false_by_default,
                hoist_funs    : !false_by_default,
                keep_fargs    : false,
                keep_fnames   : false,
                hoist_vars    : false,
                if_return     : !false_by_default,
                join_vars     : !false_by_default,
                cascade       : !false_by_default,
                side_effects  : !false_by_default,
                pure_getters  : false,
                pure_funcs    : null,
                negate_iife   : !false_by_default,
                screw_ie8     : false,
                drop_console  : false,
                angular       : false,
        
                warnings      : true,
                global_defs   : {}
            }, true);
        };
        
        Compressor.prototype = new TreeTransformer;
        merge(Compressor.prototype, {
            option: function(key) { return this.options[key] },
            warn: function() {
                if (this.options.warnings)
                    AST_Node.warn.apply(AST_Node, arguments);
            },
            before: function(node, descend, in_list) {
                if (node._squeezed) return node;
                var was_scope = false;
                if (node instanceof AST_Scope) {
                    node = node.hoist_declarations(this);
                    was_scope = true;
                }
                descend(node, this);
                node = node.optimize(this);
                if (was_scope && node instanceof AST_Scope) {
                    node.drop_unused(this);
                    descend(node, this);
                }
                node._squeezed = true;
                return node;
            }
        });
        
        (function(){
        
            function OPT(node, optimizer) {
                node.DEFMETHOD("optimize", function(compressor){
                    var self = this;
                    if (self._optimized) return self;
                    var opt = optimizer(self, compressor);
                    opt._optimized = true;
                    if (opt === self) return opt;
                    return opt.transform(compressor);
                });
            };
        
            OPT(AST_Node, function(self, compressor){
                return self;
            });
        
            AST_Node.DEFMETHOD("equivalent_to", function(node){
                // XXX: this is a rather expensive way to test two node's equivalence:
                return this.print_to_string() == node.print_to_string();
            });
        
            function make_node(ctor, orig, props) {
                if (!props) props = {};
                if (orig) {
                    if (!props.start) props.start = orig.start;
                    if (!props.end) props.end = orig.end;
                }
                return new ctor(props);
            };
        
            function make_node_from_constant(compressor, val, orig) {
                // XXX: WIP.
                // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){
                //     if (node instanceof AST_SymbolRef) {
                //         var scope = compressor.find_parent(AST_Scope);
                //         var def = scope.find_variable(node);
                //         node.thedef = def;
                //         return node;
                //     }
                // })).transform(compressor);
        
                if (val instanceof AST_Node) return val.transform(compressor);
                switch (typeof val) {
                  case "string":
                    return make_node(AST_String, orig, {
                        value: val
                    }).optimize(compressor);
                  case "number":
                    return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
                        value: val
                    }).optimize(compressor);
                  case "boolean":
                    return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
                  case "undefined":
                    return make_node(AST_Undefined, orig).optimize(compressor);
                  default:
                    if (val === null) {
                        return make_node(AST_Null, orig, { value: null }).optimize(compressor);
                    }
                    if (val instanceof RegExp) {
                        return make_node(AST_RegExp, orig, { value: val }).optimize(compressor);
                    }
                    throw new Error(string_template("Can't handle constant of type: {type}", {
                        type: typeof val
                    }));
                }
            };
        
            function as_statement_array(thing) {
                if (thing === null) return [];
                if (thing instanceof AST_BlockStatement) return thing.body;
                if (thing instanceof AST_EmptyStatement) return [];
                if (thing instanceof AST_Statement) return [ thing ];
                throw new Error("Can't convert thing to statement array");
            };
        
            function is_empty(thing) {
                if (thing === null) return true;
                if (thing instanceof AST_EmptyStatement) return true;
                if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
                return false;
            };
        
            function loop_body(x) {
                if (x instanceof AST_Switch) return x;
                if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
                    return (x.body instanceof AST_BlockStatement ? x.body : x);
                }
                return x;
            };
        
            function tighten_body(statements, compressor) {
                var CHANGED;
                do {
                    CHANGED = false;
                    if (compressor.option("angular")) {
                        statements = process_for_angular(statements);
                    }
                    statements = eliminate_spurious_blocks(statements);
                    if (compressor.option("dead_code")) {
                        statements = eliminate_dead_code(statements, compressor);
                    }
                    if (compressor.option("if_return")) {
                        statements = handle_if_return(statements, compressor);
                    }
                    if (compressor.option("sequences")) {
                        statements = sequencesize(statements, compressor);
                    }
                    if (compressor.option("join_vars")) {
                        statements = join_consecutive_vars(statements, compressor);
                    }
                } while (CHANGED);
        
                if (compressor.option("negate_iife")) {
                    negate_iifes(statements, compressor);
                }
        
                return statements;
        
                function process_for_angular(statements) {
                    function has_inject(comment) {
                        return /@ngInject/.test(comment.value);
                    }
                    function make_arguments_names_list(func) {
                        return func.argnames.map(function(sym){
                            return make_node(AST_String, sym, { value: sym.name });
                        });
                    }
                    function make_array(orig, elements) {
                        return make_node(AST_Array, orig, { elements: elements });
                    }
                    function make_injector(func, name) {
                        return make_node(AST_SimpleStatement, func, {
                            body: make_node(AST_Assign, func, {
                                operator: "=",
                                left: make_node(AST_Dot, name, {
                                    expression: make_node(AST_SymbolRef, name, name),
                                    property: "$inject"
                                }),
                                right: make_array(func, make_arguments_names_list(func))
                            })
                        });
                    }
                    function check_expression(body) {
                        if (body && body.args) {
                            // if this is a function call check all of arguments passed
                            body.args.forEach(function(argument, index, array) {
                                var comments = argument.start.comments_before;
                                // if the argument is function preceded by @ngInject
                                if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) {
                                    // replace the function with an array of names of its parameters and function at the end
                                    array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument));
                                }
                            });
                            // if this is chained call check previous one recursively
                            if (body.expression && body.expression.expression) {
                                check_expression(body.expression.expression);
                            }
                        }
                    }
                    return statements.reduce(function(a, stat){
                        a.push(stat);
        
                        if (stat.body && stat.body.args) {
                            check_expression(stat.body);
                        } else {
                            var token = stat.start;
                            var comments = token.comments_before;
                            if (comments && comments.length > 0) {
                                var last = comments.pop();
                                if (has_inject(last)) {
                                    // case 1: defun
                                    if (stat instanceof AST_Defun) {
                                        a.push(make_injector(stat, stat.name));
                                    }
                                    else if (stat instanceof AST_Definitions) {
                                        stat.definitions.forEach(function(def) {
                                            if (def.value && def.value instanceof AST_Lambda) {
                                                a.push(make_injector(def.value, def.name));
                                            }
                                        });
                                    }
                                    else {
                                        compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token);
                                    }
                                }
                            }
                        }
        
                        return a;
                    }, []);
                }
        
                function eliminate_spurious_blocks(statements) {
                    var seen_dirs = [];
                    return statements.reduce(function(a, stat){
                        if (stat instanceof AST_BlockStatement) {
                            CHANGED = true;
                            a.push.apply(a, eliminate_spurious_blocks(stat.body));
                        } else if (stat instanceof AST_EmptyStatement) {
                            CHANGED = true;
                        } else if (stat instanceof AST_Directive) {
                            if (seen_dirs.indexOf(stat.value) < 0) {
                                a.push(stat);
                                seen_dirs.push(stat.value);
                            } else {
                                CHANGED = true;
                            }
                        } else {
                            a.push(stat);
                        }
                        return a;
                    }, []);
                };
        
                function handle_if_return(statements, compressor) {
                    var self = compressor.self();
                    var in_lambda = self instanceof AST_Lambda;
                    var ret = [];
                    loop: for (var i = statements.length; --i >= 0;) {
                        var stat = statements[i];
                        switch (true) {
                          case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0):
                            CHANGED = true;
                            // note, ret.length is probably always zero
                            // because we drop unreachable code before this
                            // step.  nevertheless, it's good to check.
                            continue loop;
                          case stat instanceof AST_If:
                            if (stat.body instanceof AST_Return) {
                                //---
                                // pretty silly case, but:
                                // if (foo()) return; return; ==> foo(); return;
                                if (((in_lambda && ret.length == 0)
                                     || (ret[0] instanceof AST_Return && !ret[0].value))
                                    && !stat.body.value && !stat.alternative) {
                                    CHANGED = true;
                                    var cond = make_node(AST_SimpleStatement, stat.condition, {
                                        body: stat.condition
                                    });
                                    ret.unshift(cond);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return x; return y; ==> return foo() ? x : y;
                                if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.alternative = ret[0];
                                    ret[0] = stat.transform(compressor);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
                                if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.alternative = ret[0] || make_node(AST_Return, stat, {
                                        value: make_node(AST_Undefined, stat)
                                    });
                                    ret[0] = stat.transform(compressor);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
                                if (!stat.body.value && in_lambda) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.condition = stat.condition.negate(compressor);
                                    stat.body = make_node(AST_BlockStatement, stat, {
                                        body: as_statement_array(stat.alternative).concat(ret)
                                    });
                                    stat.alternative = null;
                                    ret = [ stat.transform(compressor) ];
                                    continue loop;
                                }
                                //---
                                if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
                                    && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
                                    CHANGED = true;
                                    ret.push(make_node(AST_Return, ret[0], {
                                        value: make_node(AST_Undefined, ret[0])
                                    }).transform(compressor));
                                    ret = as_statement_array(stat.alternative).concat(ret);
                                    ret.unshift(stat);
                                    continue loop;
                                }
                            }
        
                            var ab = aborts(stat.body);
                            var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                            if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                       || (ab instanceof AST_Continue && self === loop_body(lct))
                                       || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
                                if (ab.label) {
                                    remove(ab.label.thedef.references, ab);
                                }
                                CHANGED = true;
                                var body = as_statement_array(stat.body).slice(0, -1);
                                stat = stat.clone();
                                stat.condition = stat.condition.negate(compressor);
                                stat.body = make_node(AST_BlockStatement, stat, {
                                    body: as_statement_array(stat.alternative).concat(ret)
                                });
                                stat.alternative = make_node(AST_BlockStatement, stat, {
                                    body: body
                                });
                                ret = [ stat.transform(compressor) ];
                                continue loop;
                            }
        
                            var ab = aborts(stat.alternative);
                            var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                            if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                       || (ab instanceof AST_Continue && self === loop_body(lct))
                                       || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
                                if (ab.label) {
                                    remove(ab.label.thedef.references, ab);
                                }
                                CHANGED = true;
                                stat = stat.clone();
                                stat.body = make_node(AST_BlockStatement, stat.body, {
                                    body: as_statement_array(stat.body).concat(ret)
                                });
                                stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
                                    body: as_statement_array(stat.alternative).slice(0, -1)
                                });
                                ret = [ stat.transform(compressor) ];
                                continue loop;
                            }
        
                            ret.unshift(stat);
                            break;
                          default:
                            ret.unshift(stat);
                            break;
                        }
                    }
                    return ret;
                };
        
                function eliminate_dead_code(statements, compressor) {
                    var has_quit = false;
                    var orig = statements.length;
                    var self = compressor.self();
                    statements = statements.reduce(function(a, stat){
                        if (has_quit) {
                            extract_declarations_from_unreachable_code(compressor, stat, a);
                        } else {
                            if (stat instanceof AST_LoopControl) {
                                var lct = compressor.loopcontrol_target(stat.label);
                                if ((stat instanceof AST_Break
                                     && lct instanceof AST_BlockStatement
                                     && loop_body(lct) === self) || (stat instanceof AST_Continue
                                                                     && loop_body(lct) === self)) {
                                    if (stat.label) {
                                        remove(stat.label.thedef.references, stat);
                                    }
                                } else {
                                    a.push(stat);
                                }
                            } else {
                                a.push(stat);
                            }
                            if (aborts(stat)) has_quit = true;
                        }
                        return a;
                    }, []);
                    CHANGED = statements.length != orig;
                    return statements;
                };
        
                function sequencesize(statements, compressor) {
                    if (statements.length < 2) return statements;
                    var seq = [], ret = [];
                    function push_seq() {
                        seq = AST_Seq.from_array(seq);
                        if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
                            body: seq
                        }));
                        seq = [];
                    };
                    statements.forEach(function(stat){
                        if (stat instanceof AST_SimpleStatement) seq.push(stat.body);
                        else push_seq(), ret.push(stat);
                    });
                    push_seq();
                    ret = sequencesize_2(ret, compressor);
                    CHANGED = ret.length != statements.length;
                    return ret;
                };
        
                function sequencesize_2(statements, compressor) {
                    function cons_seq(right) {
                        ret.pop();
                        var left = prev.body;
                        if (left instanceof AST_Seq) {
                            left.add(right);
                        } else {
                            left = AST_Seq.cons(left, right);
                        }
                        return left.transform(compressor);
                    };
                    var ret = [], prev = null;
                    statements.forEach(function(stat){
                        if (prev) {
                            if (stat instanceof AST_For) {
                                var opera = {};
                                try {
                                    prev.body.walk(new TreeWalker(function(node){
                                        if (node instanceof AST_Binary && node.operator == "in")
                                            throw opera;
                                    }));
                                    if (stat.init && !(stat.init instanceof AST_Definitions)) {
                                        stat.init = cons_seq(stat.init);
                                    }
                                    else if (!stat.init) {
                                        stat.init = prev.body;
                                        ret.pop();
                                    }
                                } catch(ex) {
                                    if (ex !== opera) throw ex;
                                }
                            }
                            else if (stat instanceof AST_If) {
                                stat.condition = cons_seq(stat.condition);
                            }
                            else if (stat instanceof AST_With) {
                                stat.expression = cons_seq(stat.expression);
                            }
                            else if (stat instanceof AST_Exit && stat.value) {
                                stat.value = cons_seq(stat.value);
                            }
                            else if (stat instanceof AST_Exit) {
                                stat.value = cons_seq(make_node(AST_Undefined, stat));
                            }
                            else if (stat instanceof AST_Switch) {
                                stat.expression = cons_seq(stat.expression);
                            }
                        }
                        ret.push(stat);
                        prev = stat instanceof AST_SimpleStatement ? stat : null;
                    });
                    return ret;
                };
        
                function join_consecutive_vars(statements, compressor) {
                    var prev = null;
                    return statements.reduce(function(a, stat){
                        if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
                            prev.definitions = prev.definitions.concat(stat.definitions);
                            CHANGED = true;
                        }
                        else if (stat instanceof AST_For
                                 && prev instanceof AST_Definitions
                                 && (!stat.init || stat.init.TYPE == prev.TYPE)) {
                            CHANGED = true;
                            a.pop();
                            if (stat.init) {
                                stat.init.definitions = prev.definitions.concat(stat.init.definitions);
                            } else {
                                stat.init = prev;
                            }
                            a.push(stat);
                            prev = stat;
                        }
                        else {
                            prev = stat;
                            a.push(stat);
                        }
                        return a;
                    }, []);
                };
        
                function negate_iifes(statements, compressor) {
                    statements.forEach(function(stat){
                        if (stat instanceof AST_SimpleStatement) {
                            stat.body = (function transform(thing) {
                                return thing.transform(new TreeTransformer(function(node){
                                    if (node instanceof AST_Call && node.expression instanceof AST_Function) {
                                        return make_node(AST_UnaryPrefix, node, {
                                            operator: "!",
                                            expression: node
                                        });
                                    }
                                    else if (node instanceof AST_Call) {
                                        node.expression = transform(node.expression);
                                    }
                                    else if (node instanceof AST_Seq) {
                                        node.car = transform(node.car);
                                    }
                                    else if (node instanceof AST_Conditional) {
                                        var expr = transform(node.condition);
                                        if (expr !== node.condition) {
                                            // it has been negated, reverse
                                            node.condition = expr;
                                            var tmp = node.consequent;
                                            node.consequent = node.alternative;
                                            node.alternative = tmp;
                                        }
                                    }
                                    return node;
                                }));
                            })(stat.body);
                        }
                    });
                };
        
            };
        
            function extract_declarations_from_unreachable_code(compressor, stat, target) {
                compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
                stat.walk(new TreeWalker(function(node){
                    if (node instanceof AST_Definitions) {
                        compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
                        node.remove_initializers();
                        target.push(node);
                        return true;
                    }
                    if (node instanceof AST_Defun) {
                        target.push(node);
                        return true;
                    }
                    if (node instanceof AST_Scope) {
                        return true;
                    }
                }));
            };
        
            /* -----[ boolean/negation helpers ]----- */
        
            // methods to determine whether an expression has a boolean result type
            (function (def){
                var unary_bool = [ "!", "delete" ];
                var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
                def(AST_Node, function(){ return false });
                def(AST_UnaryPrefix, function(){
                    return member(this.operator, unary_bool);
                });
                def(AST_Binary, function(){
                    return member(this.operator, binary_bool) ||
                        ( (this.operator == "&&" || this.operator == "||") &&
                          this.left.is_boolean() && this.right.is_boolean() );
                });
                def(AST_Conditional, function(){
                    return this.consequent.is_boolean() && this.alternative.is_boolean();
                });
                def(AST_Assign, function(){
                    return this.operator == "=" && this.right.is_boolean();
                });
                def(AST_Seq, function(){
                    return this.cdr.is_boolean();
                });
                def(AST_True, function(){ return true });
                def(AST_False, function(){ return true });
            })(function(node, func){
                node.DEFMETHOD("is_boolean", func);
            });
        
            // methods to determine if an expression has a string result type
            (function (def){
                def(AST_Node, function(){ return false });
                def(AST_String, function(){ return true });
                def(AST_UnaryPrefix, function(){
                    return this.operator == "typeof";
                });
                def(AST_Binary, function(compressor){
                    return this.operator == "+" &&
                        (this.left.is_string(compressor) || this.right.is_string(compressor));
                });
                def(AST_Assign, function(compressor){
                    return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
                });
                def(AST_Seq, function(compressor){
                    return this.cdr.is_string(compressor);
                });
                def(AST_Conditional, function(compressor){
                    return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
                });
                def(AST_Call, function(compressor){
                    return compressor.option("unsafe")
                        && this.expression instanceof AST_SymbolRef
                        && this.expression.name == "String"
                        && this.expression.undeclared();
                });
            })(function(node, func){
                node.DEFMETHOD("is_string", func);
            });
        
            function best_of(ast1, ast2) {
                return ast1.print_to_string().length >
                    ast2.print_to_string().length
                    ? ast2 : ast1;
            };
        
            // methods to evaluate a constant expression
            (function (def){
                // The evaluate method returns an array with one or two
                // elements.  If the node has been successfully reduced to a
                // constant, then the second element tells us the value;
                // otherwise the second element is missing.  The first element
                // of the array is always an AST_Node descendant; if
                // evaluation was successful it's a node that represents the
                // constant; otherwise it's the original or a replacement node.
                AST_Node.DEFMETHOD("evaluate", function(compressor){
                    if (!compressor.option("evaluate")) return [ this ];
                    try {
                        var val = this._eval(compressor);
                        return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
                    } catch(ex) {
                        if (ex !== def) throw ex;
                        return [ this ];
                    }
                });
                def(AST_Statement, function(){
                    throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
                });
                def(AST_Function, function(){
                    // XXX: AST_Function inherits from AST_Scope, which itself
                    // inherits from AST_Statement; however, an AST_Function
                    // isn't really a statement.  This could byte in other
                    // places too. :-( Wish JS had multiple inheritance.
                    throw def;
                });
                function ev(node, compressor) {
                    if (!compressor) throw new Error("Compressor must be passed");
        
                    return node._eval(compressor);
                };
                def(AST_Node, function(){
                    throw def;          // not constant
                });
                def(AST_Constant, function(){
                    return this.getValue();
                });
                def(AST_UnaryPrefix, function(compressor){
                    var e = this.expression;
                    switch (this.operator) {
                      case "!": return !ev(e, compressor);
                      case "typeof":
                        // Function would be evaluated to an array and so typeof would
                        // incorrectly return 'object'. Hence making is a special case.
                        if (e instanceof AST_Function) return typeof function(){};
        
                        e = ev(e, compressor);
        
                        // typeof <RegExp> returns "object" or "function" on different platforms
                        // so cannot evaluate reliably
                        if (e instanceof RegExp) throw def;
        
                        return typeof e;
                      case "void": return void ev(e, compressor);
                      case "~": return ~ev(e, compressor);
                      case "-":
                        e = ev(e, compressor);
                        if (e === 0) throw def;
                        return -e;
                      case "+": return +ev(e, compressor);
                    }
                    throw def;
                });
                def(AST_Binary, function(c){
                    var left = this.left, right = this.right;
                    switch (this.operator) {
                      case "&&"         : return ev(left, c) &&         ev(right, c);
                      case "||"         : return ev(left, c) ||         ev(right, c);
                      case "|"          : return ev(left, c) |          ev(right, c);
                      case "&"          : return ev(left, c) &          ev(right, c);
                      case "^"          : return ev(left, c) ^          ev(right, c);
                      case "+"          : return ev(left, c) +          ev(right, c);
                      case "*"          : return ev(left, c) *          ev(right, c);
                      case "/"          : return ev(left, c) /          ev(right, c);
                      case "%"          : return ev(left, c) %          ev(right, c);
                      case "-"          : return ev(left, c) -          ev(right, c);
                      case "<<"         : return ev(left, c) <<         ev(right, c);
                      case ">>"         : return ev(left, c) >>         ev(right, c);
                      case ">>>"        : return ev(left, c) >>>        ev(right, c);
                      case "=="         : return ev(left, c) ==         ev(right, c);
                      case "==="        : return ev(left, c) ===        ev(right, c);
                      case "!="         : return ev(left, c) !=         ev(right, c);
                      case "!=="        : return ev(left, c) !==        ev(right, c);
                      case "<"          : return ev(left, c) <          ev(right, c);
                      case "<="         : return ev(left, c) <=         ev(right, c);
                      case ">"          : return ev(left, c) >          ev(right, c);
                      case ">="         : return ev(left, c) >=         ev(right, c);
                      case "in"         : return ev(left, c) in         ev(right, c);
                      case "instanceof" : return ev(left, c) instanceof ev(right, c);
                    }
                    throw def;
                });
                def(AST_Conditional, function(compressor){
                    return ev(this.condition, compressor)
                        ? ev(this.consequent, compressor)
                        : ev(this.alternative, compressor);
                });
                def(AST_SymbolRef, function(compressor){
                    var d = this.definition();
                    if (d && d.constant && d.init) return ev(d.init, compressor);
                    throw def;
                });
                def(AST_Dot, function(compressor){
                    if (compressor.option("unsafe") && this.property == "length") {
                        var str = ev(this.expression, compressor);
                        if (typeof str == "string")
                            return str.length;
                    }
                    throw def;
                });
            })(function(node, func){
                node.DEFMETHOD("_eval", func);
            });
        
            // method to negate an expression
            (function(def){
                function basic_negation(exp) {
                    return make_node(AST_UnaryPrefix, exp, {
                        operator: "!",
                        expression: exp
                    });
                };
                def(AST_Node, function(){
                    return basic_negation(this);
                });
                def(AST_Statement, function(){
                    throw new Error("Cannot negate a statement");
                });
                def(AST_Function, function(){
                    return basic_negation(this);
                });
                def(AST_UnaryPrefix, function(){
                    if (this.operator == "!")
                        return this.expression;
                    return basic_negation(this);
                });
                def(AST_Seq, function(compressor){
                    var self = this.clone();
                    self.cdr = self.cdr.negate(compressor);
                    return self;
                });
                def(AST_Conditional, function(compressor){
                    var self = this.clone();
                    self.consequent = self.consequent.negate(compressor);
                    self.alternative = self.alternative.negate(compressor);
                    return best_of(basic_negation(this), self);
                });
                def(AST_Binary, function(compressor){
                    var self = this.clone(), op = this.operator;
                    if (compressor.option("unsafe_comps")) {
                        switch (op) {
                          case "<=" : self.operator = ">"  ; return self;
                          case "<"  : self.operator = ">=" ; return self;
                          case ">=" : self.operator = "<"  ; return self;
                          case ">"  : self.operator = "<=" ; return self;
                        }
                    }
                    switch (op) {
                      case "==" : self.operator = "!="; return self;
                      case "!=" : self.operator = "=="; return self;
                      case "===": self.operator = "!=="; return self;
                      case "!==": self.operator = "==="; return self;
                      case "&&":
                        self.operator = "||";
                        self.left = self.left.negate(compressor);
                        self.right = self.right.negate(compressor);
                        return best_of(basic_negation(this), self);
                      case "||":
                        self.operator = "&&";
                        self.left = self.left.negate(compressor);
                        self.right = self.right.negate(compressor);
                        return best_of(basic_negation(this), self);
                    }
                    return basic_negation(this);
                });
            })(function(node, func){
                node.DEFMETHOD("negate", function(compressor){
                    return func.call(this, compressor);
                });
            });
        
            // determine if expression has side effects
            (function(def){
                def(AST_Node, function(compressor){ return true });
        
                def(AST_EmptyStatement, function(compressor){ return false });
                def(AST_Constant, function(compressor){ return false });
                def(AST_This, function(compressor){ return false });
        
                def(AST_Call, function(compressor){
                    var pure = compressor.option("pure_funcs");
                    if (!pure) return true;
                    return pure.indexOf(this.expression.print_to_string()) < 0;
                });
        
                def(AST_Block, function(compressor){
                    for (var i = this.body.length; --i >= 0;) {
                        if (this.body[i].has_side_effects(compressor))
                            return true;
                    }
                    return false;
                });
        
                def(AST_SimpleStatement, function(compressor){
                    return this.body.has_side_effects(compressor);
                });
                def(AST_Defun, function(compressor){ return true });
                def(AST_Function, function(compressor){ return false });
                def(AST_Binary, function(compressor){
                    return this.left.has_side_effects(compressor)
                        || this.right.has_side_effects(compressor);
                });
                def(AST_Assign, function(compressor){ return true });
                def(AST_Conditional, function(compressor){
                    return this.condition.has_side_effects(compressor)
                        || this.consequent.has_side_effects(compressor)
                        || this.alternative.has_side_effects(compressor);
                });
                def(AST_Unary, function(compressor){
                    return this.operator == "delete"
                        || this.operator == "++"
                        || this.operator == "--"
                        || this.expression.has_side_effects(compressor);
                });
                def(AST_SymbolRef, function(compressor){
                    return this.global() && this.undeclared();
                });
                def(AST_Object, function(compressor){
                    for (var i = this.properties.length; --i >= 0;)
                        if (this.properties[i].has_side_effects(compressor))
                            return true;
                    return false;
                });
                def(AST_ObjectProperty, function(compressor){
                    return this.value.has_side_effects(compressor);
                });
                def(AST_Array, function(compressor){
                    for (var i = this.elements.length; --i >= 0;)
                        if (this.elements[i].has_side_effects(compressor))
                            return true;
                    return false;
                });
                def(AST_Dot, function(compressor){
                    if (!compressor.option("pure_getters")) return true;
                    return this.expression.has_side_effects(compressor);
                });
                def(AST_Sub, function(compressor){
                    if (!compressor.option("pure_getters")) return true;
                    return this.expression.has_side_effects(compressor)
                        || this.property.has_side_effects(compressor);
                });
                def(AST_PropAccess, function(compressor){
                    return !compressor.option("pure_getters");
                });
                def(AST_Seq, function(compressor){
                    return this.car.has_side_effects(compressor)
                        || this.cdr.has_side_effects(compressor);
                });
            })(function(node, func){
                node.DEFMETHOD("has_side_effects", func);
            });
        
            // tell me if a statement aborts
            function aborts(thing) {
                return thing && thing.aborts();
            };
            (function(def){
                def(AST_Statement, function(){ return null });
                def(AST_Jump, function(){ return this });
                function block_aborts(){
                    var n = this.body.length;
                    return n > 0 && aborts(this.body[n - 1]);
                };
                def(AST_BlockStatement, block_aborts);
                def(AST_SwitchBranch, block_aborts);
                def(AST_If, function(){
                    return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
                });
            })(function(node, func){
                node.DEFMETHOD("aborts", func);
            });
        
            /* -----[ optimizers ]----- */
        
            OPT(AST_Directive, function(self, compressor){
                if (self.scope.has_directive(self.value) !== self.scope) {
                    return make_node(AST_EmptyStatement, self);
                }
                return self;
            });
        
            OPT(AST_Debugger, function(self, compressor){
                if (compressor.option("drop_debugger"))
                    return make_node(AST_EmptyStatement, self);
                return self;
            });
        
            OPT(AST_LabeledStatement, function(self, compressor){
                if (self.body instanceof AST_Break
                    && compressor.loopcontrol_target(self.body.label) === self.body) {
                    return make_node(AST_EmptyStatement, self);
                }
                return self.label.references.length == 0 ? self.body : self;
            });
        
            OPT(AST_Block, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            OPT(AST_BlockStatement, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                switch (self.body.length) {
                  case 1: return self.body[0];
                  case 0: return make_node(AST_EmptyStatement, self);
                }
                return self;
            });
        
            AST_Scope.DEFMETHOD("drop_unused", function(compressor){
                var self = this;
                if (compressor.option("unused")
                    && !(self instanceof AST_Toplevel)
                    && !self.uses_eval
                   ) {
                    var in_use = [];
                    var initializations = new Dictionary();
                    // pass 1: find out which symbols are directly used in
                    // this scope (not in nested scopes).
                    var scope = this;
                    var tw = new TreeWalker(function(node, descend){
                        if (node !== self) {
                            if (node instanceof AST_Defun) {
                                initializations.add(node.name.name, node);
                                return true; // don't go in nested scopes
                            }
                            if (node instanceof AST_Definitions && scope === self) {
                                node.definitions.forEach(function(def){
                                    if (def.value) {
                                        initializations.add(def.name.name, def.value);
                                        if (def.value.has_side_effects(compressor)) {
                                            def.value.walk(tw);
                                        }
                                    }
                                });
                                return true;
                            }
                            if (node instanceof AST_SymbolRef) {
                                push_uniq(in_use, node.definition());
                                return true;
                            }
                            if (node instanceof AST_Scope) {
                                var save_scope = scope;
                                scope = node;
                                descend();
                                scope = save_scope;
                                return true;
                            }
                        }
                    });
                    self.walk(tw);
                    // pass 2: for every used symbol we need to walk its
                    // initialization code to figure out if it uses other
                    // symbols (that may not be in_use).
                    for (var i = 0; i < in_use.length; ++i) {
                        in_use[i].orig.forEach(function(decl){
                            // undeclared globals will be instanceof AST_SymbolRef
                            var init = initializations.get(decl.name);
                            if (init) init.forEach(function(init){
                                var tw = new TreeWalker(function(node){
                                    if (node instanceof AST_SymbolRef) {
                                        push_uniq(in_use, node.definition());
                                    }
                                });
                                init.walk(tw);
                            });
                        });
                    }
                    // pass 3: we should drop declarations not in_use
                    var tt = new TreeTransformer(
                        function before(node, descend, in_list) {
                            if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
                                if (!compressor.option("keep_fargs")) {
                                    for (var a = node.argnames, i = a.length; --i >= 0;) {
                                        var sym = a[i];
                                        if (sym.unreferenced()) {
                                            a.pop();
                                            compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
                                                name : sym.name,
                                                file : sym.start.file,
                                                line : sym.start.line,
                                                col  : sym.start.col
                                            });
                                        }
                                        else break;
                                    }
                                }
                            }
                            if (node instanceof AST_Defun && node !== self) {
                                if (!member(node.name.definition(), in_use)) {
                                    compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
                                        name : node.name.name,
                                        file : node.name.start.file,
                                        line : node.name.start.line,
                                        col  : node.name.start.col
                                    });
                                    return make_node(AST_EmptyStatement, node);
                                }
                                return node;
                            }
                            if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
                                var def = node.definitions.filter(function(def){
                                    if (member(def.name.definition(), in_use)) return true;
                                    var w = {
                                        name : def.name.name,
                                        file : def.name.start.file,
                                        line : def.name.start.line,
                                        col  : def.name.start.col
                                    };
                                    if (def.value && def.value.has_side_effects(compressor)) {
                                        def._unused_side_effects = true;
                                        compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
                                        return true;
                                    }
                                    compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
                                    return false;
                                });
                                // place uninitialized names at the start
                                def = mergeSort(def, function(a, b){
                                    if (!a.value && b.value) return -1;
                                    if (!b.value && a.value) return 1;
                                    return 0;
                                });
                                // for unused names whose initialization has
                                // side effects, we can cascade the init. code
                                // into the next one, or next statement.
                                var side_effects = [];
                                for (var i = 0; i < def.length;) {
                                    var x = def[i];
                                    if (x._unused_side_effects) {
                                        side_effects.push(x.value);
                                        def.splice(i, 1);
                                    } else {
                                        if (side_effects.length > 0) {
                                            side_effects.push(x.value);
                                            x.value = AST_Seq.from_array(side_effects);
                                            side_effects = [];
                                        }
                                        ++i;
                                    }
                                }
                                if (side_effects.length > 0) {
                                    side_effects = make_node(AST_BlockStatement, node, {
                                        body: [ make_node(AST_SimpleStatement, node, {
                                            body: AST_Seq.from_array(side_effects)
                                        }) ]
                                    });
                                } else {
                                    side_effects = null;
                                }
                                if (def.length == 0 && !side_effects) {
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (def.length == 0) {
                                    return side_effects;
                                }
                                node.definitions = def;
                                if (side_effects) {
                                    side_effects.body.unshift(node);
                                    node = side_effects;
                                }
                                return node;
                            }
                            if (node instanceof AST_For) {
                                descend(node, this);
        
                                if (node.init instanceof AST_BlockStatement) {
                                    // certain combination of unused name + side effect leads to:
                                    //    https://github.com/mishoo/UglifyJS2/issues/44
                                    // that's an invalid AST.
                                    // We fix it at this stage by moving the `var` outside the `for`.
        
                                    var body = node.init.body.slice(0, -1);
                                    node.init = node.init.body.slice(-1)[0].body;
                                    body.push(node);
        
                                    return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
                                        body: body
                                    });
                                }
                            }
                            if (node instanceof AST_Scope && node !== self)
                                return node;
                        }
                    );
                    self.transform(tt);
                }
            });
        
            AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
                var hoist_funs = compressor.option("hoist_funs");
                var hoist_vars = compressor.option("hoist_vars");
                var self = this;
                if (hoist_funs || hoist_vars) {
                    var dirs = [];
                    var hoisted = [];
                    var vars = new Dictionary(), vars_found = 0, var_decl = 0;
                    // let's count var_decl first, we seem to waste a lot of
                    // space if we hoist `var` when there's only one.
                    self.walk(new TreeWalker(function(node){
                        if (node instanceof AST_Scope && node !== self)
                            return true;
                        if (node instanceof AST_Var) {
                            ++var_decl;
                            return true;
                        }
                    }));
                    hoist_vars = hoist_vars && var_decl > 1;
                    var tt = new TreeTransformer(
                        function before(node) {
                            if (node !== self) {
                                if (node instanceof AST_Directive) {
                                    dirs.push(node);
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (node instanceof AST_Defun && hoist_funs) {
                                    hoisted.push(node);
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (node instanceof AST_Var && hoist_vars) {
                                    node.definitions.forEach(function(def){
                                        vars.set(def.name.name, def);
                                        ++vars_found;
                                    });
                                    var seq = node.to_assignments();
                                    var p = tt.parent();
                                    if (p instanceof AST_ForIn && p.init === node) {
                                        if (seq == null) return node.definitions[0].name;
                                        return seq;
                                    }
                                    if (p instanceof AST_For && p.init === node) {
                                        return seq;
                                    }
                                    if (!seq) return make_node(AST_EmptyStatement, node);
                                    return make_node(AST_SimpleStatement, node, {
                                        body: seq
                                    });
                                }
                                if (node instanceof AST_Scope)
                                    return node; // to avoid descending in nested scopes
                            }
                        }
                    );
                    self = self.transform(tt);
                    if (vars_found > 0) {
                        // collect only vars which don't show up in self's arguments list
                        var defs = [];
                        vars.each(function(def, name){
                            if (self instanceof AST_Lambda
                                && find_if(function(x){ return x.name == def.name.name },
                                           self.argnames)) {
                                vars.del(name);
                            } else {
                                def = def.clone();
                                def.value = null;
                                defs.push(def);
                                vars.set(name, def);
                            }
                        });
                        if (defs.length > 0) {
                            // try to merge in assignments
                            for (var i = 0; i < self.body.length;) {
                                if (self.body[i] instanceof AST_SimpleStatement) {
                                    var expr = self.body[i].body, sym, assign;
                                    if (expr instanceof AST_Assign
                                        && expr.operator == "="
                                        && (sym = expr.left) instanceof AST_Symbol
                                        && vars.has(sym.name))
                                    {
                                        var def = vars.get(sym.name);
                                        if (def.value) break;
                                        def.value = expr.right;
                                        remove(defs, def);
                                        defs.push(def);
                                        self.body.splice(i, 1);
                                        continue;
                                    }
                                    if (expr instanceof AST_Seq
                                        && (assign = expr.car) instanceof AST_Assign
                                        && assign.operator == "="
                                        && (sym = assign.left) instanceof AST_Symbol
                                        && vars.has(sym.name))
                                    {
                                        var def = vars.get(sym.name);
                                        if (def.value) break;
                                        def.value = assign.right;
                                        remove(defs, def);
                                        defs.push(def);
                                        self.body[i].body = expr.cdr;
                                        continue;
                                    }
                                }
                                if (self.body[i] instanceof AST_EmptyStatement) {
                                    self.body.splice(i, 1);
                                    continue;
                                }
                                if (self.body[i] instanceof AST_BlockStatement) {
                                    var tmp = [ i, 1 ].concat(self.body[i].body);
                                    self.body.splice.apply(self.body, tmp);
                                    continue;
                                }
                                break;
                            }
                            defs = make_node(AST_Var, self, {
                                definitions: defs
                            });
                            hoisted.push(defs);
                        };
                    }
                    self.body = dirs.concat(hoisted, self.body);
                }
                return self;
            });
        
            OPT(AST_SimpleStatement, function(self, compressor){
                if (compressor.option("side_effects")) {
                    if (!self.body.has_side_effects(compressor)) {
                        compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
                        return make_node(AST_EmptyStatement, self);
                    }
                }
                return self;
            });
        
            OPT(AST_DWLoop, function(self, compressor){
                var cond = self.condition.evaluate(compressor);
                self.condition = cond[0];
                if (!compressor.option("loops")) return self;
                if (cond.length > 1) {
                    if (cond[1]) {
                        return make_node(AST_For, self, {
                            body: self.body
                        });
                    } else if (self instanceof AST_While) {
                        if (compressor.option("dead_code")) {
                            var a = [];
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            return make_node(AST_BlockStatement, self, { body: a });
                        }
                    }
                }
                return self;
            });
        
            function if_break_in_loop(self, compressor) {
                function drop_it(rest) {
                    rest = as_statement_array(rest);
                    if (self.body instanceof AST_BlockStatement) {
                        self.body = self.body.clone();
                        self.body.body = rest.concat(self.body.body.slice(1));
                        self.body = self.body.transform(compressor);
                    } else {
                        self.body = make_node(AST_BlockStatement, self.body, {
                            body: rest
                        }).transform(compressor);
                    }
                    if_break_in_loop(self, compressor);
                }
                var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
                if (first instanceof AST_If) {
                    if (first.body instanceof AST_Break
                        && compressor.loopcontrol_target(first.body.label) === self) {
                        if (self.condition) {
                            self.condition = make_node(AST_Binary, self.condition, {
                                left: self.condition,
                                operator: "&&",
                                right: first.condition.negate(compressor),
                            });
                        } else {
                            self.condition = first.condition.negate(compressor);
                        }
                        drop_it(first.alternative);
                    }
                    else if (first.alternative instanceof AST_Break
                             && compressor.loopcontrol_target(first.alternative.label) === self) {
                        if (self.condition) {
                            self.condition = make_node(AST_Binary, self.condition, {
                                left: self.condition,
                                operator: "&&",
                                right: first.condition,
                            });
                        } else {
                            self.condition = first.condition;
                        }
                        drop_it(first.body);
                    }
                }
            };
        
            OPT(AST_While, function(self, compressor) {
                if (!compressor.option("loops")) return self;
                self = AST_DWLoop.prototype.optimize.call(self, compressor);
                if (self instanceof AST_While) {
                    if_break_in_loop(self, compressor);
                    self = make_node(AST_For, self, self).transform(compressor);
                }
                return self;
            });
        
            OPT(AST_For, function(self, compressor){
                var cond = self.condition;
                if (cond) {
                    cond = cond.evaluate(compressor);
                    self.condition = cond[0];
                }
                if (!compressor.option("loops")) return self;
                if (cond) {
                    if (cond.length > 1 && !cond[1]) {
                        if (compressor.option("dead_code")) {
                            var a = [];
                            if (self.init instanceof AST_Statement) {
                                a.push(self.init);
                            }
                            else if (self.init) {
                                a.push(make_node(AST_SimpleStatement, self.init, {
                                    body: self.init
                                }));
                            }
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            return make_node(AST_BlockStatement, self, { body: a });
                        }
                    }
                }
                if_break_in_loop(self, compressor);
                return self;
            });
        
            OPT(AST_If, function(self, compressor){
                if (!compressor.option("conditionals")) return self;
                // if condition can be statically determined, warn and drop
                // one of the blocks.  note, statically determined implies
                // “has no side effects”; also it doesn't work for cases like
                // `x && true`, though it probably should.
                var cond = self.condition.evaluate(compressor);
                self.condition = cond[0];
                if (cond.length > 1) {
                    if (cond[1]) {
                        compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
                        if (compressor.option("dead_code")) {
                            var a = [];
                            if (self.alternative) {
                                extract_declarations_from_unreachable_code(compressor, self.alternative, a);
                            }
                            a.push(self.body);
                            return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
                        }
                    } else {
                        compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
                        if (compressor.option("dead_code")) {
                            var a = [];
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            if (self.alternative) a.push(self.alternative);
                            return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
                        }
                    }
                }
                if (is_empty(self.alternative)) self.alternative = null;
                var negated = self.condition.negate(compressor);
                var negated_is_best = best_of(self.condition, negated) === negated;
                if (self.alternative && negated_is_best) {
                    negated_is_best = false; // because we already do the switch here.
                    self.condition = negated;
                    var tmp = self.body;
                    self.body = self.alternative || make_node(AST_EmptyStatement);
                    self.alternative = tmp;
                }
                if (is_empty(self.body) && is_empty(self.alternative)) {
                    return make_node(AST_SimpleStatement, self.condition, {
                        body: self.condition
                    }).transform(compressor);
                }
                if (self.body instanceof AST_SimpleStatement
                    && self.alternative instanceof AST_SimpleStatement) {
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Conditional, self, {
                            condition   : self.condition,
                            consequent  : self.body.body,
                            alternative : self.alternative.body
                        })
                    }).transform(compressor);
                }
                if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
                    if (negated_is_best) return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "||",
                            left     : negated,
                            right    : self.body.body
                        })
                    }).transform(compressor);
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "&&",
                            left     : self.condition,
                            right    : self.body.body
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_EmptyStatement
                    && self.alternative
                    && self.alternative instanceof AST_SimpleStatement) {
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "||",
                            left     : self.condition,
                            right    : self.alternative.body
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_Exit
                    && self.alternative instanceof AST_Exit
                    && self.body.TYPE == self.alternative.TYPE) {
                    return make_node(self.body.CTOR, self, {
                        value: make_node(AST_Conditional, self, {
                            condition   : self.condition,
                            consequent  : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
                            alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_If
                    && !self.body.alternative
                    && !self.alternative) {
                    self.condition = make_node(AST_Binary, self.condition, {
                        operator: "&&",
                        left: self.condition,
                        right: self.body.condition
                    }).transform(compressor);
                    self.body = self.body.body;
                }
                if (aborts(self.body)) {
                    if (self.alternative) {
                        var alt = self.alternative;
                        self.alternative = null;
                        return make_node(AST_BlockStatement, self, {
                            body: [ self, alt ]
                        }).transform(compressor);
                    }
                }
                if (aborts(self.alternative)) {
                    var body = self.body;
                    self.body = self.alternative;
                    self.condition = negated_is_best ? negated : self.condition.negate(compressor);
                    self.alternative = null;
                    return make_node(AST_BlockStatement, self, {
                        body: [ self, body ]
                    }).transform(compressor);
                }
                return self;
            });
        
            OPT(AST_Switch, function(self, compressor){
                if (self.body.length == 0 && compressor.option("conditionals")) {
                    return make_node(AST_SimpleStatement, self, {
                        body: self.expression
                    }).transform(compressor);
                }
                for(;;) {
                    var last_branch = self.body[self.body.length - 1];
                    if (last_branch) {
                        var stat = last_branch.body[last_branch.body.length - 1]; // last statement
                        if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
                            last_branch.body.pop();
                        if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
                            self.body.pop();
                            continue;
                        }
                    }
                    break;
                }
                var exp = self.expression.evaluate(compressor);
                out: if (exp.length == 2) try {
                    // constant expression
                    self.expression = exp[0];
                    if (!compressor.option("dead_code")) break out;
                    var value = exp[1];
                    var in_if = false;
                    var in_block = false;
                    var started = false;
                    var stopped = false;
                    var ruined = false;
                    var tt = new TreeTransformer(function(node, descend, in_list){
                        if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
                            // no need to descend these node types
                            return node;
                        }
                        else if (node instanceof AST_Switch && node === self) {
                            node = node.clone();
                            descend(node, this);
                            return ruined ? node : make_node(AST_BlockStatement, node, {
                                body: node.body.reduce(function(a, branch){
                                    return a.concat(branch.body);
                                }, [])
                            }).transform(compressor);
                        }
                        else if (node instanceof AST_If || node instanceof AST_Try) {
                            var save = in_if;
                            in_if = !in_block;
                            descend(node, this);
                            in_if = save;
                            return node;
                        }
                        else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
                            var save = in_block;
                            in_block = true;
                            descend(node, this);
                            in_block = save;
                            return node;
                        }
                        else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
                            if (in_if) {
                                ruined = true;
                                return node;
                            }
                            if (in_block) return node;
                            stopped = true;
                            return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
                        }
                        else if (node instanceof AST_SwitchBranch && this.parent() === self) {
                            if (stopped) return MAP.skip;
                            if (node instanceof AST_Case) {
                                var exp = node.expression.evaluate(compressor);
                                if (exp.length < 2) {
                                    // got a case with non-constant expression, baling out
                                    throw self;
                                }
                                if (exp[1] === value || started) {
                                    started = true;
                                    if (aborts(node)) stopped = true;
                                    descend(node, this);
                                    return node;
                                }
                                return MAP.skip;
                            }
                            descend(node, this);
                            return node;
                        }
                    });
                    tt.stack = compressor.stack.slice(); // so that's able to see parent nodes
                    self = self.transform(tt);
                } catch(ex) {
                    if (ex !== self) throw ex;
                }
                return self;
            });
        
            OPT(AST_Case, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            OPT(AST_Try, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            AST_Definitions.DEFMETHOD("remove_initializers", function(){
                this.definitions.forEach(function(def){ def.value = null });
            });
        
            AST_Definitions.DEFMETHOD("to_assignments", function(){
                var assignments = this.definitions.reduce(function(a, def){
                    if (def.value) {
                        var name = make_node(AST_SymbolRef, def.name, def.name);
                        a.push(make_node(AST_Assign, def, {
                            operator : "=",
                            left     : name,
                            right    : def.value
                        }));
                    }
                    return a;
                }, []);
                if (assignments.length == 0) return null;
                return AST_Seq.from_array(assignments);
            });
        
            OPT(AST_Definitions, function(self, compressor){
                if (self.definitions.length == 0)
                    return make_node(AST_EmptyStatement, self);
                return self;
            });
        
            OPT(AST_Function, function(self, compressor){
                self = AST_Lambda.prototype.optimize.call(self, compressor);
                if (compressor.option("unused") && !compressor.option("keep_fnames")) {
                    if (self.name && self.name.unreferenced()) {
                        self.name = null;
                    }
                }
                return self;
            });
        
            OPT(AST_Call, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var exp = self.expression;
                    if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                        switch (exp.name) {
                          case "Array":
                            if (self.args.length != 1) {
                                return make_node(AST_Array, self, {
                                    elements: self.args
                                }).transform(compressor);
                            }
                            break;
                          case "Object":
                            if (self.args.length == 0) {
                                return make_node(AST_Object, self, {
                                    properties: []
                                });
                            }
                            break;
                          case "String":
                            if (self.args.length == 0) return make_node(AST_String, self, {
                                value: ""
                            });
                            if (self.args.length <= 1) return make_node(AST_Binary, self, {
                                left: self.args[0],
                                operator: "+",
                                right: make_node(AST_String, self, { value: "" })
                            }).transform(compressor);
                            break;
                          case "Number":
                            if (self.args.length == 0) return make_node(AST_Number, self, {
                                value: 0
                            });
                            if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                                expression: self.args[0],
                                operator: "+"
                            }).transform(compressor);
                          case "Boolean":
                            if (self.args.length == 0) return make_node(AST_False, self);
                            if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                                expression: make_node(AST_UnaryPrefix, null, {
                                    expression: self.args[0],
                                    operator: "!"
                                }),
                                operator: "!"
                            }).transform(compressor);
                            break;
                          case "Function":
                            // new Function() => function(){}
                            if (self.args.length == 0) return make_node(AST_Function, self, {
                                argnames: [],
                                body: []
                            });
                            if (all(self.args, function(x){ return x instanceof AST_String })) {
                                // quite a corner-case, but we can handle it:
                                //   https://github.com/mishoo/UglifyJS2/issues/203
                                // if the code argument is a constant, then we can minify it.
                                try {
                                    var code = "(function(" + self.args.slice(0, -1).map(function(arg){
                                        return arg.value;
                                    }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
                                    var ast = parse(code);
                                    ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
                                    var comp = new Compressor(compressor.options);
                                    ast = ast.transform(comp);
                                    ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
                                    ast.mangle_names();
                                    var fun;
                                    try {
                                        ast.walk(new TreeWalker(function(node){
                                            if (node instanceof AST_Lambda) {
                                                fun = node;
                                                throw ast;
                                            }
                                        }));
                                    } catch(ex) {
                                        if (ex !== ast) throw ex;
                                    };
                                    if (!fun) return self;
                                    var args = fun.argnames.map(function(arg, i){
                                        return make_node(AST_String, self.args[i], {
                                            value: arg.print_to_string()
                                        });
                                    });
                                    var code = OutputStream();
                                    AST_BlockStatement.prototype._codegen.call(fun, fun, code);
                                    code = code.toString().replace(/^\{|\}$/g, "");
                                    args.push(make_node(AST_String, self.args[self.args.length - 1], {
                                        value: code
                                    }));
                                    self.args = args;
                                    return self;
                                } catch(ex) {
                                    if (ex instanceof JS_Parse_Error) {
                                        compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
                                        compressor.warn(ex.toString());
                                    } else {
                                        console.log(ex);
                                        throw ex;
                                    }
                                }
                            }
                            break;
                        }
                    }
                    else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
                        return make_node(AST_Binary, self, {
                            left: make_node(AST_String, self, { value: "" }),
                            operator: "+",
                            right: exp.expression
                        }).transform(compressor);
                    }
                    else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
                        var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1];
                        if (separator == null) break EXIT; // not a constant
                        var elements = exp.expression.elements.reduce(function(a, el){
                            el = el.evaluate(compressor);
                            if (a.length == 0 || el.length == 1) {
                                a.push(el);
                            } else {
                                var last = a[a.length - 1];
                                if (last.length == 2) {
                                    // it's a constant
                                    var val = "" + last[1] + separator + el[1];
                                    a[a.length - 1] = [ make_node_from_constant(compressor, val, last[0]), val ];
                                } else {
                                    a.push(el);
                                }
                            }
                            return a;
                        }, []);
                        if (elements.length == 0) return make_node(AST_String, self, { value: "" });
                        if (elements.length == 1) return elements[0][0];
                        if (separator == "") {
                            var first;
                            if (elements[0][0] instanceof AST_String
                                || elements[1][0] instanceof AST_String) {
                                first = elements.shift()[0];
                            } else {
                                first = make_node(AST_String, self, { value: "" });
                            }
                            return elements.reduce(function(prev, el){
                                return make_node(AST_Binary, el[0], {
                                    operator : "+",
                                    left     : prev,
                                    right    : el[0],
                                });
                            }, first).transform(compressor);
                        }
                        // need this awkward cloning to not affect original element
                        // best_of will decide which one to get through.
                        var node = self.clone();
                        node.expression = node.expression.clone();
                        node.expression.expression = node.expression.expression.clone();
                        node.expression.expression.elements = elements.map(function(el){
                            return el[0];
                        });
                        return best_of(self, node);
                    }
                }
                if (compressor.option("side_effects")) {
                    if (self.expression instanceof AST_Function
                        && self.args.length == 0
                        && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) {
                        return make_node(AST_Undefined, self).transform(compressor);
                    }
                }
                if (compressor.option("drop_console")) {
                    if (self.expression instanceof AST_PropAccess &&
                        self.expression.expression instanceof AST_SymbolRef &&
                        self.expression.expression.name == "console" &&
                        self.expression.expression.undeclared()) {
                        return make_node(AST_Undefined, self).transform(compressor);
                    }
                }
                return self.evaluate(compressor)[0];
            });
        
            OPT(AST_New, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var exp = self.expression;
                    if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                        switch (exp.name) {
                          case "Object":
                          case "RegExp":
                          case "Function":
                          case "Error":
                          case "Array":
                            return make_node(AST_Call, self, self).transform(compressor);
                        }
                    }
                }
                return self;
            });
        
            OPT(AST_Seq, function(self, compressor){
                if (!compressor.option("side_effects"))
                    return self;
                if (!self.car.has_side_effects(compressor)) {
                    // we shouldn't compress (1,eval)(something) to
                    // eval(something) because that changes the meaning of
                    // eval (becomes lexical instead of global).
                    var p;
                    if (!(self.cdr instanceof AST_SymbolRef
                          && self.cdr.name == "eval"
                          && self.cdr.undeclared()
                          && (p = compressor.parent()) instanceof AST_Call
                          && p.expression === self)) {
                        return self.cdr;
                    }
                }
                if (compressor.option("cascade")) {
                    if (self.car instanceof AST_Assign
                        && !self.car.left.has_side_effects(compressor)) {
                        if (self.car.left.equivalent_to(self.cdr)) {
                            return self.car;
                        }
                        if (self.cdr instanceof AST_Call
                            && self.cdr.expression.equivalent_to(self.car.left)) {
                            self.cdr.expression = self.car;
                            return self.cdr;
                        }
                    }
                    if (!self.car.has_side_effects(compressor)
                        && !self.cdr.has_side_effects(compressor)
                        && self.car.equivalent_to(self.cdr)) {
                        return self.car;
                    }
                }
                if (self.cdr instanceof AST_UnaryPrefix
                    && self.cdr.operator == "void"
                    && !self.cdr.expression.has_side_effects(compressor)) {
                    self.cdr.expression = self.car;
                    return self.cdr;
                }
                if (self.cdr instanceof AST_Undefined) {
                    return make_node(AST_UnaryPrefix, self, {
                        operator   : "void",
                        expression : self.car
                    });
                }
                return self;
            });
        
            AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
                if (compressor.option("sequences")) {
                    if (this.expression instanceof AST_Seq) {
                        var seq = this.expression;
                        var x = seq.to_array();
                        this.expression = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                }
                return this;
            });
        
            OPT(AST_UnaryPostfix, function(self, compressor){
                return self.lift_sequences(compressor);
            });
        
            OPT(AST_UnaryPrefix, function(self, compressor){
                self = self.lift_sequences(compressor);
                var e = self.expression;
                if (compressor.option("booleans") && compressor.in_boolean_context()) {
                    switch (self.operator) {
                      case "!":
                        if (e instanceof AST_UnaryPrefix && e.operator == "!") {
                            // !!foo ==> foo, if we're in boolean context
                            return e.expression;
                        }
                        break;
                      case "typeof":
                        // typeof always returns a non-empty string, thus it's
                        // always true in booleans
                        compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    if (e instanceof AST_Binary && self.operator == "!") {
                        self = best_of(self, e.negate(compressor));
                    }
                }
                return self.evaluate(compressor)[0];
            });
        
            function has_side_effects_or_prop_access(node, compressor) {
                var save_pure_getters = compressor.option("pure_getters");
                compressor.options.pure_getters = false;
                var ret = node.has_side_effects(compressor);
                compressor.options.pure_getters = save_pure_getters;
                return ret;
            }
        
            AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
                if (compressor.option("sequences")) {
                    if (this.left instanceof AST_Seq) {
                        var seq = this.left;
                        var x = seq.to_array();
                        this.left = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                    if (this.right instanceof AST_Seq
                        && this instanceof AST_Assign
                        && !has_side_effects_or_prop_access(this.left, compressor)) {
                        var seq = this.right;
                        var x = seq.to_array();
                        this.right = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                }
                return this;
            });
        
            var commutativeOperators = makePredicate("== === != !== * & | ^");
        
            OPT(AST_Binary, function(self, compressor){
                var reverse = compressor.has_directive("use asm") ? noop
                    : function(op, force) {
                        if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
                            if (op) self.operator = op;
                            var tmp = self.left;
                            self.left = self.right;
                            self.right = tmp;
                        }
                    };
                if (commutativeOperators(self.operator)) {
                    if (self.right instanceof AST_Constant
                        && !(self.left instanceof AST_Constant)) {
                        // if right is a constant, whatever side effects the
                        // left side might have could not influence the
                        // result.  hence, force switch.
        
                        if (!(self.left instanceof AST_Binary
                              && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
                            reverse(null, true);
                        }
                    }
                    if (/^[!=]==?$/.test(self.operator)) {
                        if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) {
                            if (self.right.consequent instanceof AST_SymbolRef
                                && self.right.consequent.definition() === self.left.definition()) {
                                if (/^==/.test(self.operator)) return self.right.condition;
                                if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor);
                            }
                            if (self.right.alternative instanceof AST_SymbolRef
                                && self.right.alternative.definition() === self.left.definition()) {
                                if (/^==/.test(self.operator)) return self.right.condition.negate(compressor);
                                if (/^!=/.test(self.operator)) return self.right.condition;
                            }
                        }
                        if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) {
                            if (self.left.consequent instanceof AST_SymbolRef
                                && self.left.consequent.definition() === self.right.definition()) {
                                if (/^==/.test(self.operator)) return self.left.condition;
                                if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor);
                            }
                            if (self.left.alternative instanceof AST_SymbolRef
                                && self.left.alternative.definition() === self.right.definition()) {
                                if (/^==/.test(self.operator)) return self.left.condition.negate(compressor);
                                if (/^!=/.test(self.operator)) return self.left.condition;
                            }
                        }
                    }
                }
                self = self.lift_sequences(compressor);
                if (compressor.option("comparisons")) switch (self.operator) {
                  case "===":
                  case "!==":
                    if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
                        (self.left.is_boolean() && self.right.is_boolean())) {
                        self.operator = self.operator.substr(0, 2);
                    }
                    // XXX: intentionally falling down to the next case
                  case "==":
                  case "!=":
                    if (self.left instanceof AST_String
                        && self.left.value == "undefined"
                        && self.right instanceof AST_UnaryPrefix
                        && self.right.operator == "typeof"
                        && compressor.option("unsafe")) {
                        if (!(self.right.expression instanceof AST_SymbolRef)
                            || !self.right.expression.undeclared()) {
                            self.right = self.right.expression;
                            self.left = make_node(AST_Undefined, self.left).optimize(compressor);
                            if (self.operator.length == 2) self.operator += "=";
                        }
                    }
                    break;
                }
                if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
                  case "&&":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) {
                        compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
                        return make_node(AST_False, self);
                    }
                    if (ll.length > 1 && ll[1]) {
                        return rr[0];
                    }
                    if (rr.length > 1 && rr[1]) {
                        return ll[0];
                    }
                    break;
                  case "||":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) {
                        compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    if (ll.length > 1 && !ll[1]) {
                        return rr[0];
                    }
                    if (rr.length > 1 && !rr[1]) {
                        return ll[0];
                    }
                    break;
                  case "+":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
                        (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
                        compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    break;
                }
                if (compressor.option("comparisons")) {
                    if (!(compressor.parent() instanceof AST_Binary)
                        || compressor.parent() instanceof AST_Assign) {
                        var negated = make_node(AST_UnaryPrefix, self, {
                            operator: "!",
                            expression: self.negate(compressor)
                        });
                        self = best_of(self, negated);
                    }
                    switch (self.operator) {
                      case "<": reverse(">"); break;
                      case "<=": reverse(">="); break;
                    }
                }
                if (self.operator == "+" && self.right instanceof AST_String
                    && self.right.getValue() === "" && self.left instanceof AST_Binary
                    && self.left.operator == "+" && self.left.is_string(compressor)) {
                    return self.left;
                }
                if (compressor.option("evaluate")) {
                    if (self.operator == "+") {
                        if (self.left instanceof AST_Constant
                            && self.right instanceof AST_Binary
                            && self.right.operator == "+"
                            && self.right.left instanceof AST_Constant
                            && self.right.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: make_node(AST_String, null, {
                                    value: "" + self.left.getValue() + self.right.left.getValue(),
                                    start: self.left.start,
                                    end: self.right.left.end
                                }),
                                right: self.right.right
                            });
                        }
                        if (self.right instanceof AST_Constant
                            && self.left instanceof AST_Binary
                            && self.left.operator == "+"
                            && self.left.right instanceof AST_Constant
                            && self.left.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: self.left.left,
                                right: make_node(AST_String, null, {
                                    value: "" + self.left.right.getValue() + self.right.getValue(),
                                    start: self.left.right.start,
                                    end: self.right.end
                                })
                            });
                        }
                        if (self.left instanceof AST_Binary
                            && self.left.operator == "+"
                            && self.left.is_string(compressor)
                            && self.left.right instanceof AST_Constant
                            && self.right instanceof AST_Binary
                            && self.right.operator == "+"
                            && self.right.left instanceof AST_Constant
                            && self.right.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: make_node(AST_Binary, self.left, {
                                    operator: "+",
                                    left: self.left.left,
                                    right: make_node(AST_String, null, {
                                        value: "" + self.left.right.getValue() + self.right.left.getValue(),
                                        start: self.left.right.start,
                                        end: self.right.left.end
                                    })
                                }),
                                right: self.right.right
                            });
                        }
                    }
                }
                // x * (y * z)  ==>  x * y * z
                if (self.right instanceof AST_Binary
                    && self.right.operator == self.operator
                    && (self.operator == "*" || self.operator == "&&" || self.operator == "||"))
                {
                    self.left = make_node(AST_Binary, self.left, {
                        operator : self.operator,
                        left     : self.left,
                        right    : self.right.left
                    });
                    self.right = self.right.right;
                    return self.transform(compressor);
                }
                return self.evaluate(compressor)[0];
            });
        
            OPT(AST_SymbolRef, function(self, compressor){
                if (self.undeclared()) {
                    var defines = compressor.option("global_defs");
                    if (defines && defines.hasOwnProperty(self.name)) {
                        return make_node_from_constant(compressor, defines[self.name], self);
                    }
                    switch (self.name) {
                      case "undefined":
                        return make_node(AST_Undefined, self);
                      case "NaN":
                        return make_node(AST_NaN, self).transform(compressor);
                      case "Infinity":
                        return make_node(AST_Infinity, self).transform(compressor);
                    }
                }
                return self;
            });
        
            OPT(AST_Infinity, function (self, compressor) {
                return make_node(AST_Binary, self, {
                    operator : '/',
                    left     : make_node(AST_Number, null, {value: 1}),
                    right    : make_node(AST_Number, null, {value: 0})
                });
            });
        
            OPT(AST_NaN, function (self, compressor) {
                return make_node(AST_Binary, self, {
                    operator : '/',
                    left     : make_node(AST_Number, null, {value: 0}),
                    right    : make_node(AST_Number, null, {value: 0})
                });
            });
        
            OPT(AST_Undefined, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var scope = compressor.find_parent(AST_Scope);
                    var undef = scope.find_variable("undefined");
                    if (undef) {
                        var ref = make_node(AST_SymbolRef, self, {
                            name   : "undefined",
                            scope  : scope,
                            thedef : undef
                        });
                        ref.reference();
                        return ref;
                    }
                }
                return self;
            });
        
            var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
            OPT(AST_Assign, function(self, compressor){
                self = self.lift_sequences(compressor);
                if (self.operator == "="
                    && self.left instanceof AST_SymbolRef
                    && self.right instanceof AST_Binary
                    && self.right.left instanceof AST_SymbolRef
                    && self.right.left.name == self.left.name
                    && member(self.right.operator, ASSIGN_OPS)) {
                    self.operator = self.right.operator + "=";
                    self.right = self.right.right;
                }
                return self;
            });
        
            OPT(AST_Conditional, function(self, compressor){
                if (!compressor.option("conditionals")) return self;
                if (self.condition instanceof AST_Seq) {
                    var car = self.condition.car;
                    self.condition = self.condition.cdr;
                    return AST_Seq.cons(car, self);
                }
                var cond = self.condition.evaluate(compressor);
                if (cond.length > 1) {
                    if (cond[1]) {
                        compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
                        return self.consequent;
                    } else {
                        compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
                        return self.alternative;
                    }
                }
                var negated = cond[0].negate(compressor);
                if (best_of(cond[0], negated) === negated) {
                    self = make_node(AST_Conditional, self, {
                        condition: negated,
                        consequent: self.alternative,
                        alternative: self.consequent
                    });
                }
                var consequent = self.consequent;
                var alternative = self.alternative;
                if (consequent instanceof AST_Assign
                    && alternative instanceof AST_Assign
                    && consequent.operator == alternative.operator
                    && consequent.left.equivalent_to(alternative.left)
                   ) {
                    /*
                     * Stuff like this:
                     * if (foo) exp = something; else exp = something_else;
                     * ==>
                     * exp = foo ? something : something_else;
                     */
                    return make_node(AST_Assign, self, {
                        operator: consequent.operator,
                        left: consequent.left,
                        right: make_node(AST_Conditional, self, {
                            condition: self.condition,
                            consequent: consequent.right,
                            alternative: alternative.right
                        })
                    });
                }
                if (consequent instanceof AST_Call
                    && alternative.TYPE === consequent.TYPE
                    && consequent.args.length == alternative.args.length
                    && consequent.expression.equivalent_to(alternative.expression)) {
                    if (consequent.args.length == 0) {
                        return make_node(AST_Seq, self, {
                            car: self.condition,
                            cdr: consequent
                        });
                    }
                    if (consequent.args.length == 1) {
                        consequent.args[0] = make_node(AST_Conditional, self, {
                            condition: self.condition,
                            consequent: consequent.args[0],
                            alternative: alternative.args[0]
                        });
                        return consequent;
                    }
                }
                // x?y?z:a:a --> x&&y?z:a
                if (consequent instanceof AST_Conditional
                    && consequent.alternative.equivalent_to(alternative)) {
                    return make_node(AST_Conditional, self, {
                        condition: make_node(AST_Binary, self, {
                            left: self.condition,
                            operator: "&&",
                            right: consequent.condition
                        }),
                        consequent: consequent.consequent,
                        alternative: alternative
                    });
                }
                // x=y?1:1 --> x=1
                if (consequent instanceof AST_Constant
                    && alternative instanceof AST_Constant
                    && consequent.equivalent_to(alternative)) {
                    if (self.condition.has_side_effects(compressor)) {
                        return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
                    } else {
                        return make_node_from_constant(compressor, consequent.value, self);
        
                    }
                }
                // x=y?true:false --> x=!!y
                if (consequent instanceof AST_True
                    && alternative instanceof AST_False) {
                    self.condition = self.condition.negate(compressor);
                    return make_node(AST_UnaryPrefix, self.condition, {
                        operator: "!",
                        expression: self.condition
                    });
                }
                // x=y?false:true --> x=!y
                if (consequent instanceof AST_False
                    && alternative instanceof AST_True) {
                    return self.condition.negate(compressor)
                }
                return self;
            });
        
            OPT(AST_Boolean, function(self, compressor){
                if (compressor.option("booleans")) {
                    var p = compressor.parent();
                    if (p instanceof AST_Binary && (p.operator == "=="
                                                    || p.operator == "!=")) {
                        compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
                            operator : p.operator,
                            value    : self.value,
                            file     : p.start.file,
                            line     : p.start.line,
                            col      : p.start.col,
                        });
                        return make_node(AST_Number, self, {
                            value: +self.value
                        });
                    }
                    return make_node(AST_UnaryPrefix, self, {
                        operator: "!",
                        expression: make_node(AST_Number, self, {
                            value: 1 - self.value
                        })
                    });
                }
                return self;
            });
        
            OPT(AST_Sub, function(self, compressor){
                var prop = self.property;
                if (prop instanceof AST_String && compressor.option("properties")) {
                    prop = prop.getValue();
                    if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
                        return make_node(AST_Dot, self, {
                            expression : self.expression,
                            property   : prop
                        }).optimize(compressor);
                    }
                    var v = parseFloat(prop);
                    if (!isNaN(v) && v.toString() == prop) {
                        self.property = make_node(AST_Number, self.property, {
                            value: v
                        });
                    }
                }
                return self;
            });
        
            OPT(AST_Dot, function(self, compressor){
                var prop = self.property;
                if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
                    return make_node(AST_Sub, self, {
                        expression : self.expression,
                        property   : make_node(AST_String, self, {
                            value: prop
                        })
                    }).optimize(compressor);
                }
                return self.evaluate(compressor)[0];
            });
        
            function literals_in_boolean_context(self, compressor) {
                if (compressor.option("booleans") && compressor.in_boolean_context()) {
                    return make_node(AST_True, self);
                }
                return self;
            };
            OPT(AST_Array, literals_in_boolean_context);
            OPT(AST_Object, literals_in_boolean_context);
            OPT(AST_RegExp, literals_in_boolean_context);
        
        })();
        
      • mozilla-ast.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        (function(){
        
            var MOZ_TO_ME = {
                ExpressionStatement: function(M) {
                    var expr = M.expression;
                    if (expr.type === "Literal" && typeof expr.value === "string") {
                        return new AST_Directive({
                            start: my_start_token(M),
                            end: my_end_token(M),
                            value: expr.value
                        });
                    }
                    return new AST_SimpleStatement({
                        start: my_start_token(M),
                        end: my_end_token(M),
                        body: from_moz(expr)
                    });
                },
                TryStatement: function(M) {
                    var handlers = M.handlers || [M.handler];
                    if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
                        throw new Error("Multiple catch clauses are not supported.");
                    }
                    return new AST_Try({
                        start    : my_start_token(M),
                        end      : my_end_token(M),
                        body     : from_moz(M.block).body,
                        bcatch   : from_moz(handlers[0]),
                        bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
                    });
                },
                Property: function(M) {
                    var key = M.key;
                    var name = key.type == "Identifier" ? key.name : key.value;
                    var args = {
                        start    : my_start_token(key),
                        end      : my_end_token(M.value),
                        key      : name,
                        value    : from_moz(M.value)
                    };
                    switch (M.kind) {
                      case "init":
                        return new AST_ObjectKeyVal(args);
                      case "set":
                        args.value.name = from_moz(key);
                        return new AST_ObjectSetter(args);
                      case "get":
                        args.value.name = from_moz(key);
                        return new AST_ObjectGetter(args);
                    }
                },
                ObjectExpression: function(M) {
                    return new AST_Object({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        properties : M.properties.map(function(prop){
                            prop.type = "Property";
                            return from_moz(prop)
                        })
                    });
                },
                SequenceExpression: function(M) {
                    return AST_Seq.from_array(M.expressions.map(from_moz));
                },
                MemberExpression: function(M) {
                    return new (M.computed ? AST_Sub : AST_Dot)({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        property   : M.computed ? from_moz(M.property) : M.property.name,
                        expression : from_moz(M.object)
                    });
                },
                SwitchCase: function(M) {
                    return new (M.test ? AST_Case : AST_Default)({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        expression : from_moz(M.test),
                        body       : M.consequent.map(from_moz)
                    });
                },
                VariableDeclaration: function(M) {
                    return new (M.kind === "const" ? AST_Const : AST_Var)({
                        start       : my_start_token(M),
                        end         : my_end_token(M),
                        definitions : M.declarations.map(from_moz)
                    });
                },
                Literal: function(M) {
                    var val = M.value, args = {
                        start  : my_start_token(M),
                        end    : my_end_token(M)
                    };
                    if (val === null) return new AST_Null(args);
                    switch (typeof val) {
                      case "string":
                        args.value = val;
                        return new AST_String(args);
                      case "number":
                        args.value = val;
                        return new AST_Number(args);
                      case "boolean":
                        return new (val ? AST_True : AST_False)(args);
                      default:
                        args.value = val;
                        return new AST_RegExp(args);
                    }
                },
                Identifier: function(M) {
                    var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
                    return new (  p.type == "LabeledStatement" ? AST_Label
                                : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
                                : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
                                : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
                                : p.type == "CatchClause" ? AST_SymbolCatch
                                : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
                                : AST_SymbolRef)({
                                    start : my_start_token(M),
                                    end   : my_end_token(M),
                                    name  : M.name
                                });
                }
            };
        
            MOZ_TO_ME.UpdateExpression =
            MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
                var prefix = "prefix" in M ? M.prefix
                    : M.type == "UnaryExpression" ? true : false;
                return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
                    start      : my_start_token(M),
                    end        : my_end_token(M),
                    operator   : M.operator,
                    expression : from_moz(M.argument)
                });
            };
        
            map("Program", AST_Toplevel, "body@body");
            map("EmptyStatement", AST_EmptyStatement);
            map("BlockStatement", AST_BlockStatement, "body@body");
            map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
            map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
            map("BreakStatement", AST_Break, "label>label");
            map("ContinueStatement", AST_Continue, "label>label");
            map("WithStatement", AST_With, "object>expression, body>body");
            map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
            map("ReturnStatement", AST_Return, "argument>value");
            map("ThrowStatement", AST_Throw, "argument>value");
            map("WhileStatement", AST_While, "test>condition, body>body");
            map("DoWhileStatement", AST_Do, "test>condition, body>body");
            map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
            map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
            map("DebuggerStatement", AST_Debugger);
            map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
            map("VariableDeclarator", AST_VarDef, "id>name, init>value");
            map("CatchClause", AST_Catch, "param>argname, body%body");
        
            map("ThisExpression", AST_This);
            map("ArrayExpression", AST_Array, "elements@elements");
            map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
            map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
            map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
            map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
            map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
            map("NewExpression", AST_New, "callee>expression, arguments@args");
            map("CallExpression", AST_Call, "callee>expression, arguments@args");
        
            def_to_moz(AST_Directive, function To_Moz_Directive(M) {
                return {
                    type: "ExpressionStatement",
                    expression: {
                        type: "Literal",
                        value: M.value
                    }
                };
            });
        
            def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
                return {
                    type: "ExpressionStatement",
                    expression: to_moz(M.body)
                };
            });
        
            def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
                return {
                    type: "SwitchCase",
                    test: to_moz(M.expression),
                    consequent: M.body.map(to_moz)
                };
            });
        
            def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
                return {
                    type: "TryStatement",
                    block: to_moz_block(M),
                    handler: to_moz(M.bcatch),
                    guardedHandlers: [],
                    finalizer: to_moz(M.bfinally)
                };
            });
        
            def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
                return {
                    type: "CatchClause",
                    param: to_moz(M.argname),
                    guard: null,
                    body: to_moz_block(M)
                };
            });
        
            def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
                return {
                    type: "VariableDeclaration",
                    kind: M instanceof AST_Const ? "const" : "var",
                    declarations: M.definitions.map(to_moz)
                };
            });
        
            def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
                return {
                    type: "SequenceExpression",
                    expressions: M.to_array().map(to_moz)
                };
            });
        
            def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
                var isComputed = M instanceof AST_Sub;
                return {
                    type: "MemberExpression",
                    object: to_moz(M.expression),
                    computed: isComputed,
                    property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
                };
            });
        
            def_to_moz(AST_Unary, function To_Moz_Unary(M) {
                return {
                    type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
                    operator: M.operator,
                    prefix: M instanceof AST_UnaryPrefix,
                    argument: to_moz(M.expression)
                };
            });
        
            def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
                return {
                    type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
                    left: to_moz(M.left),
                    operator: M.operator,
                    right: to_moz(M.right)
                };
            });
        
            def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
                return {
                    type: "ObjectExpression",
                    properties: M.properties.map(to_moz)
                };
            });
        
            def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
                var key = (
                    is_identifier(M.key)
                    ? {type: "Identifier", name: M.key}
                    : {type: "Literal", value: M.key}
                );
                var kind;
                if (M instanceof AST_ObjectKeyVal) {
                    kind = "init";
                } else
                if (M instanceof AST_ObjectGetter) {
                    kind = "get";
                } else
                if (M instanceof AST_ObjectSetter) {
                    kind = "set";
                }
                return {
                    type: "Property",
                    kind: kind,
                    key: key,
                    value: to_moz(M.value)
                };
            });
        
            def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
                var def = M.definition();
                return {
                    type: "Identifier",
                    name: def ? def.mangled_name || def.name : M.name
                };
            });
        
            def_to_moz(AST_Constant, function To_Moz_Literal(M) {
                var value = M.value;
                if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
                    return {
                        type: "UnaryExpression",
                        operator: "-",
                        prefix: true,
                        argument: {
                            type: "Literal",
                            value: -value
                        }
                    };
                }
                return {
                    type: "Literal",
                    value: value
                };
            });
        
            def_to_moz(AST_Atom, function To_Moz_Atom(M) {
                return {
                    type: "Identifier",
                    name: String(M.value)
                };
            });
        
            AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
            AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
            AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
        
            AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
            AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
        
            /* -----[ tools ]----- */
        
            function my_start_token(moznode) {
                var loc = moznode.loc, start = loc && loc.start;
                var range = moznode.range;
                return new AST_Token({
                    file    : loc && loc.source,
                    line    : start && start.line,
                    col     : start && start.column,
                    pos     : range ? range[0] : moznode.start,
                    endline : start && start.line,
                    endcol  : start && start.column,
                    endpos  : range ? range[0] : moznode.start
                });
            };
        
            function my_end_token(moznode) {
                var loc = moznode.loc, end = loc && loc.end;
                var range = moznode.range;
                return new AST_Token({
                    file    : loc && loc.source,
                    line    : end && end.line,
                    col     : end && end.column,
                    pos     : range ? range[1] : moznode.end,
                    endline : end && end.line,
                    endcol  : end && end.column,
                    endpos  : range ? range[1] : moznode.end
                });
            };
        
            function map(moztype, mytype, propmap) {
                var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
                moz_to_me += "return new " + mytype.name + "({\n" +
                    "start: my_start_token(M),\n" +
                    "end: my_end_token(M)";
        
                var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
                me_to_moz += "return {\n" +
                    "type: " + JSON.stringify(moztype);
        
                if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
                    var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
                    if (!m) throw new Error("Can't understand property map: " + prop);
                    var moz = m[1], how = m[2], my = m[3];
                    moz_to_me += ",\n" + my + ": ";
                    me_to_moz += ",\n" + moz + ": ";
                    switch (how) {
                        case "@":
                            moz_to_me += "M." + moz + ".map(from_moz)";
                            me_to_moz += "M." +  my + ".map(to_moz)";
                            break;
                        case ">":
                            moz_to_me += "from_moz(M." + moz + ")";
                            me_to_moz += "to_moz(M." + my + ")";
                            break;
                        case "=":
                            moz_to_me += "M." + moz;
                            me_to_moz += "M." + my;
                            break;
                        case "%":
                            moz_to_me += "from_moz(M." + moz + ").body";
                            me_to_moz += "to_moz_block(M)";
                            break;
                        default:
                            throw new Error("Can't understand operator in propmap: " + prop);
                    }
                });
        
                moz_to_me += "\n})\n}";
                me_to_moz += "\n}\n}";
        
                //moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
                //me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
                //console.log(moz_to_me);
        
                moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
                    my_start_token, my_end_token, from_moz
                );
                me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
                    to_moz, to_moz_block
                );
                MOZ_TO_ME[moztype] = moz_to_me;
                def_to_moz(mytype, me_to_moz);
            };
        
            var FROM_MOZ_STACK = null;
        
            function from_moz(node) {
                FROM_MOZ_STACK.push(node);
                var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
                FROM_MOZ_STACK.pop();
                return ret;
            };
        
            AST_Node.from_mozilla_ast = function(node){
                var save_stack = FROM_MOZ_STACK;
                FROM_MOZ_STACK = [];
                var ast = from_moz(node);
                FROM_MOZ_STACK = save_stack;
                return ast;
            };
        
            function set_moz_loc(mynode, moznode, myparent) {
                var start = mynode.start;
                var end = mynode.end;
                if (start.pos != null && end.endpos != null) {
                    moznode.range = [start.pos, end.endpos];
                }
                if (start.line) {
                    moznode.loc = {
                        start: {line: start.line, column: start.col},
                        end: end.endline ? {line: end.endline, column: end.endcol} : null
                    };
                    if (start.file) {
                        moznode.loc.source = start.file;
                    }
                }
                return moznode;
            };
        
            function def_to_moz(mytype, handler) {
                mytype.DEFMETHOD("to_mozilla_ast", function() {
                    return set_moz_loc(this, handler(this));
                });
            };
        
            function to_moz(node) {
                return node != null ? node.to_mozilla_ast() : null;
            };
        
            function to_moz_block(node) {
                return {
                    type: "BlockStatement",
                    body: node.body.map(to_moz)
                };
            };
        
        })();
        
      • output.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function OutputStream(options) {
        
            options = defaults(options, {
                indent_start     : 0,
                indent_level     : 4,
                quote_keys       : false,
                space_colon      : true,
                ascii_only       : false,
                unescape_regexps : false,
                inline_script    : false,
                width            : 80,
                max_line_len     : 32000,
                beautify         : false,
                source_map       : null,
                bracketize       : false,
                semicolons       : true,
                comments         : false,
                preserve_line    : false,
                screw_ie8        : false,
                preamble         : null,
                quote_style      : 0
            }, true);
        
            var indentation = 0;
            var current_col = 0;
            var current_line = 1;
            var current_pos = 0;
            var OUTPUT = "";
        
            function to_ascii(str, identifier) {
                return str.replace(/[\u0080-\uffff]/g, function(ch) {
                    var code = ch.charCodeAt(0).toString(16);
                    if (code.length <= 2 && !identifier) {
                        while (code.length < 2) code = "0" + code;
                        return "\\x" + code;
                    } else {
                        while (code.length < 4) code = "0" + code;
                        return "\\u" + code;
                    }
                });
            };
        
            function make_string(str, quote) {
                var dq = 0, sq = 0;
                str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){
                    switch (s) {
                      case "\\": return "\\\\";
                      case "\b": return "\\b";
                      case "\f": return "\\f";
                      case "\n": return "\\n";
                      case "\r": return "\\r";
                      case "\u2028": return "\\u2028";
                      case "\u2029": return "\\u2029";
                      case '"': ++dq; return '"';
                      case "'": ++sq; return "'";
                      case "\0": return "\\x00";
                      case "\ufeff": return "\\ufeff";
                    }
                    return s;
                });
                function quote_single() {
                    return "'" + str.replace(/\x27/g, "\\'") + "'";
                }
                function quote_double() {
                    return '"' + str.replace(/\x22/g, '\\"') + '"';
                }
                if (options.ascii_only) str = to_ascii(str);
                switch (options.quote_style) {
                  case 1:
                    return quote_single();
                  case 2:
                    return quote_double();
                  case 3:
                    return quote == "'" ? quote_single() : quote_double();
                  default:
                    return dq > sq ? quote_single() : quote_double();
                }
            };
        
            function encode_string(str, quote) {
                var ret = make_string(str, quote);
                if (options.inline_script)
                    ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
                return ret;
            };
        
            function make_name(name) {
                name = name.toString();
                if (options.ascii_only)
                    name = to_ascii(name, true);
                return name;
            };
        
            function make_indent(back) {
                return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
            };
        
            /* -----[ beautification/minification ]----- */
        
            var might_need_space = false;
            var might_need_semicolon = false;
            var last = null;
        
            function last_char() {
                return last.charAt(last.length - 1);
            };
        
            function maybe_newline() {
                if (options.max_line_len && current_col > options.max_line_len)
                    print("\n");
            };
        
            var requireSemicolonChars = makePredicate("( [ + * / - , .");
        
            function print(str) {
                str = String(str);
                var ch = str.charAt(0);
                if (might_need_semicolon) {
                    if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
                        if (options.semicolons || requireSemicolonChars(ch)) {
                            OUTPUT += ";";
                            current_col++;
                            current_pos++;
                        } else {
                            OUTPUT += "\n";
                            current_pos++;
                            current_line++;
                            current_col = 0;
                        }
                        if (!options.beautify)
                            might_need_space = false;
                    }
                    might_need_semicolon = false;
                    maybe_newline();
                }
        
                if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
                    var target_line = stack[stack.length - 1].start.line;
                    while (current_line < target_line) {
                        OUTPUT += "\n";
                        current_pos++;
                        current_line++;
                        current_col = 0;
                        might_need_space = false;
                    }
                }
        
                if (might_need_space) {
                    var prev = last_char();
                    if ((is_identifier_char(prev)
                         && (is_identifier_char(ch) || ch == "\\"))
                        || (/^[\+\-\/]$/.test(ch) && ch == prev))
                    {
                        OUTPUT += " ";
                        current_col++;
                        current_pos++;
                    }
                    might_need_space = false;
                }
                var a = str.split(/\r?\n/), n = a.length - 1;
                current_line += n;
                if (n == 0) {
                    current_col += a[n].length;
                } else {
                    current_col = a[n].length;
                }
                current_pos += str.length;
                last = str;
                OUTPUT += str;
            };
        
            var space = options.beautify ? function() {
                print(" ");
            } : function() {
                might_need_space = true;
            };
        
            var indent = options.beautify ? function(half) {
                if (options.beautify) {
                    print(make_indent(half ? 0.5 : 0));
                }
            } : noop;
        
            var with_indent = options.beautify ? function(col, cont) {
                if (col === true) col = next_indent();
                var save_indentation = indentation;
                indentation = col;
                var ret = cont();
                indentation = save_indentation;
                return ret;
            } : function(col, cont) { return cont() };
        
            var newline = options.beautify ? function() {
                print("\n");
            } : maybe_newline;
        
            var semicolon = options.beautify ? function() {
                print(";");
            } : function() {
                might_need_semicolon = true;
            };
        
            function force_semicolon() {
                might_need_semicolon = false;
                print(";");
            };
        
            function next_indent() {
                return indentation + options.indent_level;
            };
        
            function with_block(cont) {
                var ret;
                print("{");
                newline();
                with_indent(next_indent(), function(){
                    ret = cont();
                });
                indent();
                print("}");
                return ret;
            };
        
            function with_parens(cont) {
                print("(");
                //XXX: still nice to have that for argument lists
                //var ret = with_indent(current_col, cont);
                var ret = cont();
                print(")");
                return ret;
            };
        
            function with_square(cont) {
                print("[");
                //var ret = with_indent(current_col, cont);
                var ret = cont();
                print("]");
                return ret;
            };
        
            function comma() {
                print(",");
                space();
            };
        
            function colon() {
                print(":");
                if (options.space_colon) space();
            };
        
            var add_mapping = options.source_map ? function(token, name) {
                try {
                    if (token) options.source_map.add(
                        token.file || "?",
                        current_line, current_col,
                        token.line, token.col,
                        (!name && token.type == "name") ? token.value : name
                    );
                } catch(ex) {
                    AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
                        file: token.file,
                        line: token.line,
                        col: token.col,
                        cline: current_line,
                        ccol: current_col,
                        name: name || ""
                    })
                }
            } : noop;
        
            function get() {
                return OUTPUT;
            };
        
            if (options.preamble) {
                print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
            }
        
            var stack = [];
            return {
                get             : get,
                toString        : get,
                indent          : indent,
                indentation     : function() { return indentation },
                current_width   : function() { return current_col - indentation },
                should_break    : function() { return options.width && this.current_width() >= options.width },
                newline         : newline,
                print           : print,
                space           : space,
                comma           : comma,
                colon           : colon,
                last            : function() { return last },
                semicolon       : semicolon,
                force_semicolon : force_semicolon,
                to_ascii        : to_ascii,
                print_name      : function(name) { print(make_name(name)) },
                print_string    : function(str, quote) { print(encode_string(str, quote)) },
                next_indent     : next_indent,
                with_indent     : with_indent,
                with_block      : with_block,
                with_parens     : with_parens,
                with_square     : with_square,
                add_mapping     : add_mapping,
                option          : function(opt) { return options[opt] },
                line            : function() { return current_line },
                col             : function() { return current_col },
                pos             : function() { return current_pos },
                push_node       : function(node) { stack.push(node) },
                pop_node        : function() { return stack.pop() },
                stack           : function() { return stack },
                parent          : function(n) {
                    return stack[stack.length - 2 - (n || 0)];
                }
            };
        
        };
        
        /* -----[ code generators ]----- */
        
        (function(){
        
            /* -----[ utils ]----- */
        
            function DEFPRINT(nodetype, generator) {
                nodetype.DEFMETHOD("_codegen", generator);
            };
        
            AST_Node.DEFMETHOD("print", function(stream, force_parens){
                var self = this, generator = self._codegen;
                function doit() {
                    self.add_comments(stream);
                    self.add_source_map(stream);
                    generator(self, stream);
                }
                stream.push_node(self);
                if (force_parens || self.needs_parens(stream)) {
                    stream.with_parens(doit);
                } else {
                    doit();
                }
                stream.pop_node();
            });
        
            AST_Node.DEFMETHOD("print_to_string", function(options){
                var s = OutputStream(options);
                this.print(s);
                return s.get();
            });
        
            /* -----[ comments ]----- */
        
            AST_Node.DEFMETHOD("add_comments", function(output){
                var c = output.option("comments"), self = this;
                if (c) {
                    var start = self.start;
                    if (start && !start._comments_dumped) {
                        start._comments_dumped = true;
                        var comments = start.comments_before || [];
        
                        // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
                        //               and https://github.com/mishoo/UglifyJS2/issues/372
                        if (self instanceof AST_Exit && self.value) {
                            self.value.walk(new TreeWalker(function(node){
                                if (node.start && node.start.comments_before) {
                                    comments = comments.concat(node.start.comments_before);
                                    node.start.comments_before = [];
                                }
                                if (node instanceof AST_Function ||
                                    node instanceof AST_Array ||
                                    node instanceof AST_Object)
                                {
                                    return true; // don't go inside.
                                }
                            }));
                        }
        
                        if (c.test) {
                            comments = comments.filter(function(comment){
                                return c.test(comment.value);
                            });
                        } else if (typeof c == "function") {
                            comments = comments.filter(function(comment){
                                return c(self, comment);
                            });
                        }
        
                        // Keep single line comments after nlb, after nlb
                        if (!output.option("beautify") && comments.length > 0 &&
                            /comment[134]/.test(comments[0].type) &&
                            output.col() !== 0 && comments[0].nlb)
                        {
                            output.print("\n");
                        }
        
                        comments.forEach(function(c){
                            if (/comment[134]/.test(c.type)) {
                                output.print("//" + c.value + "\n");
                                output.indent();
                            }
                            else if (c.type == "comment2") {
                                output.print("/*" + c.value + "*/");
                                if (start.nlb) {
                                    output.print("\n");
                                    output.indent();
                                } else {
                                    output.space();
                                }
                            }
                        });
                    }
                }
            });
        
            /* -----[ PARENTHESES ]----- */
        
            function PARENS(nodetype, func) {
                if (Array.isArray(nodetype)) {
                    nodetype.forEach(function(nodetype){
                        PARENS(nodetype, func);
                    });
                } else {
                    nodetype.DEFMETHOD("needs_parens", func);
                }
            };
        
            PARENS(AST_Node, function(){
                return false;
            });
        
            // a function expression needs parens around it when it's provably
            // the first token to appear in a statement.
            PARENS(AST_Function, function(output){
                return first_in_statement(output);
            });
        
            // same goes for an object literal, because otherwise it would be
            // interpreted as a block of code.
            PARENS(AST_Object, function(output){
                return first_in_statement(output);
            });
        
            PARENS([ AST_Unary, AST_Undefined ], function(output){
                var p = output.parent();
                return p instanceof AST_PropAccess && p.expression === this;
            });
        
            PARENS(AST_Seq, function(output){
                var p = output.parent();
                return p instanceof AST_Call             // (foo, bar)() or foo(1, (2, 3), 4)
                    || p instanceof AST_Unary            // !(foo, bar, baz)
                    || p instanceof AST_Binary           // 1 + (2, 3) + 4 ==> 8
                    || p instanceof AST_VarDef           // var a = (1, 2), b = a + a; ==> b == 4
                    || p instanceof AST_PropAccess       // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
                    || p instanceof AST_Array            // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
                    || p instanceof AST_ObjectProperty   // { foo: (1, 2) }.foo ==> 2
                    || p instanceof AST_Conditional      /* (false, true) ? (a = 10, b = 20) : (c = 30)
                                                          * ==> 20 (side effect, set a := 10 and b := 20) */
                ;
            });
        
            PARENS(AST_Binary, function(output){
                var p = output.parent();
                // (foo && bar)()
                if (p instanceof AST_Call && p.expression === this)
                    return true;
                // typeof (foo && bar)
                if (p instanceof AST_Unary)
                    return true;
                // (foo && bar)["prop"], (foo && bar).prop
                if (p instanceof AST_PropAccess && p.expression === this)
                    return true;
                // this deals with precedence: 3 * (2 + 1)
                if (p instanceof AST_Binary) {
                    var po = p.operator, pp = PRECEDENCE[po];
                    var so = this.operator, sp = PRECEDENCE[so];
                    if (pp > sp
                        || (pp == sp
                            && this === p.right)) {
                        return true;
                    }
                }
            });
        
            PARENS(AST_PropAccess, function(output){
                var p = output.parent();
                if (p instanceof AST_New && p.expression === this) {
                    // i.e. new (foo.bar().baz)
                    //
                    // if there's one call into this subtree, then we need
                    // parens around it too, otherwise the call will be
                    // interpreted as passing the arguments to the upper New
                    // expression.
                    try {
                        this.walk(new TreeWalker(function(node){
                            if (node instanceof AST_Call) throw p;
                        }));
                    } catch(ex) {
                        if (ex !== p) throw ex;
                        return true;
                    }
                }
            });
        
            PARENS(AST_Call, function(output){
                var p = output.parent(), p1;
                if (p instanceof AST_New && p.expression === this)
                    return true;
        
                // workaround for Safari bug.
                // https://bugs.webkit.org/show_bug.cgi?id=123506
                return this.expression instanceof AST_Function
                    && p instanceof AST_PropAccess
                    && p.expression === this
                    && (p1 = output.parent(1)) instanceof AST_Assign
                    && p1.left === p;
            });
        
            PARENS(AST_New, function(output){
                var p = output.parent();
                if (no_constructor_parens(this, output)
                    && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
                        || p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
                    return true;
            });
        
            PARENS(AST_Number, function(output){
                var p = output.parent();
                if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this)
                    return true;
            });
        
            PARENS([ AST_Assign, AST_Conditional ], function (output){
                var p = output.parent();
                // !(a = false) → true
                if (p instanceof AST_Unary)
                    return true;
                // 1 + (a = 2) + 3 → 6, side effect setting a = 2
                if (p instanceof AST_Binary && !(p instanceof AST_Assign))
                    return true;
                // (a = func)() —or— new (a = Object)()
                if (p instanceof AST_Call && p.expression === this)
                    return true;
                // (a = foo) ? bar : baz
                if (p instanceof AST_Conditional && p.condition === this)
                    return true;
                // (a = foo)["prop"] —or— (a = foo).prop
                if (p instanceof AST_PropAccess && p.expression === this)
                    return true;
            });
        
            /* -----[ PRINTERS ]----- */
        
            DEFPRINT(AST_Directive, function(self, output){
                output.print_string(self.value, self.quote);
                output.semicolon();
            });
            DEFPRINT(AST_Debugger, function(self, output){
                output.print("debugger");
                output.semicolon();
            });
        
            /* -----[ statements ]----- */
        
            function display_body(body, is_toplevel, output) {
                var last = body.length - 1;
                body.forEach(function(stmt, i){
                    if (!(stmt instanceof AST_EmptyStatement)) {
                        output.indent();
                        stmt.print(output);
                        if (!(i == last && is_toplevel)) {
                            output.newline();
                            if (is_toplevel) output.newline();
                        }
                    }
                });
            };
        
            AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
                force_statement(this.body, output);
            });
        
            DEFPRINT(AST_Statement, function(self, output){
                self.body.print(output);
                output.semicolon();
            });
            DEFPRINT(AST_Toplevel, function(self, output){
                display_body(self.body, true, output);
                output.print("");
            });
            DEFPRINT(AST_LabeledStatement, function(self, output){
                self.label.print(output);
                output.colon();
                self.body.print(output);
            });
            DEFPRINT(AST_SimpleStatement, function(self, output){
                self.body.print(output);
                output.semicolon();
            });
            function print_bracketed(body, output) {
                if (body.length > 0) output.with_block(function(){
                    display_body(body, false, output);
                });
                else output.print("{}");
            };
            DEFPRINT(AST_BlockStatement, function(self, output){
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_EmptyStatement, function(self, output){
                output.semicolon();
            });
            DEFPRINT(AST_Do, function(self, output){
                output.print("do");
                output.space();
                self._do_print_body(output);
                output.space();
                output.print("while");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.semicolon();
            });
            DEFPRINT(AST_While, function(self, output){
                output.print("while");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_For, function(self, output){
                output.print("for");
                output.space();
                output.with_parens(function(){
                    if (self.init && !(self.init instanceof AST_EmptyStatement)) {
                        if (self.init instanceof AST_Definitions) {
                            self.init.print(output);
                        } else {
                            parenthesize_for_noin(self.init, output, true);
                        }
                        output.print(";");
                        output.space();
                    } else {
                        output.print(";");
                    }
                    if (self.condition) {
                        self.condition.print(output);
                        output.print(";");
                        output.space();
                    } else {
                        output.print(";");
                    }
                    if (self.step) {
                        self.step.print(output);
                    }
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_ForIn, function(self, output){
                output.print("for");
                output.space();
                output.with_parens(function(){
                    self.init.print(output);
                    output.space();
                    output.print("in");
                    output.space();
                    self.object.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_With, function(self, output){
                output.print("with");
                output.space();
                output.with_parens(function(){
                    self.expression.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
        
            /* -----[ functions ]----- */
            AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
                var self = this;
                if (!nokeyword) {
                    output.print("function");
                }
                if (self.name) {
                    output.space();
                    self.name.print(output);
                }
                output.with_parens(function(){
                    self.argnames.forEach(function(arg, i){
                        if (i) output.comma();
                        arg.print(output);
                    });
                });
                output.space();
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_Lambda, function(self, output){
                self._do_print(output);
            });
        
            /* -----[ exits ]----- */
            AST_Exit.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                if (this.value) {
                    output.space();
                    this.value.print(output);
                }
                output.semicolon();
            });
            DEFPRINT(AST_Return, function(self, output){
                self._do_print(output, "return");
            });
            DEFPRINT(AST_Throw, function(self, output){
                self._do_print(output, "throw");
            });
        
            /* -----[ loop control ]----- */
            AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                if (this.label) {
                    output.space();
                    this.label.print(output);
                }
                output.semicolon();
            });
            DEFPRINT(AST_Break, function(self, output){
                self._do_print(output, "break");
            });
            DEFPRINT(AST_Continue, function(self, output){
                self._do_print(output, "continue");
            });
        
            /* -----[ if ]----- */
            function make_then(self, output) {
                if (output.option("bracketize")) {
                    make_block(self.body, output);
                    return;
                }
                // The squeezer replaces "block"-s that contain only a single
                // statement with the statement itself; technically, the AST
                // is correct, but this can create problems when we output an
                // IF having an ELSE clause where the THEN clause ends in an
                // IF *without* an ELSE block (then the outer ELSE would refer
                // to the inner IF).  This function checks for this case and
                // adds the block brackets if needed.
                if (!self.body)
                    return output.force_semicolon();
                if (self.body instanceof AST_Do
                    && !output.option("screw_ie8")) {
                    // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
                    // croaks with "syntax error" on code like this: if (foo)
                    // do ... while(cond); else ...  we need block brackets
                    // around do/while
                    make_block(self.body, output);
                    return;
                }
                var b = self.body;
                while (true) {
                    if (b instanceof AST_If) {
                        if (!b.alternative) {
                            make_block(self.body, output);
                            return;
                        }
                        b = b.alternative;
                    }
                    else if (b instanceof AST_StatementWithBody) {
                        b = b.body;
                    }
                    else break;
                }
                force_statement(self.body, output);
            };
            DEFPRINT(AST_If, function(self, output){
                output.print("if");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.space();
                if (self.alternative) {
                    make_then(self, output);
                    output.space();
                    output.print("else");
                    output.space();
                    force_statement(self.alternative, output);
                } else {
                    self._do_print_body(output);
                }
            });
        
            /* -----[ switch ]----- */
            DEFPRINT(AST_Switch, function(self, output){
                output.print("switch");
                output.space();
                output.with_parens(function(){
                    self.expression.print(output);
                });
                output.space();
                if (self.body.length > 0) output.with_block(function(){
                    self.body.forEach(function(stmt, i){
                        if (i) output.newline();
                        output.indent(true);
                        stmt.print(output);
                    });
                });
                else output.print("{}");
            });
            AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
                if (this.body.length > 0) {
                    output.newline();
                    this.body.forEach(function(stmt){
                        output.indent();
                        stmt.print(output);
                        output.newline();
                    });
                }
            });
            DEFPRINT(AST_Default, function(self, output){
                output.print("default:");
                self._do_print_body(output);
            });
            DEFPRINT(AST_Case, function(self, output){
                output.print("case");
                output.space();
                self.expression.print(output);
                output.print(":");
                self._do_print_body(output);
            });
        
            /* -----[ exceptions ]----- */
            DEFPRINT(AST_Try, function(self, output){
                output.print("try");
                output.space();
                print_bracketed(self.body, output);
                if (self.bcatch) {
                    output.space();
                    self.bcatch.print(output);
                }
                if (self.bfinally) {
                    output.space();
                    self.bfinally.print(output);
                }
            });
            DEFPRINT(AST_Catch, function(self, output){
                output.print("catch");
                output.space();
                output.with_parens(function(){
                    self.argname.print(output);
                });
                output.space();
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_Finally, function(self, output){
                output.print("finally");
                output.space();
                print_bracketed(self.body, output);
            });
        
            /* -----[ var/const ]----- */
            AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                output.space();
                this.definitions.forEach(function(def, i){
                    if (i) output.comma();
                    def.print(output);
                });
                var p = output.parent();
                var in_for = p instanceof AST_For || p instanceof AST_ForIn;
                var avoid_semicolon = in_for && p.init === this;
                if (!avoid_semicolon)
                    output.semicolon();
            });
            DEFPRINT(AST_Var, function(self, output){
                self._do_print(output, "var");
            });
            DEFPRINT(AST_Const, function(self, output){
                self._do_print(output, "const");
            });
        
            function parenthesize_for_noin(node, output, noin) {
                if (!noin) node.print(output);
                else try {
                    // need to take some precautions here:
                    //    https://github.com/mishoo/UglifyJS2/issues/60
                    node.walk(new TreeWalker(function(node){
                        if (node instanceof AST_Binary && node.operator == "in")
                            throw output;
                    }));
                    node.print(output);
                } catch(ex) {
                    if (ex !== output) throw ex;
                    node.print(output, true);
                }
            };
        
            DEFPRINT(AST_VarDef, function(self, output){
                self.name.print(output);
                if (self.value) {
                    output.space();
                    output.print("=");
                    output.space();
                    var p = output.parent(1);
                    var noin = p instanceof AST_For || p instanceof AST_ForIn;
                    parenthesize_for_noin(self.value, output, noin);
                }
            });
        
            /* -----[ other expressions ]----- */
            DEFPRINT(AST_Call, function(self, output){
                self.expression.print(output);
                if (self instanceof AST_New && no_constructor_parens(self, output))
                    return;
                output.with_parens(function(){
                    self.args.forEach(function(expr, i){
                        if (i) output.comma();
                        expr.print(output);
                    });
                });
            });
            DEFPRINT(AST_New, function(self, output){
                output.print("new");
                output.space();
                AST_Call.prototype._codegen(self, output);
            });
        
            AST_Seq.DEFMETHOD("_do_print", function(output){
                this.car.print(output);
                if (this.cdr) {
                    output.comma();
                    if (output.should_break()) {
                        output.newline();
                        output.indent();
                    }
                    this.cdr.print(output);
                }
            });
            DEFPRINT(AST_Seq, function(self, output){
                self._do_print(output);
                // var p = output.parent();
                // if (p instanceof AST_Statement) {
                //     output.with_indent(output.next_indent(), function(){
                //         self._do_print(output);
                //     });
                // } else {
                //     self._do_print(output);
                // }
            });
            DEFPRINT(AST_Dot, function(self, output){
                var expr = self.expression;
                expr.print(output);
                if (expr instanceof AST_Number && expr.getValue() >= 0) {
                    if (!/[xa-f.]/i.test(output.last())) {
                        output.print(".");
                    }
                }
                output.print(".");
                // the name after dot would be mapped about here.
                output.add_mapping(self.end);
                output.print_name(self.property);
            });
            DEFPRINT(AST_Sub, function(self, output){
                self.expression.print(output);
                output.print("[");
                self.property.print(output);
                output.print("]");
            });
            DEFPRINT(AST_UnaryPrefix, function(self, output){
                var op = self.operator;
                output.print(op);
                if (/^[a-z]/i.test(op)
                    || (/[+-]$/.test(op)
                        && self.expression instanceof AST_UnaryPrefix
                        && /^[+-]/.test(self.expression.operator))) {
                    output.space();
                }
                self.expression.print(output);
            });
            DEFPRINT(AST_UnaryPostfix, function(self, output){
                self.expression.print(output);
                output.print(self.operator);
            });
            DEFPRINT(AST_Binary, function(self, output){
                self.left.print(output);
                output.space();
                output.print(self.operator);
                if (self.operator == "<"
                    && self.right instanceof AST_UnaryPrefix
                    && self.right.operator == "!"
                    && self.right.expression instanceof AST_UnaryPrefix
                    && self.right.expression.operator == "--") {
                    // space is mandatory to avoid outputting <!--
                    // http://javascript.spec.whatwg.org/#comment-syntax
                    output.print(" ");
                } else {
                    // the space is optional depending on "beautify"
                    output.space();
                }
                self.right.print(output);
            });
            DEFPRINT(AST_Conditional, function(self, output){
                self.condition.print(output);
                output.space();
                output.print("?");
                output.space();
                self.consequent.print(output);
                output.space();
                output.colon();
                self.alternative.print(output);
            });
        
            /* -----[ literals ]----- */
            DEFPRINT(AST_Array, function(self, output){
                output.with_square(function(){
                    var a = self.elements, len = a.length;
                    if (len > 0) output.space();
                    a.forEach(function(exp, i){
                        if (i) output.comma();
                        exp.print(output);
                        // If the final element is a hole, we need to make sure it
                        // doesn't look like a trailing comma, by inserting an actual
                        // trailing comma.
                        if (i === len - 1 && exp instanceof AST_Hole)
                          output.comma();
                    });
                    if (len > 0) output.space();
                });
            });
            DEFPRINT(AST_Object, function(self, output){
                if (self.properties.length > 0) output.with_block(function(){
                    self.properties.forEach(function(prop, i){
                        if (i) {
                            output.print(",");
                            output.newline();
                        }
                        output.indent();
                        prop.print(output);
                    });
                    output.newline();
                });
                else output.print("{}");
            });
            DEFPRINT(AST_ObjectKeyVal, function(self, output){
                var key = self.key;
                var quote = self.quote;
                if (output.option("quote_keys")) {
                    output.print_string(key + "");
                } else if ((typeof key == "number"
                            || !output.option("beautify")
                            && +key + "" == key)
                           && parseFloat(key) >= 0) {
                    output.print(make_num(key));
                } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
                    output.print_name(key);
                } else {
                    output.print_string(key, quote);
                }
                output.colon();
                self.value.print(output);
            });
            DEFPRINT(AST_ObjectSetter, function(self, output){
                output.print("set");
                output.space();
                self.key.print(output);
                self.value._do_print(output, true);
            });
            DEFPRINT(AST_ObjectGetter, function(self, output){
                output.print("get");
                output.space();
                self.key.print(output);
                self.value._do_print(output, true);
            });
            DEFPRINT(AST_Symbol, function(self, output){
                var def = self.definition();
                output.print_name(def ? def.mangled_name || def.name : self.name);
            });
            DEFPRINT(AST_Undefined, function(self, output){
                output.print("void 0");
            });
            DEFPRINT(AST_Hole, noop);
            DEFPRINT(AST_Infinity, function(self, output){
                output.print("Infinity");
            });
            DEFPRINT(AST_NaN, function(self, output){
                output.print("NaN");
            });
            DEFPRINT(AST_This, function(self, output){
                output.print("this");
            });
            DEFPRINT(AST_Constant, function(self, output){
                output.print(self.getValue());
            });
            DEFPRINT(AST_String, function(self, output){
                output.print_string(self.getValue(), self.quote);
            });
            DEFPRINT(AST_Number, function(self, output){
                output.print(make_num(self.getValue()));
            });
        
            function regexp_safe_literal(code) {
                return [
                    0x5c   , // \
                    0x2f   , // /
                    0x2e   , // .
                    0x2b   , // +
                    0x2a   , // *
                    0x3f   , // ?
                    0x28   , // (
                    0x29   , // )
                    0x5b   , // [
                    0x5d   , // ]
                    0x7b   , // {
                    0x7d   , // }
                    0x24   , // $
                    0x5e   , // ^
                    0x3a   , // :
                    0x7c   , // |
                    0x21   , // !
                    0x0a   , // \n
                    0x0d   , // \r
                    0x00   , // \0
                    0xfeff , // Unicode BOM
                    0x2028 , // unicode "line separator"
                    0x2029 , // unicode "paragraph separator"
                ].indexOf(code) < 0;
            };
        
            DEFPRINT(AST_RegExp, function(self, output){
                var str = self.getValue().toString();
                if (output.option("ascii_only")) {
                    str = output.to_ascii(str);
                } else if (output.option("unescape_regexps")) {
                    str = str.split("\\\\").map(function(str){
                        return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
                            var code = parseInt(s.substr(2), 16);
                            return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
                        });
                    }).join("\\\\");
                }
                output.print(str);
                var p = output.parent();
                if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
                    output.print(" ");
            });
        
            function force_statement(stat, output) {
                if (output.option("bracketize")) {
                    if (!stat || stat instanceof AST_EmptyStatement)
                        output.print("{}");
                    else if (stat instanceof AST_BlockStatement)
                        stat.print(output);
                    else output.with_block(function(){
                        output.indent();
                        stat.print(output);
                        output.newline();
                    });
                } else {
                    if (!stat || stat instanceof AST_EmptyStatement)
                        output.force_semicolon();
                    else
                        stat.print(output);
                }
            };
        
            // return true if the node at the top of the stack (that means the
            // innermost node in the current output) is lexically the first in
            // a statement.
            function first_in_statement(output) {
                var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
                while (i > 0) {
                    if (p instanceof AST_Statement && p.body === node)
                        return true;
                    if ((p instanceof AST_Seq           && p.car === node        ) ||
                        (p instanceof AST_Call          && p.expression === node && !(p instanceof AST_New) ) ||
                        (p instanceof AST_Dot           && p.expression === node ) ||
                        (p instanceof AST_Sub           && p.expression === node ) ||
                        (p instanceof AST_Conditional   && p.condition === node  ) ||
                        (p instanceof AST_Binary        && p.left === node       ) ||
                        (p instanceof AST_UnaryPostfix  && p.expression === node ))
                    {
                        node = p;
                        p = a[--i];
                    } else {
                        return false;
                    }
                }
            };
        
            // self should be AST_New.  decide if we want to show parens or not.
            function no_constructor_parens(self, output) {
                return self.args.length == 0 && !output.option("beautify");
            };
        
            function best_of(a) {
                var best = a[0], len = best.length;
                for (var i = 1; i < a.length; ++i) {
                    if (a[i].length < len) {
                        best = a[i];
                        len = best.length;
                    }
                }
                return best;
            };
        
            function make_num(num) {
                var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
                if (Math.floor(num) === num) {
                    if (num >= 0) {
                        a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
                               "0" + num.toString(8)); // same.
                    } else {
                        a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
                               "-0" + (-num).toString(8)); // same.
                    }
                    if ((m = /^(.*?)(0+)$/.exec(num))) {
                        a.push(m[1] + "e" + m[2].length);
                    }
                } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
                    a.push(m[2] + "e-" + (m[1].length + m[2].length),
                           str.substr(str.indexOf(".")));
                }
                return best_of(a);
            };
        
            function make_block(stmt, output) {
                if (stmt instanceof AST_BlockStatement) {
                    stmt.print(output);
                    return;
                }
                output.with_block(function(){
                    output.indent();
                    stmt.print(output);
                    output.newline();
                });
            };
        
            /* -----[ source map generators ]----- */
        
            function DEFMAP(nodetype, generator) {
                nodetype.DEFMETHOD("add_source_map", function(stream){
                    generator(this, stream);
                });
            };
        
            // We could easily add info for ALL nodes, but it seems to me that
            // would be quite wasteful, hence this noop in the base class.
            DEFMAP(AST_Node, noop);
        
            function basic_sourcemap_gen(self, output) {
                output.add_mapping(self.start);
            };
        
            // XXX: I'm not exactly sure if we need it for all of these nodes,
            // or if we should add even more.
        
            DEFMAP(AST_Directive, basic_sourcemap_gen);
            DEFMAP(AST_Debugger, basic_sourcemap_gen);
            DEFMAP(AST_Symbol, basic_sourcemap_gen);
            DEFMAP(AST_Jump, basic_sourcemap_gen);
            DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
            DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
            DEFMAP(AST_Lambda, basic_sourcemap_gen);
            DEFMAP(AST_Switch, basic_sourcemap_gen);
            DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
            DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
            DEFMAP(AST_Toplevel, noop);
            DEFMAP(AST_New, basic_sourcemap_gen);
            DEFMAP(AST_Try, basic_sourcemap_gen);
            DEFMAP(AST_Catch, basic_sourcemap_gen);
            DEFMAP(AST_Finally, basic_sourcemap_gen);
            DEFMAP(AST_Definitions, basic_sourcemap_gen);
            DEFMAP(AST_Constant, basic_sourcemap_gen);
            DEFMAP(AST_ObjectProperty, function(self, output){
                output.add_mapping(self.start, self.key);
            });
        
        })();
        
      • parse.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
            Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
        var KEYWORDS_ATOM = 'false null true';
        var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield'
            + " " + KEYWORDS_ATOM + " " + KEYWORDS;
        var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
        
        KEYWORDS = makePredicate(KEYWORDS);
        RESERVED_WORDS = makePredicate(RESERVED_WORDS);
        KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
        KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
        
        var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
        
        var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
        var RE_OCT_NUMBER = /^0[0-7]+$/;
        var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
        
        var OPERATORS = makePredicate([
            "in",
            "instanceof",
            "typeof",
            "new",
            "void",
            "delete",
            "++",
            "--",
            "+",
            "-",
            "!",
            "~",
            "&",
            "|",
            "^",
            "*",
            "/",
            "%",
            ">>",
            "<<",
            ">>>",
            "<",
            ">",
            "<=",
            ">=",
            "==",
            "===",
            "!=",
            "!==",
            "?",
            "=",
            "+=",
            "-=",
            "/=",
            "*=",
            "%=",
            ">>=",
            "<<=",
            ">>>=",
            "|=",
            "^=",
            "&=",
            "&&",
            "||"
        ]);
        
        var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
        
        var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
        
        var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
        
        var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
        
        /* -----[ Tokenizer ]----- */
        
        // regexps adapted from http://xregexp.com/plugins/#unicode
        var UNICODE = {
            letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
            digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"),
            non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
            space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
            connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
        };
        
        function is_letter(code) {
            return (code >= 97 && code <= 122)
                || (code >= 65 && code <= 90)
                || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
        };
        
        function is_digit(code) {
            return code >= 48 && code <= 57;
        };
        
        function is_alphanumeric_char(code) {
            return is_digit(code) || is_letter(code);
        };
        
        function is_unicode_digit(code) {
            return UNICODE.digit.test(String.fromCharCode(code));
        }
        
        function is_unicode_combining_mark(ch) {
            return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
        };
        
        function is_unicode_connector_punctuation(ch) {
            return UNICODE.connector_punctuation.test(ch);
        };
        
        function is_identifier(name) {
            return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
        };
        
        function is_identifier_start(code) {
            return code == 36 || code == 95 || is_letter(code);
        };
        
        function is_identifier_char(ch) {
            var code = ch.charCodeAt(0);
            return is_identifier_start(code)
                || is_digit(code)
                || code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
                || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
                || is_unicode_combining_mark(ch)
                || is_unicode_connector_punctuation(ch)
                || is_unicode_digit(code)
            ;
        };
        
        function is_identifier_string(str){
            return /^[a-z_$][a-z0-9_$]*$/i.test(str);
        };
        
        function parse_js_number(num) {
            if (RE_HEX_NUMBER.test(num)) {
                return parseInt(num.substr(2), 16);
            } else if (RE_OCT_NUMBER.test(num)) {
                return parseInt(num.substr(1), 8);
            } else if (RE_DEC_NUMBER.test(num)) {
                return parseFloat(num);
            }
        };
        
        function JS_Parse_Error(message, line, col, pos) {
            this.message = message;
            this.line = line;
            this.col = col;
            this.pos = pos;
            this.stack = new Error().stack;
        };
        
        JS_Parse_Error.prototype.toString = function() {
            return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
        };
        
        function js_error(message, filename, line, col, pos) {
            throw new JS_Parse_Error(message, line, col, pos);
        };
        
        function is_token(token, type, val) {
            return token.type == type && (val == null || token.value == val);
        };
        
        var EX_EOF = {};
        
        function tokenizer($TEXT, filename, html5_comments) {
        
            var S = {
                text            : $TEXT.replace(/\uFEFF/g, ''),
                filename        : filename,
                pos             : 0,
                tokpos          : 0,
                line            : 1,
                tokline         : 0,
                col             : 0,
                tokcol          : 0,
                newline_before  : false,
                regex_allowed   : false,
                comments_before : []
            };
        
            function peek() { return S.text.charAt(S.pos); };
        
            function next(signal_eof, in_string) {
                var ch = S.text.charAt(S.pos++);
                if (signal_eof && !ch)
                    throw EX_EOF;
                if ("\r\n\u2028\u2029".indexOf(ch) >= 0) {
                    S.newline_before = S.newline_before || !in_string;
                    ++S.line;
                    S.col = 0;
                    if (!in_string && ch == "\r" && peek() == "\n") {
                        // treat a \r\n sequence as a single \n
                        ++S.pos;
                        ch = "\n";
                    }
                } else {
                    ++S.col;
                }
                return ch;
            };
        
            function forward(i) {
                while (i-- > 0) next();
            };
        
            function looking_at(str) {
                return S.text.substr(S.pos, str.length) == str;
            };
        
            function find(what, signal_eof) {
                var pos = S.text.indexOf(what, S.pos);
                if (signal_eof && pos == -1) throw EX_EOF;
                return pos;
            };
        
            function start_token() {
                S.tokline = S.line;
                S.tokcol = S.col;
                S.tokpos = S.pos;
            };
        
            var prev_was_dot = false;
            function token(type, value, is_comment) {
                S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
                                   (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
                                   (type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
                prev_was_dot = (type == "punc" && value == ".");
                var ret = {
                    type    : type,
                    value   : value,
                    line    : S.tokline,
                    col     : S.tokcol,
                    pos     : S.tokpos,
                    endline : S.line,
                    endcol  : S.col,
                    endpos  : S.pos,
                    nlb     : S.newline_before,
                    file    : filename
                };
                if (!is_comment) {
                    ret.comments_before = S.comments_before;
                    S.comments_before = [];
                    // make note of any newlines in the comments that came before
                    for (var i = 0, len = ret.comments_before.length; i < len; i++) {
                        ret.nlb = ret.nlb || ret.comments_before[i].nlb;
                    }
                }
                S.newline_before = false;
                return new AST_Token(ret);
            };
        
            function skip_whitespace() {
                while (WHITESPACE_CHARS(peek()))
                    next();
            };
        
            function read_while(pred) {
                var ret = "", ch, i = 0;
                while ((ch = peek()) && pred(ch, i++))
                    ret += next();
                return ret;
            };
        
            function parse_error(err) {
                js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
            };
        
            function read_num(prefix) {
                var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
                var num = read_while(function(ch, i){
                    var code = ch.charCodeAt(0);
                    switch (code) {
                      case 120: case 88: // xX
                        return has_x ? false : (has_x = true);
                      case 101: case 69: // eE
                        return has_x ? true : has_e ? false : (has_e = after_e = true);
                      case 45: // -
                        return after_e || (i == 0 && !prefix);
                      case 43: // +
                        return after_e;
                      case (after_e = false, 46): // .
                        return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
                    }
                    return is_alphanumeric_char(code);
                });
                if (prefix) num = prefix + num;
                var valid = parse_js_number(num);
                if (!isNaN(valid)) {
                    return token("num", valid);
                } else {
                    parse_error("Invalid syntax: " + num);
                }
            };
        
            function read_escaped_char(in_string) {
                var ch = next(true, in_string);
                switch (ch.charCodeAt(0)) {
                  case 110 : return "\n";
                  case 114 : return "\r";
                  case 116 : return "\t";
                  case 98  : return "\b";
                  case 118 : return "\u000b"; // \v
                  case 102 : return "\f";
                  case 48  : return "\0";
                  case 120 : return String.fromCharCode(hex_bytes(2)); // \x
                  case 117 : return String.fromCharCode(hex_bytes(4)); // \u
                  case 10  : return ""; // newline
                  default  : return ch;
                }
            };
        
            function hex_bytes(n) {
                var num = 0;
                for (; n > 0; --n) {
                    var digit = parseInt(next(true), 16);
                    if (isNaN(digit))
                        parse_error("Invalid hex-character pattern in string");
                    num = (num << 4) | digit;
                }
                return num;
            };
        
            var read_string = with_eof_error("Unterminated string constant", function(quote_char){
                var quote = next(), ret = "";
                for (;;) {
                    var ch = next(true);
                    if (ch == "\\") {
                        // read OctalEscapeSequence (XXX: deprecated if "strict mode")
                        // https://github.com/mishoo/UglifyJS/issues/178
                        var octal_len = 0, first = null;
                        ch = read_while(function(ch){
                            if (ch >= "0" && ch <= "7") {
                                if (!first) {
                                    first = ch;
                                    return ++octal_len;
                                }
                                else if (first <= "3" && octal_len <= 2) return ++octal_len;
                                else if (first >= "4" && octal_len <= 1) return ++octal_len;
                            }
                            return false;
                        });
                        if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
                        else ch = read_escaped_char(true);
                    }
                    else if (ch == quote) break;
                    ret += ch;
                }
                var tok = token("string", ret);
                tok.quote = quote_char;
                return tok;
            });
        
            function skip_line_comment(type) {
                var regex_allowed = S.regex_allowed;
                var i = find("\n"), ret;
                if (i == -1) {
                    ret = S.text.substr(S.pos);
                    S.pos = S.text.length;
                } else {
                    ret = S.text.substring(S.pos, i);
                    S.pos = i;
                }
                S.col = S.tokcol + (S.pos - S.tokpos);
                S.comments_before.push(token(type, ret, true));
                S.regex_allowed = regex_allowed;
                return next_token();
            };
        
            var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
                var regex_allowed = S.regex_allowed;
                var i = find("*/", true);
                var text = S.text.substring(S.pos, i);
                var a = text.split("\n"), n = a.length;
                // update stream position
                S.pos = i + 2;
                S.line += n - 1;
                if (n > 1) S.col = a[n - 1].length;
                else S.col += a[n - 1].length;
                S.col += 2;
                var nlb = S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
                S.comments_before.push(token("comment2", text, true));
                S.regex_allowed = regex_allowed;
                S.newline_before = nlb;
                return next_token();
            });
        
            function read_name() {
                var backslash = false, name = "", ch, escaped = false, hex;
                while ((ch = peek()) != null) {
                    if (!backslash) {
                        if (ch == "\\") escaped = backslash = true, next();
                        else if (is_identifier_char(ch)) name += next();
                        else break;
                    }
                    else {
                        if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
                        ch = read_escaped_char();
                        if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
                        name += ch;
                        backslash = false;
                    }
                }
                if (KEYWORDS(name) && escaped) {
                    hex = name.charCodeAt(0).toString(16).toUpperCase();
                    name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
                }
                return name;
            };
        
            var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
                var prev_backslash = false, ch, in_class = false;
                while ((ch = next(true))) if (prev_backslash) {
                    regexp += "\\" + ch;
                    prev_backslash = false;
                } else if (ch == "[") {
                    in_class = true;
                    regexp += ch;
                } else if (ch == "]" && in_class) {
                    in_class = false;
                    regexp += ch;
                } else if (ch == "/" && !in_class) {
                    break;
                } else if (ch == "\\") {
                    prev_backslash = true;
                } else {
                    regexp += ch;
                }
                var mods = read_name();
                return token("regexp", new RegExp(regexp, mods));
            });
        
            function read_operator(prefix) {
                function grow(op) {
                    if (!peek()) return op;
                    var bigger = op + peek();
                    if (OPERATORS(bigger)) {
                        next();
                        return grow(bigger);
                    } else {
                        return op;
                    }
                };
                return token("operator", grow(prefix || next()));
            };
        
            function handle_slash() {
                next();
                switch (peek()) {
                  case "/":
                    next();
                    return skip_line_comment("comment1");
                  case "*":
                    next();
                    return skip_multiline_comment();
                }
                return S.regex_allowed ? read_regexp("") : read_operator("/");
            };
        
            function handle_dot() {
                next();
                return is_digit(peek().charCodeAt(0))
                    ? read_num(".")
                    : token("punc", ".");
            };
        
            function read_word() {
                var word = read_name();
                if (prev_was_dot) return token("name", word);
                return KEYWORDS_ATOM(word) ? token("atom", word)
                    : !KEYWORDS(word) ? token("name", word)
                    : OPERATORS(word) ? token("operator", word)
                    : token("keyword", word);
            };
        
            function with_eof_error(eof_error, cont) {
                return function(x) {
                    try {
                        return cont(x);
                    } catch(ex) {
                        if (ex === EX_EOF) parse_error(eof_error);
                        else throw ex;
                    }
                };
            };
        
            function next_token(force_regexp) {
                if (force_regexp != null)
                    return read_regexp(force_regexp);
                skip_whitespace();
                start_token();
                if (html5_comments) {
                    if (looking_at("<!--")) {
                        forward(4);
                        return skip_line_comment("comment3");
                    }
                    if (looking_at("-->") && S.newline_before) {
                        forward(3);
                        return skip_line_comment("comment4");
                    }
                }
                var ch = peek();
                if (!ch) return token("eof");
                var code = ch.charCodeAt(0);
                switch (code) {
                  case 34: case 39: return read_string(ch);
                  case 46: return handle_dot();
                  case 47: return handle_slash();
                }
                if (is_digit(code)) return read_num();
                if (PUNC_CHARS(ch)) return token("punc", next());
                if (OPERATOR_CHARS(ch)) return read_operator();
                if (code == 92 || is_identifier_start(code)) return read_word();
                parse_error("Unexpected character '" + ch + "'");
            };
        
            next_token.context = function(nc) {
                if (nc) S = nc;
                return S;
            };
        
            return next_token;
        
        };
        
        /* -----[ Parser (constants) ]----- */
        
        var UNARY_PREFIX = makePredicate([
            "typeof",
            "void",
            "delete",
            "--",
            "++",
            "!",
            "~",
            "-",
            "+"
        ]);
        
        var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
        
        var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
        
        var PRECEDENCE = (function(a, ret){
            for (var i = 0; i < a.length; ++i) {
                var b = a[i];
                for (var j = 0; j < b.length; ++j) {
                    ret[b[j]] = i + 1;
                }
            }
            return ret;
        })(
            [
                ["||"],
                ["&&"],
                ["|"],
                ["^"],
                ["&"],
                ["==", "===", "!=", "!=="],
                ["<", ">", "<=", ">=", "in", "instanceof"],
                [">>", "<<", ">>>"],
                ["+", "-"],
                ["*", "/", "%"]
            ],
            {}
        );
        
        var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
        
        var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
        
        /* -----[ Parser ]----- */
        
        function parse($TEXT, options) {
        
            options = defaults(options, {
                strict         : false,
                filename       : null,
                toplevel       : null,
                expression     : false,
                html5_comments : true,
                bare_returns   : false,
            });
        
            var S = {
                input         : (typeof $TEXT == "string"
                                 ? tokenizer($TEXT, options.filename,
                                             options.html5_comments)
                                 : $TEXT),
                token         : null,
                prev          : null,
                peeked        : null,
                in_function   : 0,
                in_directives : true,
                in_loop       : 0,
                labels        : []
            };
        
            S.token = next();
        
            function is(type, value) {
                return is_token(S.token, type, value);
            };
        
            function peek() { return S.peeked || (S.peeked = S.input()); };
        
            function next() {
                S.prev = S.token;
                if (S.peeked) {
                    S.token = S.peeked;
                    S.peeked = null;
                } else {
                    S.token = S.input();
                }
                S.in_directives = S.in_directives && (
                    S.token.type == "string" || is("punc", ";")
                );
                return S.token;
            };
        
            function prev() {
                return S.prev;
            };
        
            function croak(msg, line, col, pos) {
                var ctx = S.input.context();
                js_error(msg,
                         ctx.filename,
                         line != null ? line : ctx.tokline,
                         col != null ? col : ctx.tokcol,
                         pos != null ? pos : ctx.tokpos);
            };
        
            function token_error(token, msg) {
                croak(msg, token.line, token.col);
            };
        
            function unexpected(token) {
                if (token == null)
                    token = S.token;
                token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
            };
        
            function expect_token(type, val) {
                if (is(type, val)) {
                    return next();
                }
                token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
            };
        
            function expect(punc) { return expect_token("punc", punc); };
        
            function can_insert_semicolon() {
                return !options.strict && (
                    S.token.nlb || is("eof") || is("punc", "}")
                );
            };
        
            function semicolon() {
                if (is("punc", ";")) next();
                else if (!can_insert_semicolon()) unexpected();
            };
        
            function parenthesised() {
                expect("(");
                var exp = expression(true);
                expect(")");
                return exp;
            };
        
            function embed_tokens(parser) {
                return function() {
                    var start = S.token;
                    var expr = parser();
                    var end = prev();
                    expr.start = start;
                    expr.end = end;
                    return expr;
                };
            };
        
            function handle_regexp() {
                if (is("operator", "/") || is("operator", "/=")) {
                    S.peeked = null;
                    S.token = S.input(S.token.value.substr(1)); // force regexp
                }
            };
        
            var statement = embed_tokens(function() {
                var tmp;
                handle_regexp();
                switch (S.token.type) {
                  case "string":
                    var dir = S.in_directives, stat = simple_statement();
                    // XXXv2: decide how to fix directives
                    if (dir && stat.body instanceof AST_String && !is("punc", ",")) {
                        return new AST_Directive({
                            start : stat.body.start,
                            end   : stat.body.end,
                            quote : stat.body.quote,
                            value : stat.body.value,
                        });
                    }
                    return stat;
                  case "num":
                  case "regexp":
                  case "operator":
                  case "atom":
                    return simple_statement();
        
                  case "name":
                    return is_token(peek(), "punc", ":")
                        ? labeled_statement()
                        : simple_statement();
        
                  case "punc":
                    switch (S.token.value) {
                      case "{":
                        return new AST_BlockStatement({
                            start : S.token,
                            body  : block_(),
                            end   : prev()
                        });
                      case "[":
                      case "(":
                        return simple_statement();
                      case ";":
                        next();
                        return new AST_EmptyStatement();
                      default:
                        unexpected();
                    }
        
                  case "keyword":
                    switch (tmp = S.token.value, next(), tmp) {
                      case "break":
                        return break_cont(AST_Break);
        
                      case "continue":
                        return break_cont(AST_Continue);
        
                      case "debugger":
                        semicolon();
                        return new AST_Debugger();
        
                      case "do":
                        return new AST_Do({
                            body      : in_loop(statement),
                            condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp)
                        });
        
                      case "while":
                        return new AST_While({
                            condition : parenthesised(),
                            body      : in_loop(statement)
                        });
        
                      case "for":
                        return for_();
        
                      case "function":
                        return function_(AST_Defun);
        
                      case "if":
                        return if_();
        
                      case "return":
                        if (S.in_function == 0 && !options.bare_returns)
                            croak("'return' outside of function");
                        return new AST_Return({
                            value: ( is("punc", ";")
                                     ? (next(), null)
                                     : can_insert_semicolon()
                                     ? null
                                     : (tmp = expression(true), semicolon(), tmp) )
                        });
        
                      case "switch":
                        return new AST_Switch({
                            expression : parenthesised(),
                            body       : in_loop(switch_body_)
                        });
        
                      case "throw":
                        if (S.token.nlb)
                            croak("Illegal newline after 'throw'");
                        return new AST_Throw({
                            value: (tmp = expression(true), semicolon(), tmp)
                        });
        
                      case "try":
                        return try_();
        
                      case "var":
                        return tmp = var_(), semicolon(), tmp;
        
                      case "const":
                        return tmp = const_(), semicolon(), tmp;
        
                      case "with":
                        return new AST_With({
                            expression : parenthesised(),
                            body       : statement()
                        });
        
                      default:
                        unexpected();
                    }
                }
            });
        
            function labeled_statement() {
                var label = as_symbol(AST_Label);
                if (find_if(function(l){ return l.name == label.name }, S.labels)) {
                    // ECMA-262, 12.12: An ECMAScript program is considered
                    // syntactically incorrect if it contains a
                    // LabelledStatement that is enclosed by a
                    // LabelledStatement with the same Identifier as label.
                    croak("Label " + label.name + " defined twice");
                }
                expect(":");
                S.labels.push(label);
                var stat = statement();
                S.labels.pop();
                if (!(stat instanceof AST_IterationStatement)) {
                    // check for `continue` that refers to this label.
                    // those should be reported as syntax errors.
                    // https://github.com/mishoo/UglifyJS2/issues/287
                    label.references.forEach(function(ref){
                        if (ref instanceof AST_Continue) {
                            ref = ref.label.start;
                            croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
                                  ref.line, ref.col, ref.pos);
                        }
                    });
                }
                return new AST_LabeledStatement({ body: stat, label: label });
            };
        
            function simple_statement(tmp) {
                return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
            };
        
            function break_cont(type) {
                var label = null, ldef;
                if (!can_insert_semicolon()) {
                    label = as_symbol(AST_LabelRef, true);
                }
                if (label != null) {
                    ldef = find_if(function(l){ return l.name == label.name }, S.labels);
                    if (!ldef)
                        croak("Undefined label " + label.name);
                    label.thedef = ldef;
                }
                else if (S.in_loop == 0)
                    croak(type.TYPE + " not inside a loop or switch");
                semicolon();
                var stat = new type({ label: label });
                if (ldef) ldef.references.push(stat);
                return stat;
            };
        
            function for_() {
                expect("(");
                var init = null;
                if (!is("punc", ";")) {
                    init = is("keyword", "var")
                        ? (next(), var_(true))
                        : expression(true, true);
                    if (is("operator", "in")) {
                        if (init instanceof AST_Var && init.definitions.length > 1)
                            croak("Only one variable declaration allowed in for..in loop");
                        next();
                        return for_in(init);
                    }
                }
                return regular_for(init);
            };
        
            function regular_for(init) {
                expect(";");
                var test = is("punc", ";") ? null : expression(true);
                expect(";");
                var step = is("punc", ")") ? null : expression(true);
                expect(")");
                return new AST_For({
                    init      : init,
                    condition : test,
                    step      : step,
                    body      : in_loop(statement)
                });
            };
        
            function for_in(init) {
                var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
                var obj = expression(true);
                expect(")");
                return new AST_ForIn({
                    init   : init,
                    name   : lhs,
                    object : obj,
                    body   : in_loop(statement)
                });
            };
        
            var function_ = function(ctor) {
                var in_statement = ctor === AST_Defun;
                var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
                if (in_statement && !name)
                    unexpected();
                expect("(");
                return new ctor({
                    name: name,
                    argnames: (function(first, a){
                        while (!is("punc", ")")) {
                            if (first) first = false; else expect(",");
                            a.push(as_symbol(AST_SymbolFunarg));
                        }
                        next();
                        return a;
                    })(true, []),
                    body: (function(loop, labels){
                        ++S.in_function;
                        S.in_directives = true;
                        S.in_loop = 0;
                        S.labels = [];
                        var a = block_();
                        --S.in_function;
                        S.in_loop = loop;
                        S.labels = labels;
                        return a;
                    })(S.in_loop, S.labels)
                });
            };
        
            function if_() {
                var cond = parenthesised(), body = statement(), belse = null;
                if (is("keyword", "else")) {
                    next();
                    belse = statement();
                }
                return new AST_If({
                    condition   : cond,
                    body        : body,
                    alternative : belse
                });
            };
        
            function block_() {
                expect("{");
                var a = [];
                while (!is("punc", "}")) {
                    if (is("eof")) unexpected();
                    a.push(statement());
                }
                next();
                return a;
            };
        
            function switch_body_() {
                expect("{");
                var a = [], cur = null, branch = null, tmp;
                while (!is("punc", "}")) {
                    if (is("eof")) unexpected();
                    if (is("keyword", "case")) {
                        if (branch) branch.end = prev();
                        cur = [];
                        branch = new AST_Case({
                            start      : (tmp = S.token, next(), tmp),
                            expression : expression(true),
                            body       : cur
                        });
                        a.push(branch);
                        expect(":");
                    }
                    else if (is("keyword", "default")) {
                        if (branch) branch.end = prev();
                        cur = [];
                        branch = new AST_Default({
                            start : (tmp = S.token, next(), expect(":"), tmp),
                            body  : cur
                        });
                        a.push(branch);
                    }
                    else {
                        if (!cur) unexpected();
                        cur.push(statement());
                    }
                }
                if (branch) branch.end = prev();
                next();
                return a;
            };
        
            function try_() {
                var body = block_(), bcatch = null, bfinally = null;
                if (is("keyword", "catch")) {
                    var start = S.token;
                    next();
                    expect("(");
                    var name = as_symbol(AST_SymbolCatch);
                    expect(")");
                    bcatch = new AST_Catch({
                        start   : start,
                        argname : name,
                        body    : block_(),
                        end     : prev()
                    });
                }
                if (is("keyword", "finally")) {
                    var start = S.token;
                    next();
                    bfinally = new AST_Finally({
                        start : start,
                        body  : block_(),
                        end   : prev()
                    });
                }
                if (!bcatch && !bfinally)
                    croak("Missing catch/finally blocks");
                return new AST_Try({
                    body     : body,
                    bcatch   : bcatch,
                    bfinally : bfinally
                });
            };
        
            function vardefs(no_in, in_const) {
                var a = [];
                for (;;) {
                    a.push(new AST_VarDef({
                        start : S.token,
                        name  : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
                        value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
                        end   : prev()
                    }));
                    if (!is("punc", ","))
                        break;
                    next();
                }
                return a;
            };
        
            var var_ = function(no_in) {
                return new AST_Var({
                    start       : prev(),
                    definitions : vardefs(no_in, false),
                    end         : prev()
                });
            };
        
            var const_ = function() {
                return new AST_Const({
                    start       : prev(),
                    definitions : vardefs(false, true),
                    end         : prev()
                });
            };
        
            var new_ = function() {
                var start = S.token;
                expect_token("operator", "new");
                var newexp = expr_atom(false), args;
                if (is("punc", "(")) {
                    next();
                    args = expr_list(")");
                } else {
                    args = [];
                }
                return subscripts(new AST_New({
                    start      : start,
                    expression : newexp,
                    args       : args,
                    end        : prev()
                }), true);
            };
        
            function as_atom_node() {
                var tok = S.token, ret;
                switch (tok.type) {
                  case "name":
                  case "keyword":
                    ret = _make_symbol(AST_SymbolRef);
                    break;
                  case "num":
                    ret = new AST_Number({ start: tok, end: tok, value: tok.value });
                    break;
                  case "string":
                    ret = new AST_String({
                        start : tok,
                        end   : tok,
                        value : tok.value,
                        quote : tok.quote
                    });
                    break;
                  case "regexp":
                    ret = new AST_RegExp({ start: tok, end: tok, value: tok.value });
                    break;
                  case "atom":
                    switch (tok.value) {
                      case "false":
                        ret = new AST_False({ start: tok, end: tok });
                        break;
                      case "true":
                        ret = new AST_True({ start: tok, end: tok });
                        break;
                      case "null":
                        ret = new AST_Null({ start: tok, end: tok });
                        break;
                    }
                    break;
                }
                next();
                return ret;
            };
        
            var expr_atom = function(allow_calls) {
                if (is("operator", "new")) {
                    return new_();
                }
                var start = S.token;
                if (is("punc")) {
                    switch (start.value) {
                      case "(":
                        next();
                        var ex = expression(true);
                        ex.start = start;
                        ex.end = S.token;
                        expect(")");
                        return subscripts(ex, allow_calls);
                      case "[":
                        return subscripts(array_(), allow_calls);
                      case "{":
                        return subscripts(object_(), allow_calls);
                    }
                    unexpected();
                }
                if (is("keyword", "function")) {
                    next();
                    var func = function_(AST_Function);
                    func.start = start;
                    func.end = prev();
                    return subscripts(func, allow_calls);
                }
                if (ATOMIC_START_TOKEN[S.token.type]) {
                    return subscripts(as_atom_node(), allow_calls);
                }
                unexpected();
            };
        
            function expr_list(closing, allow_trailing_comma, allow_empty) {
                var first = true, a = [];
                while (!is("punc", closing)) {
                    if (first) first = false; else expect(",");
                    if (allow_trailing_comma && is("punc", closing)) break;
                    if (is("punc", ",") && allow_empty) {
                        a.push(new AST_Hole({ start: S.token, end: S.token }));
                    } else {
                        a.push(expression(false));
                    }
                }
                next();
                return a;
            };
        
            var array_ = embed_tokens(function() {
                expect("[");
                return new AST_Array({
                    elements: expr_list("]", !options.strict, true)
                });
            });
        
            var object_ = embed_tokens(function() {
                expect("{");
                var first = true, a = [];
                while (!is("punc", "}")) {
                    if (first) first = false; else expect(",");
                    if (!options.strict && is("punc", "}"))
                        // allow trailing comma
                        break;
                    var start = S.token;
                    var type = start.type;
                    var name = as_property_name();
                    if (type == "name" && !is("punc", ":")) {
                        if (name == "get") {
                            a.push(new AST_ObjectGetter({
                                start : start,
                                key   : as_atom_node(),
                                value : function_(AST_Accessor),
                                end   : prev()
                            }));
                            continue;
                        }
                        if (name == "set") {
                            a.push(new AST_ObjectSetter({
                                start : start,
                                key   : as_atom_node(),
                                value : function_(AST_Accessor),
                                end   : prev()
                            }));
                            continue;
                        }
                    }
                    expect(":");
                    a.push(new AST_ObjectKeyVal({
                        start : start,
                        quote : start.quote,
                        key   : name,
                        value : expression(false),
                        end   : prev()
                    }));
                }
                next();
                return new AST_Object({ properties: a });
            });
        
            function as_property_name() {
                var tmp = S.token;
                next();
                switch (tmp.type) {
                  case "num":
                  case "string":
                  case "name":
                  case "operator":
                  case "keyword":
                  case "atom":
                    return tmp.value;
                  default:
                    unexpected();
                }
            };
        
            function as_name() {
                var tmp = S.token;
                next();
                switch (tmp.type) {
                  case "name":
                  case "operator":
                  case "keyword":
                  case "atom":
                    return tmp.value;
                  default:
                    unexpected();
                }
            };
        
            function _make_symbol(type) {
                var name = S.token.value;
                return new (name == "this" ? AST_This : type)({
                    name  : String(name),
                    start : S.token,
                    end   : S.token
                });
            };
        
            function as_symbol(type, noerror) {
                if (!is("name")) {
                    if (!noerror) croak("Name expected");
                    return null;
                }
                var sym = _make_symbol(type);
                next();
                return sym;
            };
        
            var subscripts = function(expr, allow_calls) {
                var start = expr.start;
                if (is("punc", ".")) {
                    next();
                    return subscripts(new AST_Dot({
                        start      : start,
                        expression : expr,
                        property   : as_name(),
                        end        : prev()
                    }), allow_calls);
                }
                if (is("punc", "[")) {
                    next();
                    var prop = expression(true);
                    expect("]");
                    return subscripts(new AST_Sub({
                        start      : start,
                        expression : expr,
                        property   : prop,
                        end        : prev()
                    }), allow_calls);
                }
                if (allow_calls && is("punc", "(")) {
                    next();
                    return subscripts(new AST_Call({
                        start      : start,
                        expression : expr,
                        args       : expr_list(")"),
                        end        : prev()
                    }), true);
                }
                return expr;
            };
        
            var maybe_unary = function(allow_calls) {
                var start = S.token;
                if (is("operator") && UNARY_PREFIX(start.value)) {
                    next();
                    handle_regexp();
                    var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
                    ex.start = start;
                    ex.end = prev();
                    return ex;
                }
                var val = expr_atom(allow_calls);
                while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
                    val = make_unary(AST_UnaryPostfix, S.token.value, val);
                    val.start = start;
                    val.end = S.token;
                    next();
                }
                return val;
            };
        
            function make_unary(ctor, op, expr) {
                if ((op == "++" || op == "--") && !is_assignable(expr))
                    croak("Invalid use of " + op + " operator");
                return new ctor({ operator: op, expression: expr });
            };
        
            var expr_op = function(left, min_prec, no_in) {
                var op = is("operator") ? S.token.value : null;
                if (op == "in" && no_in) op = null;
                var prec = op != null ? PRECEDENCE[op] : null;
                if (prec != null && prec > min_prec) {
                    next();
                    var right = expr_op(maybe_unary(true), prec, no_in);
                    return expr_op(new AST_Binary({
                        start    : left.start,
                        left     : left,
                        operator : op,
                        right    : right,
                        end      : right.end
                    }), min_prec, no_in);
                }
                return left;
            };
        
            function expr_ops(no_in) {
                return expr_op(maybe_unary(true), 0, no_in);
            };
        
            var maybe_conditional = function(no_in) {
                var start = S.token;
                var expr = expr_ops(no_in);
                if (is("operator", "?")) {
                    next();
                    var yes = expression(false);
                    expect(":");
                    return new AST_Conditional({
                        start       : start,
                        condition   : expr,
                        consequent  : yes,
                        alternative : expression(false, no_in),
                        end         : prev()
                    });
                }
                return expr;
            };
        
            function is_assignable(expr) {
                if (!options.strict) return true;
                if (expr instanceof AST_This) return false;
                return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
            };
        
            var maybe_assign = function(no_in) {
                var start = S.token;
                var left = maybe_conditional(no_in), val = S.token.value;
                if (is("operator") && ASSIGNMENT(val)) {
                    if (is_assignable(left)) {
                        next();
                        return new AST_Assign({
                            start    : start,
                            left     : left,
                            operator : val,
                            right    : maybe_assign(no_in),
                            end      : prev()
                        });
                    }
                    croak("Invalid assignment");
                }
                return left;
            };
        
            var expression = function(commas, no_in) {
                var start = S.token;
                var expr = maybe_assign(no_in);
                if (commas && is("punc", ",")) {
                    next();
                    return new AST_Seq({
                        start  : start,
                        car    : expr,
                        cdr    : expression(true, no_in),
                        end    : peek()
                    });
                }
                return expr;
            };
        
            function in_loop(cont) {
                ++S.in_loop;
                var ret = cont();
                --S.in_loop;
                return ret;
            };
        
            if (options.expression) {
                return expression(true);
            }
        
            return (function(){
                var start = S.token;
                var body = [];
                while (!is("eof"))
                    body.push(statement());
                var end = prev();
                var toplevel = options.toplevel;
                if (toplevel) {
                    toplevel.body = toplevel.body.concat(body);
                    toplevel.end = end;
                } else {
                    toplevel = new AST_Toplevel({ start: start, body: body, end: end });
                }
                return toplevel;
            })();
        
        };
        
      • scope.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function SymbolDef(scope, index, orig) {
            this.name = orig.name;
            this.orig = [ orig ];
            this.scope = scope;
            this.references = [];
            this.global = false;
            this.mangled_name = null;
            this.undeclared = false;
            this.constant = false;
            this.index = index;
        };
        
        SymbolDef.prototype = {
            unmangleable: function(options) {
                if (!options) options = {};
        
                return (this.global && !options.toplevel)
                    || this.undeclared
                    || (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
                    || (options.keep_fnames
                        && (this.orig[0] instanceof AST_SymbolLambda
                            || this.orig[0] instanceof AST_SymbolDefun));
            },
            mangle: function(options) {
                if (!this.mangled_name && !this.unmangleable(options)) {
                    var s = this.scope;
                    if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
                        s = s.parent_scope;
                    this.mangled_name = s.next_mangled(options, this);
                }
            }
        };
        
        AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
            options = defaults(options, {
                screw_ie8: false
            });
        
            // pass 1: setup scope chaining and handle definitions
            var self = this;
            var scope = self.parent_scope = null;
            var defun = null;
            var nesting = 0;
            var tw = new TreeWalker(function(node, descend){
                if (options.screw_ie8 && node instanceof AST_Catch) {
                    var save_scope = scope;
                    scope = new AST_Scope(node);
                    scope.init_scope_vars(nesting);
                    scope.parent_scope = save_scope;
                    descend();
                    scope = save_scope;
                    return true;
                }
                if (node instanceof AST_Scope) {
                    node.init_scope_vars(nesting);
                    var save_scope = node.parent_scope = scope;
                    var save_defun = defun;
                    defun = scope = node;
                    ++nesting; descend(); --nesting;
                    scope = save_scope;
                    defun = save_defun;
                    return true;        // don't descend again in TreeWalker
                }
                if (node instanceof AST_Directive) {
                    node.scope = scope;
                    push_uniq(scope.directives, node.value);
                    return true;
                }
                if (node instanceof AST_With) {
                    for (var s = scope; s; s = s.parent_scope)
                        s.uses_with = true;
                    return;
                }
                if (node instanceof AST_Symbol) {
                    node.scope = scope;
                }
                if (node instanceof AST_SymbolLambda) {
                    defun.def_function(node);
                }
                else if (node instanceof AST_SymbolDefun) {
                    // Careful here, the scope where this should be defined is
                    // the parent scope.  The reason is that we enter a new
                    // scope when we encounter the AST_Defun node (which is
                    // instanceof AST_Scope) but we get to the symbol a bit
                    // later.
                    (node.scope = defun.parent_scope).def_function(node);
                }
                else if (node instanceof AST_SymbolVar
                         || node instanceof AST_SymbolConst) {
                    var def = defun.def_variable(node);
                    def.constant = node instanceof AST_SymbolConst;
                    def.init = tw.parent().value;
                }
                else if (node instanceof AST_SymbolCatch) {
                    (options.screw_ie8 ? scope : defun)
                        .def_variable(node);
                }
            });
            self.walk(tw);
        
            // pass 2: find back references and eval
            var func = null;
            var globals = self.globals = new Dictionary();
            var tw = new TreeWalker(function(node, descend){
                if (node instanceof AST_Lambda) {
                    var prev_func = func;
                    func = node;
                    descend();
                    func = prev_func;
                    return true;
                }
                if (node instanceof AST_SymbolRef) {
                    var name = node.name;
                    var sym = node.scope.find_variable(name);
                    if (!sym) {
                        var g;
                        if (globals.has(name)) {
                            g = globals.get(name);
                        } else {
                            g = new SymbolDef(self, globals.size(), node);
                            g.undeclared = true;
                            g.global = true;
                            globals.set(name, g);
                        }
                        node.thedef = g;
                        if (name == "eval" && tw.parent() instanceof AST_Call) {
                            for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope)
                                s.uses_eval = true;
                        }
                        if (func && name == "arguments") {
                            func.uses_arguments = true;
                        }
                    } else {
                        node.thedef = sym;
                    }
                    node.reference();
                    return true;
                }
            });
            self.walk(tw);
        });
        
        AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
            this.directives = [];     // contains the directives defined in this scope, i.e. "use strict"
            this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
            this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
            this.uses_with = false;   // will be set to true if this or some nested scope uses the `with` statement
            this.uses_eval = false;   // will be set to true if this or nested scope uses the global `eval`
            this.parent_scope = null; // the parent scope
            this.enclosed = [];       // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
            this.cname = -1;          // the current index for mangling functions/variables
            this.nesting = nesting;   // the nesting level of this scope (0 means toplevel)
        });
        
        AST_Scope.DEFMETHOD("strict", function(){
            return this.has_directive("use strict");
        });
        
        AST_Lambda.DEFMETHOD("init_scope_vars", function(){
            AST_Scope.prototype.init_scope_vars.apply(this, arguments);
            this.uses_arguments = false;
        });
        
        AST_SymbolRef.DEFMETHOD("reference", function() {
            var def = this.definition();
            def.references.push(this);
            var s = this.scope;
            while (s) {
                push_uniq(s.enclosed, def);
                if (s === def.scope) break;
                s = s.parent_scope;
            }
            this.frame = this.scope.nesting - def.scope.nesting;
        });
        
        AST_Scope.DEFMETHOD("find_variable", function(name){
            if (name instanceof AST_Symbol) name = name.name;
            return this.variables.get(name)
                || (this.parent_scope && this.parent_scope.find_variable(name));
        });
        
        AST_Scope.DEFMETHOD("has_directive", function(value){
            return this.parent_scope && this.parent_scope.has_directive(value)
                || (this.directives.indexOf(value) >= 0 ? this : null);
        });
        
        AST_Scope.DEFMETHOD("def_function", function(symbol){
            this.functions.set(symbol.name, this.def_variable(symbol));
        });
        
        AST_Scope.DEFMETHOD("def_variable", function(symbol){
            var def;
            if (!this.variables.has(symbol.name)) {
                def = new SymbolDef(this, this.variables.size(), symbol);
                this.variables.set(symbol.name, def);
                def.global = !this.parent_scope;
            } else {
                def = this.variables.get(symbol.name);
                def.orig.push(symbol);
            }
            return symbol.thedef = def;
        });
        
        AST_Scope.DEFMETHOD("next_mangled", function(options){
            var ext = this.enclosed;
            out: while (true) {
                var m = base54(++this.cname);
                if (!is_identifier(m)) continue; // skip over "do"
        
                // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
                // shadow a name excepted from mangling.
                if (options.except.indexOf(m) >= 0) continue;
        
                // we must ensure that the mangled name does not shadow a name
                // from some parent scope that is referenced in this or in
                // inner scopes.
                for (var i = ext.length; --i >= 0;) {
                    var sym = ext[i];
                    var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
                    if (m == name) continue out;
                }
                return m;
            }
        });
        
        AST_Function.DEFMETHOD("next_mangled", function(options, def){
            // #179, #326
            // in Safari strict mode, something like (function x(x){...}) is a syntax error;
            // a function expression's argument cannot shadow the function expression's name
        
            var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
            while (true) {
                var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
                if (!(tricky_def && tricky_def.mangled_name == name))
                    return name;
            }
        });
        
        AST_Scope.DEFMETHOD("references", function(sym){
            if (sym instanceof AST_Symbol) sym = sym.definition();
            return this.enclosed.indexOf(sym) < 0 ? null : sym;
        });
        
        AST_Symbol.DEFMETHOD("unmangleable", function(options){
            return this.definition().unmangleable(options);
        });
        
        // property accessors are not mangleable
        AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
            return true;
        });
        
        // labels are always mangleable
        AST_Label.DEFMETHOD("unmangleable", function(){
            return false;
        });
        
        AST_Symbol.DEFMETHOD("unreferenced", function(){
            return this.definition().references.length == 0
                && !(this.scope.uses_eval || this.scope.uses_with);
        });
        
        AST_Symbol.DEFMETHOD("undeclared", function(){
            return this.definition().undeclared;
        });
        
        AST_LabelRef.DEFMETHOD("undeclared", function(){
            return false;
        });
        
        AST_Label.DEFMETHOD("undeclared", function(){
            return false;
        });
        
        AST_Symbol.DEFMETHOD("definition", function(){
            return this.thedef;
        });
        
        AST_Symbol.DEFMETHOD("global", function(){
            return this.definition().global;
        });
        
        AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
            return defaults(options, {
                except      : [],
                eval        : false,
                sort        : false,
                toplevel    : false,
                screw_ie8   : false,
                keep_fnames : false
            });
        });
        
        AST_Toplevel.DEFMETHOD("mangle_names", function(options){
            options = this._default_mangler_options(options);
            // We only need to mangle declaration nodes.  Special logic wired
            // into the code generator will display the mangled name if it's
            // present (and for AST_SymbolRef-s it'll use the mangled name of
            // the AST_SymbolDeclaration that it points to).
            var lname = -1;
            var to_mangle = [];
            var tw = new TreeWalker(function(node, descend){
                if (node instanceof AST_LabeledStatement) {
                    // lname is incremented when we get to the AST_Label
                    var save_nesting = lname;
                    descend();
                    lname = save_nesting;
                    return true;        // don't descend again in TreeWalker
                }
                if (node instanceof AST_Scope) {
                    var p = tw.parent(), a = [];
                    node.variables.each(function(symbol){
                        if (options.except.indexOf(symbol.name) < 0) {
                            a.push(symbol);
                        }
                    });
                    if (options.sort) a.sort(function(a, b){
                        return b.references.length - a.references.length;
                    });
                    to_mangle.push.apply(to_mangle, a);
                    return;
                }
                if (node instanceof AST_Label) {
                    var name;
                    do name = base54(++lname); while (!is_identifier(name));
                    node.mangled_name = name;
                    return true;
                }
                if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
                    to_mangle.push(node.definition());
                    return;
                }
            });
            this.walk(tw);
            to_mangle.forEach(function(def){ def.mangle(options) });
        });
        
        AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
            options = this._default_mangler_options(options);
            var tw = new TreeWalker(function(node){
                if (node instanceof AST_Constant)
                    base54.consider(node.print_to_string());
                else if (node instanceof AST_Return)
                    base54.consider("return");
                else if (node instanceof AST_Throw)
                    base54.consider("throw");
                else if (node instanceof AST_Continue)
                    base54.consider("continue");
                else if (node instanceof AST_Break)
                    base54.consider("break");
                else if (node instanceof AST_Debugger)
                    base54.consider("debugger");
                else if (node instanceof AST_Directive)
                    base54.consider(node.value);
                else if (node instanceof AST_While)
                    base54.consider("while");
                else if (node instanceof AST_Do)
                    base54.consider("do while");
                else if (node instanceof AST_If) {
                    base54.consider("if");
                    if (node.alternative) base54.consider("else");
                }
                else if (node instanceof AST_Var)
                    base54.consider("var");
                else if (node instanceof AST_Const)
                    base54.consider("const");
                else if (node instanceof AST_Lambda)
                    base54.consider("function");
                else if (node instanceof AST_For)
                    base54.consider("for");
                else if (node instanceof AST_ForIn)
                    base54.consider("for in");
                else if (node instanceof AST_Switch)
                    base54.consider("switch");
                else if (node instanceof AST_Case)
                    base54.consider("case");
                else if (node instanceof AST_Default)
                    base54.consider("default");
                else if (node instanceof AST_With)
                    base54.consider("with");
                else if (node instanceof AST_ObjectSetter)
                    base54.consider("set" + node.key);
                else if (node instanceof AST_ObjectGetter)
                    base54.consider("get" + node.key);
                else if (node instanceof AST_ObjectKeyVal)
                    base54.consider(node.key);
                else if (node instanceof AST_New)
                    base54.consider("new");
                else if (node instanceof AST_This)
                    base54.consider("this");
                else if (node instanceof AST_Try)
                    base54.consider("try");
                else if (node instanceof AST_Catch)
                    base54.consider("catch");
                else if (node instanceof AST_Finally)
                    base54.consider("finally");
                else if (node instanceof AST_Symbol && node.unmangleable(options))
                    base54.consider(node.name);
                else if (node instanceof AST_Unary || node instanceof AST_Binary)
                    base54.consider(node.operator);
                else if (node instanceof AST_Dot)
                    base54.consider(node.property);
            });
            this.walk(tw);
            base54.sort();
        });
        
        var base54 = (function() {
            var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
            var chars, frequency;
            function reset() {
                frequency = Object.create(null);
                chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
                chars.forEach(function(ch){ frequency[ch] = 0 });
            }
            base54.consider = function(str){
                for (var i = str.length; --i >= 0;) {
                    var code = str.charCodeAt(i);
                    if (code in frequency) ++frequency[code];
                }
            };
            base54.sort = function() {
                chars = mergeSort(chars, function(a, b){
                    if (is_digit(a) && !is_digit(b)) return 1;
                    if (is_digit(b) && !is_digit(a)) return -1;
                    return frequency[b] - frequency[a];
                });
            };
            base54.reset = reset;
            reset();
            base54.get = function(){ return chars };
            base54.freq = function(){ return frequency };
            function base54(num) {
                var ret = "", base = 54;
                num++;
                do {
                    num--;
                    ret += String.fromCharCode(chars[num % base]);
                    num = Math.floor(num / base);
                    base = 64;
                } while (num > 0);
                return ret;
            };
            return base54;
        })();
        
        AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
            options = defaults(options, {
                undeclared       : false, // this makes a lot of noise
                unreferenced     : true,
                assign_to_global : true,
                func_arguments   : true,
                nested_defuns    : true,
                eval             : true
            });
            var tw = new TreeWalker(function(node){
                if (options.undeclared
                    && node instanceof AST_SymbolRef
                    && node.undeclared())
                {
                    // XXX: this also warns about JS standard names,
                    // i.e. Object, Array, parseInt etc.  Should add a list of
                    // exceptions.
                    AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
                        name: node.name,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.assign_to_global)
                {
                    var sym = null;
                    if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
                        sym = node.left;
                    else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
                        sym = node.init;
                    if (sym
                        && (sym.undeclared()
                            || (sym.global() && sym.scope !== sym.definition().scope))) {
                        AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
                            msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
                            name: sym.name,
                            file: sym.start.file,
                            line: sym.start.line,
                            col: sym.start.col
                        });
                    }
                }
                if (options.eval
                    && node instanceof AST_SymbolRef
                    && node.undeclared()
                    && node.name == "eval") {
                    AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
                }
                if (options.unreferenced
                    && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
                    && !(node instanceof AST_SymbolCatch)
                    && node.unreferenced()) {
                    AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
                        type: node instanceof AST_Label ? "Label" : "Symbol",
                        name: node.name,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.func_arguments
                    && node instanceof AST_Lambda
                    && node.uses_arguments) {
                    AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
                        name: node.name ? node.name.name : "anonymous",
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.nested_defuns
                    && node instanceof AST_Defun
                    && !(tw.parent() instanceof AST_Scope)) {
                    AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
                        name: node.name.name,
                        type: tw.parent().TYPE,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
            });
            this.walk(tw);
        });
        
      • sourcemap.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        // a small wrapper around fitzgen's source-map library
        function SourceMap(options) {
            options = defaults(options, {
                file : null,
                root : null,
                orig : null,
        
                orig_line_diff : 0,
                dest_line_diff : 0,
            });
            var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
            var generator;
            if (orig_map) {
              generator = MOZ_SourceMap.SourceMapGenerator.fromSourceMap(orig_map);
            } else {
                generator = new MOZ_SourceMap.SourceMapGenerator({
                    file       : options.file,
                    sourceRoot : options.root
                });
            }
            function add(source, gen_line, gen_col, orig_line, orig_col, name) {
                if (orig_map) {
                    var info = orig_map.originalPositionFor({
                        line: orig_line,
                        column: orig_col
                    });
                    if (info.source === null) {
                        return;
                    }
                    source = info.source;
                    orig_line = info.line;
                    orig_col = info.column;
                    name = info.name || name;
                }
                generator.addMapping({
                    generated : { line: gen_line + options.dest_line_diff, column: gen_col },
                    original  : { line: orig_line + options.orig_line_diff, column: orig_col },
                    source    : source,
                    name      : name
                });
            }
            return {
                add        : add,
                get        : function() { return generator },
                toString   : function() { return JSON.stringify(generator.toJSON()); }
            };
        };
        
      • transform.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        // Tree transformer helpers.
        
        function TreeTransformer(before, after) {
            TreeWalker.call(this);
            this.before = before;
            this.after = after;
        }
        TreeTransformer.prototype = new TreeWalker;
        
        (function(undefined){
        
            function _(node, descend) {
                node.DEFMETHOD("transform", function(tw, in_list){
                    var x, y;
                    tw.push(this);
                    if (tw.before) x = tw.before(this, descend, in_list);
                    if (x === undefined) {
                        if (!tw.after) {
                            x = this;
                            descend(x, tw);
                        } else {
                            tw.stack[tw.stack.length - 1] = x = this.clone();
                            descend(x, tw);
                            y = tw.after(x, in_list);
                            if (y !== undefined) x = y;
                        }
                    }
                    tw.pop();
                    return x;
                });
            };
        
            function do_list(list, tw) {
                return MAP(list, function(node){
                    return node.transform(tw, true);
                });
            };
        
            _(AST_Node, noop);
        
            _(AST_LabeledStatement, function(self, tw){
                self.label = self.label.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_SimpleStatement, function(self, tw){
                self.body = self.body.transform(tw);
            });
        
            _(AST_Block, function(self, tw){
                self.body = do_list(self.body, tw);
            });
        
            _(AST_DWLoop, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_For, function(self, tw){
                if (self.init) self.init = self.init.transform(tw);
                if (self.condition) self.condition = self.condition.transform(tw);
                if (self.step) self.step = self.step.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_ForIn, function(self, tw){
                self.init = self.init.transform(tw);
                self.object = self.object.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_With, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_Exit, function(self, tw){
                if (self.value) self.value = self.value.transform(tw);
            });
        
            _(AST_LoopControl, function(self, tw){
                if (self.label) self.label = self.label.transform(tw);
            });
        
            _(AST_If, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.body = self.body.transform(tw);
                if (self.alternative) self.alternative = self.alternative.transform(tw);
            });
        
            _(AST_Switch, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Case, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Try, function(self, tw){
                self.body = do_list(self.body, tw);
                if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
                if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
            });
        
            _(AST_Catch, function(self, tw){
                self.argname = self.argname.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Definitions, function(self, tw){
                self.definitions = do_list(self.definitions, tw);
            });
        
            _(AST_VarDef, function(self, tw){
                self.name = self.name.transform(tw);
                if (self.value) self.value = self.value.transform(tw);
            });
        
            _(AST_Lambda, function(self, tw){
                if (self.name) self.name = self.name.transform(tw);
                self.argnames = do_list(self.argnames, tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Call, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.args = do_list(self.args, tw);
            });
        
            _(AST_Seq, function(self, tw){
                self.car = self.car.transform(tw);
                self.cdr = self.cdr.transform(tw);
            });
        
            _(AST_Dot, function(self, tw){
                self.expression = self.expression.transform(tw);
            });
        
            _(AST_Sub, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.property = self.property.transform(tw);
            });
        
            _(AST_Unary, function(self, tw){
                self.expression = self.expression.transform(tw);
            });
        
            _(AST_Binary, function(self, tw){
                self.left = self.left.transform(tw);
                self.right = self.right.transform(tw);
            });
        
            _(AST_Conditional, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.consequent = self.consequent.transform(tw);
                self.alternative = self.alternative.transform(tw);
            });
        
            _(AST_Array, function(self, tw){
                self.elements = do_list(self.elements, tw);
            });
        
            _(AST_Object, function(self, tw){
                self.properties = do_list(self.properties, tw);
            });
        
            _(AST_ObjectProperty, function(self, tw){
                self.value = self.value.transform(tw);
            });
        
        })();
        
      • utils.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function array_to_hash(a) {
            var ret = Object.create(null);
            for (var i = 0; i < a.length; ++i)
                ret[a[i]] = true;
            return ret;
        };
        
        function slice(a, start) {
            return Array.prototype.slice.call(a, start || 0);
        };
        
        function characters(str) {
            return str.split("");
        };
        
        function member(name, array) {
            for (var i = array.length; --i >= 0;)
                if (array[i] == name)
                    return true;
            return false;
        };
        
        function find_if(func, array) {
            for (var i = 0, n = array.length; i < n; ++i) {
                if (func(array[i]))
                    return array[i];
            }
        };
        
        function repeat_string(str, i) {
            if (i <= 0) return "";
            if (i == 1) return str;
            var d = repeat_string(str, i >> 1);
            d += d;
            if (i & 1) d += str;
            return d;
        };
        
        function DefaultsError(msg, defs) {
            Error.call(this, msg);
            this.msg = msg;
            this.defs = defs;
        };
        DefaultsError.prototype = Object.create(Error.prototype);
        DefaultsError.prototype.constructor = DefaultsError;
        
        DefaultsError.croak = function(msg, defs) {
            throw new DefaultsError(msg, defs);
        };
        
        function defaults(args, defs, croak) {
            if (args === true)
                args = {};
            var ret = args || {};
            if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
                DefaultsError.croak("`" + i + "` is not a supported option", defs);
            for (var i in defs) if (defs.hasOwnProperty(i)) {
                ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
            }
            return ret;
        };
        
        function merge(obj, ext) {
            for (var i in ext) if (ext.hasOwnProperty(i)) {
                obj[i] = ext[i];
            }
            return obj;
        };
        
        function noop() {};
        
        var MAP = (function(){
            function MAP(a, f, backwards) {
                var ret = [], top = [], i;
                function doit() {
                    var val = f(a[i], i);
                    var is_last = val instanceof Last;
                    if (is_last) val = val.v;
                    if (val instanceof AtTop) {
                        val = val.v;
                        if (val instanceof Splice) {
                            top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
                        } else {
                            top.push(val);
                        }
                    }
                    else if (val !== skip) {
                        if (val instanceof Splice) {
                            ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
                        } else {
                            ret.push(val);
                        }
                    }
                    return is_last;
                };
                if (a instanceof Array) {
                    if (backwards) {
                        for (i = a.length; --i >= 0;) if (doit()) break;
                        ret.reverse();
                        top.reverse();
                    } else {
                        for (i = 0; i < a.length; ++i) if (doit()) break;
                    }
                }
                else {
                    for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
                }
                return top.concat(ret);
            };
            MAP.at_top = function(val) { return new AtTop(val) };
            MAP.splice = function(val) { return new Splice(val) };
            MAP.last = function(val) { return new Last(val) };
            var skip = MAP.skip = {};
            function AtTop(val) { this.v = val };
            function Splice(val) { this.v = val };
            function Last(val) { this.v = val };
            return MAP;
        })();
        
        function push_uniq(array, el) {
            if (array.indexOf(el) < 0)
                array.push(el);
        };
        
        function string_template(text, props) {
            return text.replace(/\{(.+?)\}/g, function(str, p){
                return props[p];
            });
        };
        
        function remove(array, el) {
            for (var i = array.length; --i >= 0;) {
                if (array[i] === el) array.splice(i, 1);
            }
        };
        
        function mergeSort(array, cmp) {
            if (array.length < 2) return array.slice();
            function merge(a, b) {
                var r = [], ai = 0, bi = 0, i = 0;
                while (ai < a.length && bi < b.length) {
                    cmp(a[ai], b[bi]) <= 0
                        ? r[i++] = a[ai++]
                        : r[i++] = b[bi++];
                }
                if (ai < a.length) r.push.apply(r, a.slice(ai));
                if (bi < b.length) r.push.apply(r, b.slice(bi));
                return r;
            };
            function _ms(a) {
                if (a.length <= 1)
                    return a;
                var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
                left = _ms(left);
                right = _ms(right);
                return merge(left, right);
            };
            return _ms(array);
        };
        
        function set_difference(a, b) {
            return a.filter(function(el){
                return b.indexOf(el) < 0;
            });
        };
        
        function set_intersection(a, b) {
            return a.filter(function(el){
                return b.indexOf(el) >= 0;
            });
        };
        
        // this function is taken from Acorn [1], written by Marijn Haverbeke
        // [1] https://github.com/marijnh/acorn
        function makePredicate(words) {
            if (!(words instanceof Array)) words = words.split(" ");
            var f = "", cats = [];
            out: for (var i = 0; i < words.length; ++i) {
                for (var j = 0; j < cats.length; ++j)
                    if (cats[j][0].length == words[i].length) {
                        cats[j].push(words[i]);
                        continue out;
                    }
                cats.push([words[i]]);
            }
            function compareTo(arr) {
                if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
                f += "switch(str){";
                for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
                f += "return true}return false;";
            }
            // When there are more than three length categories, an outer
            // switch first dispatches on the lengths, to save on comparisons.
            if (cats.length > 3) {
                cats.sort(function(a, b) {return b.length - a.length;});
                f += "switch(str.length){";
                for (var i = 0; i < cats.length; ++i) {
                    var cat = cats[i];
                    f += "case " + cat[0].length + ":";
                    compareTo(cat);
                }
                f += "}";
                // Otherwise, simply generate a flat `switch` statement.
            } else {
                compareTo(words);
            }
            return new Function("str", f);
        };
        
        function all(array, predicate) {
            for (var i = array.length; --i >= 0;)
                if (!predicate(array[i]))
                    return false;
            return true;
        };
        
        function Dictionary() {
            this._values = Object.create(null);
            this._size = 0;
        };
        Dictionary.prototype = {
            set: function(key, val) {
                if (!this.has(key)) ++this._size;
                this._values["$" + key] = val;
                return this;
            },
            add: function(key, val) {
                if (this.has(key)) {
                    this.get(key).push(val);
                } else {
                    this.set(key, [ val ]);
                }
                return this;
            },
            get: function(key) { return this._values["$" + key] },
            del: function(key) {
                if (this.has(key)) {
                    --this._size;
                    delete this._values["$" + key];
                }
                return this;
            },
            has: function(key) { return ("$" + key) in this._values },
            each: function(f) {
                for (var i in this._values)
                    f(this._values[i], i.substr(1));
            },
            size: function() {
                return this._size;
            },
            map: function(f) {
                var ret = [];
                for (var i in this._values)
                    ret.push(f(this._values[i], i.substr(1)));
                return ret;
            }
        };
        
    • uglifyCSS
      • uglifycss-lib.js
        /**
         * UglifyCSS
         * Port of YUI CSS Compressor to NodeJS
         * Author: Franck Marcia - https://github.com/fmarcia
         * MIT licenced
         */
        
        /**
         * cssmin.js
         * Author: Stoyan Stefanov - http://phpied.com/
         * This is a JavaScript port of the CSS minification tool
         * distributed with YUICompressor, itself a port
         * of the cssmin utility by Isaac Schlueter - http://foohack.com/
         * Permission is hereby granted to use the JavaScript version under the same
         * conditions as the YUICompressor (original YUICompressor note below).
         */
        
        /**
         * YUI Compressor
         * http://developer.yahoo.com/yui/compressor/
         * Author: Julien Lecomte - http://www.julienlecomte.net/
         * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
         * The copyrights embodied in the content of this file are licensed
         * by Yahoo! Inc. under the BSD (revised) open source license.
         */
        
        'use strict';
        
        var util = require('util');
        var fs = require('fs');
        
        var defaultOptions = {
            maxLineLen: 0,
            expandVars: false,
            uglyComments: false,
            cuteComments: false
        };
        
        /**
         * Utility method to replace all data urls with tokens before we start
         * compressing, to avoid performance issues running some of the subsequent
         * regexes against large strings chunks.
         *
         * @private
         * @function extractDataUrls
         * @param {String} css The input css
         * @param {Array} The global array of tokens to preserve
         * @returns String The processed css
         */
        function extractDataUrls(css, preservedTokens) {
        
            // Leave data urls alone to increase parse performance.
            var maxIndex = css.length - 1,
                appendIndex = 0,
                startIndex,
                endIndex,
                terminator,
                foundTerminator,
                sb = [],
                m,
                preserver,
                token,
                pattern = /url\(\s*(["']?)data\:/g;
        
            // Since we need to account for non-base64 data urls, we need to handle
            // ' and ) being part of the data string. Hence switching to indexOf,
            // to determine whether or not we have matching string terminators and
            // handling sb appends directly, instead of using matcher.append* methods.
        
            while ((m = pattern.exec(css)) !== null) {
        
                startIndex = m.index + 4;  // "url(".length()
                terminator = m[1];         // ', " or empty (not quoted)
        
                if (terminator.length === 0) {
                    terminator = ")";
                }
        
                foundTerminator = false;
        
                endIndex = pattern.lastIndex - 1;
        
                while(foundTerminator === false && endIndex+1 <= maxIndex) {
                    endIndex = css.indexOf(terminator, endIndex + 1);
        
                    // endIndex == 0 doesn't really apply here
                    if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) {
                        foundTerminator = true;
                        if (")" != terminator) {
                            endIndex = css.indexOf(")", endIndex);
                        }
                    }
                }
        
                // Enough searching, start moving stuff over to the buffer
                sb.push(css.substring(appendIndex, m.index));
        
                if (foundTerminator) {
                    token = css.substring(startIndex, endIndex);
                    token = token.replace(/\s+/g, "");
                    preservedTokens.push(token);
        
                    preserver = "url(___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)";
                    sb.push(preserver);
        
                    appendIndex = endIndex + 1;
                } else {
                    // No end terminator found, re-add the whole match. Should we throw/warn here?
                    sb.push(css.substring(m.index, pattern.lastIndex));
                    appendIndex = pattern.lastIndex;
                }
            }
        
            sb.push(css.substring(appendIndex));
        
            return sb.join("");
        }
        
        /**
         * Utility method to compress hex color values of the form #AABBCC to #ABC.
         *
         * DOES NOT compress CSS ID selectors which match the above pattern (which would break things).
         * e.g. #AddressForm { ... }
         *
         * DOES NOT compress IE filters, which have hex color values (which would break things).
         * e.g. filter: chroma(color="#FFFFFF");
         *
         * DOES NOT compress invalid hex values.
         * e.g. background-color: #aabbccdd
         *
         * @private
         * @function compressHexColors
         * @param {String} css The input css
         * @returns String The processed css
         */
        function compressHexColors(css) {
        
            // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters)
            var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi,
                m,
                index = 0,
                isFilter,
                sb = [];
        
            while ((m = pattern.exec(css)) !== null) {
        
                sb.push(css.substring(index, m.index));
        
                isFilter = m[1];
        
                if (isFilter) {
                    // Restore, maintain case, otherwise filter will break
                    sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]));
                } else {
                    if (m[2].toLowerCase() == m[3].toLowerCase() &&
                        m[4].toLowerCase() == m[5].toLowerCase() &&
                        m[6].toLowerCase() == m[7].toLowerCase()) {
        
                        // Compress.
                        sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase());
                    } else {
                        // Non compressible color, restore but lower case.
                        sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase());
                    }
                }
        
                index = pattern.lastIndex = pattern.lastIndex - m[8].length;
            }
        
            sb.push(css.substring(index));
        
            return sb.join("");
        }
        
        // Preserve 0 followed by unit in keyframes steps
        
        function keyframes(content, preservedTokens) {
        
            var level,
                buffer,
                buffers,
                pattern = /@[a-z0-9-_]*keyframes\s+[a-z0-9-_]+\s*{/gi,
                index = 0,
                len,
                c,
                startIndex;
        
            var preserve = function (part, index) {
                part = part.replace(/(^\s|\s$)/g, '');
                if (part.charAt(0) === '0') {
                    preservedTokens.push(part);
                    buffer[index] = "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
                }
            };
        
            while (true) {
        
                level = 0;
                buffer = '';
        
                startIndex = content.slice(index).search(pattern);
                if (startIndex < 0) {
                    break;
                }
        
                index += startIndex;
                startIndex = index;
                len = content.length;
                buffers = [];
        
                for (; index < len; ++index) {
        
                    c = content.charAt(index);
        
                    if (c === '{') {
        
                        if (level === 0) {
                            buffers.push(buffer.replace(/(^\s|\s$)/g, ''));
        
                        } else if (level === 1) {
        
                            buffer = buffer.split(',');
        
                            buffer.forEach(preserve);
        
                            buffers.push(buffer.join(',').replace(/(^\s|\s$)/g, ''));
                        }
        
                        buffer = '';
                        level += 1;
        
                    } else if (c === '}') {
        
                        if (level === 2) {
                            buffers.push('{' + buffer.replace(/(^\s|\s$)/g, '') + '}');
                            buffer = '';
        
                        } else if (level === 1) {
                            content = content.slice(0, startIndex) +
                                buffers.shift() + '{' +
                                buffers.join('') +
                                content.slice(index);
                            break;
                        }
        
                        level -= 1;
                    }
        
                    if (level < 0) {
                        break;
        
                    } else if (c !== '{' && c !== '}') {
                        buffer += c;
                    }
                }
            }
        
            return content;
        }
        
        // Uglify a CSS string
        
        function processString(content, options) {
        
            var startIndex,
                endIndex,
                comments = [],
                preservedTokens = [],
                token,
                len = content.length,
                pattern,
                quote,
                rgbcolors,
                hexcolor,
                placeholder,
                val,
                i,
                c,
                line = [],
                lines = [],
                vars = {};
        
            options = options || defaultOptions;
        
            content = extractDataUrls(content, preservedTokens);
        
            // collect all comment blocks...
            while ((startIndex = content.indexOf("/*", startIndex)) >= 0) {
                endIndex = content.indexOf("*/", startIndex + 2);
                if (endIndex < 0) {
                    endIndex = len;
                }
                token = content.slice(startIndex + 2, endIndex);
                comments.push(token);
                content = content.slice(0, startIndex + 2) + "___PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + content.slice(endIndex);
                startIndex += 2;
            }
        
            // preserve strings so their content doesn't get accidentally minified
            pattern = /("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g;
            content = content.replace(pattern, function (token) {
                quote = token.substring(0, 1);
                token = token.slice(1, -1);
                // maybe the string contains a comment-like substring or more? put'em back then
                if (token.indexOf("___PRESERVE_CANDIDATE_COMMENT_") >= 0) {
                    for (i = 0, len = comments.length; i < len; i += 1) {
                        token = token.replace("___PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]);
                    }
                }
                // minify alpha opacity in filter strings
                token = token.replace(/progid:DXImageTransform.Microsoft.Alpha\(Opacity=/gi, "alpha(opacity=");
                preservedTokens.push(token);
                return quote + "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote;
            });
        
            // strings are safe, now wrestle the comments
            for (i = 0, len = comments.length; i < len; i += 1) {
        
                token = comments[i];
                placeholder = "___PRESERVE_CANDIDATE_COMMENT_" + i + "___";
        
                // ! in the first position of the comment means preserve
                // so push to the preserved tokens keeping the !
                if (token.charAt(0) === "!") {
                    if (options.cuteComments) {
                        preservedTokens.push(token.substring(1));
                    } else if (options.uglyComments) {
                        preservedTokens.push(token.substring(1).replace(/[\r\n]/g, ''));
                    } else {
                        preservedTokens.push(token);
                    }
                    content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                    continue;
                }
        
                // \ in the last position looks like hack for Mac/IE5
                // shorten that to /*\*/ and the next one to /**/
                if (token.charAt(token.length - 1) === "\\") {
                    preservedTokens.push("\\");
                    content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                    i = i + 1; // attn: advancing the loop
                    preservedTokens.push("");
                    content = content.replace(
                        "___PRESERVE_CANDIDATE_COMMENT_" + i + "___",
                        "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"
                    );
                    continue;
                }
        
                // keep empty comments after child selectors (IE7 hack)
                // e.g. html >/**/ body
                if (token.length === 0) {
                    startIndex = content.indexOf(placeholder);
                    if (startIndex > 2) {
                        if (content.charAt(startIndex - 3) === '>') {
                            preservedTokens.push("");
                            content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                        }
                    }
                }
        
                // in all other cases kill the comment
                content = content.replace("/*" + placeholder + "*/", "");
            }
        
            if (options.expandVars) {
                // parse simple @variables blocks and remove them
                pattern = /@variables\s*\{\s*([^\}]+)\s*\}/g;
                content = content.replace(pattern, function (ignore, f1) {
                    pattern = /\s*([a-z0-9\-]+)\s*:\s*([^;\}]+)\s*/gi;
                    f1.replace(pattern, function (ignore, f1, f2) {
                        if (f1 && f2) {
                        vars[f1] = f2;
                        }
                        return '';
                    });
                    return '';
                });
        
                // replace var(x) with the value of x
                pattern = /var\s*\(\s*([^\)]+)\s*\)/g;
                content = content.replace(pattern, function (ignore, f1) {
                    return vars[f1] || 'none';
                });
            }
        
            // normalize all whitespace strings to single spaces. Easier to work with that way.
            content = content.replace(/\s+/g, " ");
        
            // preserve formulas in calc() before removing spaces
            pattern = /calc\(([^\)\()]*)\)/;
            var preserveCalc = function (ignore, f1) {
                preservedTokens.push('calc(' + f1.replace(/(^\s*|\s*$)/g, "") + ')');
                return "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
            };
            while (true) {
                if (pattern.test(content)) {
                    content = content.replace(pattern, preserveCalc);
                } else {
                    break;
                }
            }
        
            // preserve matrix
            pattern = /\s*filter:\s*progid:DXImageTransform.Microsoft.Matrix\(([^\)]+)\);/g;
            content = content.replace(pattern, function (ignore, f1) {
                preservedTokens.push(f1);
                return "filter:progid:DXImageTransform.Microsoft.Matrix(___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___);";
            });
        
            // remove the spaces before the things that should not have spaces before them.
            // but, be careful not to turn "p :link {...}" into "p:link{...}"
            // swap out any pseudo-class colons with the token, and then swap back.
            pattern = /(^|\})(([^\{:])+:)+([^\{]*\{)/g;
            content = content.replace(pattern, function (token) {
                return token.replace(/:/g, "___PSEUDOCLASSCOLON___");
            });
        
            // remove spaces before the things that should not have spaces before them.
            content = content.replace(/\s+([!{};:>+\(\)\],])/g, "$1");
        
            // restore spaces for !important
            content = content.replace(/!important/g, " !important");
        
            // bring back the colon
            content = content.replace(/___PSEUDOCLASSCOLON___/g, ":");
        
            // preserve 0 followed by a time unit for properties using time units
            pattern = /\s*(animation|animation-delay|animation-duration|transition|transition-delay|transition-duration):\s*([^;}]+)/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
        
                f2 = f2.replace(/(\s*)0?.?0(m?s)\s*/gi, function (ignore, g1, g2) {
                    preservedTokens.push('0s');
                    return g1 + "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
                });
        
                return f1 + ":" + f2;
            });
        
            // preserve 0 followed by unit in keyframes steps (WIP)
            content = keyframes(content, preservedTokens);
        
            // retain space for special IE6 cases
            content = content.replace(/:first-(line|letter)(\{|,)/gi, function (ignore, f1, f2) {
                return ":first-" + f1.toLowerCase() + " " + f2;
            });
        
            // newlines before and after the end of a preserved comment
            if (options.cuteComments) {
                content = content.replace(/\s*\/\*/g, "___PRESERVED_NEWLINE___/*");
                content = content.replace(/\*\/\s*/g, "*/___PRESERVED_NEWLINE___");
            // no space after the end of a preserved comment
            } else {
                content = content.replace(/\*\/\s*/g, '*/');
            }
        
            // If there are multiple @charset directives, push them to the top of the file.
            pattern = /^(.*)(@charset)( "[^"]*";)/gi;
            content = content.replace(pattern, function (ignore, f1, f2, f3) {
                return f2.toLowerCase() + f3 + f1;
            });
        
            // When all @charset are at the top, remove the second and after (as they are completely ignored).
            pattern = /^((\s*)(@charset)( [^;]+;\s*))+/gi;
            content = content.replace(pattern, function (ignore, ignore2, f2, f3, f4) {
                return f2 + f3.toLowerCase() + f4;
            });
        
            // lowercase some popular @directives (@charset is done right above)
            pattern = /@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return '@' + f1.toLowerCase();
            });
        
            // lowercase some more common pseudo-elements
            pattern = /:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return ':' + f1.toLowerCase();
            });
        
            // if there is a @charset, then only allow one, and push to the top of the file.
            content = content.replace(/^(.*)(@charset \"[^\"]*\";)/g, "$2$1");
            content = content.replace(/^(\s*@charset [^;]+;\s*)+/g, "$1");
        
            // lowercase some more common functions
            pattern = /:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?any)\(/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return ':' + f1.toLowerCase() + '(';
            });
        
            // lower case some common function that can be values
            // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us right after this
            pattern = /([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1 + f2.toLowerCase();
            });
        
            // put the space back in some cases, to support stuff like
            // @media screen and (-webkit-min-device-pixel-ratio:0){
            content = content.replace(/\band\(/gi, "and (");
        
            // remove the spaces after the things that should not have spaces after them.
            content = content.replace(/([!{}:;>+\(\[,])\s+/g, "$1");
        
            // remove unnecessary semicolons
            content = content.replace(/;+\}/g, "}");
        
            // replace 0(px,em,%) with 0.
            content = content.replace(/(^|[^.0-9])(?:0?\.)?0(?:ex|ch|r?em|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|g?rad|turn|m?s|k?Hz|dpi|dpcm|dppx|%)/gi, "$10");
        
            // Replace x.0(px,em,%) with x(px,em,%).
            content = content.replace(/([0-9])\.0(ex|ch|r?em|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|g?rad|turn|m?s|k?Hz|dpi|dpcm|dppx|%| |;)/gi, "$1$2");
        
            // replace 0 0 0 0; with 0.
            content = content.replace(/:0 0 0 0(;|\})/g, ":0$1");
            content = content.replace(/:0 0 0(;|\})/g, ":0$1");
            content = content.replace(/:0 0(;|\})/g, ":0$1");
        
            // replace background-position:0; with background-position:0 0;
            // same for transform-origin
            pattern = /(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1.toLowerCase() + ":0 0" + f2;
            });
        
            // replace 0.6 to .6, but only when preceded by : or a white-space
            content = content.replace(/(:|\s)0+\.(\d+)/g, "$1.$2");
        
            // shorten colors from rgb(51,102,153) to #336699
            // this makes it more likely that it'll get further compressed in the next step.
            pattern = /rgb\s*\(\s*([0-9,\s]+)\s*\)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                rgbcolors = f1.split(",");
                hexcolor = "#";
                for (i = 0; i < rgbcolors.length; i += 1) {
                    val = parseInt(rgbcolors[i], 10);
                    if (val < 16) {
                        hexcolor += "0";
                    }
                    if (val > 255) {
                        val = 255;
                    }
                    hexcolor += val.toString(16);
                }
                return hexcolor;
            });
        
            // Shorten colors from #AABBCC to #ABC.
            content = compressHexColors(content);
        
            // Replace #f00 -> red
            content = content.replace(/(:|\s)(#f00)(;|})/g, "$1red$3");
        
            // Replace other short color keywords
            content = content.replace(/(:|\s)(#000080)(;|})/g, "$1navy$3");
            content = content.replace(/(:|\s)(#808080)(;|})/g, "$1gray$3");
            content = content.replace(/(:|\s)(#808000)(;|})/g, "$1olive$3");
            content = content.replace(/(:|\s)(#800080)(;|})/g, "$1purple$3");
            content = content.replace(/(:|\s)(#c0c0c0)(;|})/g, "$1silver$3");
            content = content.replace(/(:|\s)(#008080)(;|})/g, "$1teal$3");
            content = content.replace(/(:|\s)(#ffa500)(;|})/g, "$1orange$3");
            content = content.replace(/(:|\s)(#800000)(;|})/g, "$1maroon$3");
        
            // border: none -> border:0
            pattern = /(border|border-top|border-right|border-bottom|border-left|outline|background):none(;|\})/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1.toLowerCase() + ":0" + f2;
            });
        
            // shorter opacity IE filter
            content = content.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
        
            // Find a fraction that is used for Opera's -o-device-pixel-ratio query
            // Add token to add the "\" back in later
            content = content.replace(/\(([\-A-Za-z]+):([0-9]+)\/([0-9]+)\)/g, "($1:$2___QUERY_FRACTION___$3)");
        
            // remove empty rules.
            content = content.replace(/[^\};\{\/]+\{\}/g, "");
        
            // Add "\" back to fix Opera -o-device-pixel-ratio query
            content = content.replace(/___QUERY_FRACTION___/g, "/");
        
            // some source control tools don't like it when files containing lines longer
            // than, say 8000 characters, are checked in. The linebreak option is used in
            // that case to split long lines after a specific column.
            if (options.maxLineLen > 0) {
                for (i = 0, len = content.length; i < len; i += 1) {
                    c = content.charAt(i);
                    line.push(c);
                    if (c === '}' && line.length > options.maxLineLen) {
                        lines.push(line.join(''));
                        line = [];
                    }
                }
                if (line.length) {
                    lines.push(line.join(''));
                }
        
                content = lines.join('\n');
            }
        
            // replace multiple semi-colons in a row by a single one
            // see SF bug #1980989
            content = content.replace(/;;+/g, ";");
        
            // trim the final string (for any leading or trailing white spaces)
            content = content.replace(/(^\s*|\s*$)/g, "");
        
            // restore preserved tokens
            for (i = preservedTokens.length - 1; i >= 0 ; i--) {
                content = content.replace("___PRESERVED_TOKEN_" + i + "___", preservedTokens[i], "g");
            }
        
            // restore preserved newlines
            content = content.replace(/___PRESERVED_NEWLINE___/g, '\n');
        
            // return
            return content;
        }
        
        // Uglify CSS files
        
        function processFiles(filenames, options) {
        
            var nFiles = filenames.length,
                uglies = [],
                index,
                filename,
                content;
        
            // process files
            for (index = 0; index < nFiles; index += 1) {
                filename = filenames[index];
                try {
                    content = fs.readFileSync(filename, 'utf8');
                    if (content.length) {
                        uglies.push(processString(content, options));
                    }
                } catch (e) {
                    util.error('unable to process "' + filename + '" with ' + e);
                    process.exit(1);
                }
            }
        
            // return concat'd results
            return uglies.join('');
        }
        
        module.exports = {
            defaultOptions: defaultOptions,
            processString: processString,
            processFiles: processFiles
        };
    • zip.js
      • deflate.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright 
         notice, this list of conditions and the following disclaimer in 
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        /*
         * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
         * JZlib is based on zlib-1.1.3, so all credit should go authors
         * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
         * and contributors of zlib.
         */
        
        (function(global) {
        	"use strict";
        
        	// Global
        
        	var MAX_BITS = 15;
        	var D_CODES = 30;
        	var BL_CODES = 19;
        
        	var LENGTH_CODES = 29;
        	var LITERALS = 256;
        	var L_CODES = (LITERALS + 1 + LENGTH_CODES);
        	var HEAP_SIZE = (2 * L_CODES + 1);
        
        	var END_BLOCK = 256;
        
        	// Bit length codes must not exceed MAX_BL_BITS bits
        	var MAX_BL_BITS = 7;
        
        	// repeat previous bit length 3-6 times (2 bits of repeat count)
        	var REP_3_6 = 16;
        
        	// repeat a zero length 3-10 times (3 bits of repeat count)
        	var REPZ_3_10 = 17;
        
        	// repeat a zero length 11-138 times (7 bits of repeat count)
        	var REPZ_11_138 = 18;
        
        	// The lengths of the bit length codes are sent in order of decreasing
        	// probability, to avoid transmitting the lengths for unused bit
        	// length codes.
        
        	var Buf_size = 8 * 2;
        
        	// JZlib version : "1.0.2"
        	var Z_DEFAULT_COMPRESSION = -1;
        
        	// compression strategy
        	var Z_FILTERED = 1;
        	var Z_HUFFMAN_ONLY = 2;
        	var Z_DEFAULT_STRATEGY = 0;
        
        	var Z_NO_FLUSH = 0;
        	var Z_PARTIAL_FLUSH = 1;
        	var Z_FULL_FLUSH = 3;
        	var Z_FINISH = 4;
        
        	var Z_OK = 0;
        	var Z_STREAM_END = 1;
        	var Z_NEED_DICT = 2;
        	var Z_STREAM_ERROR = -2;
        	var Z_DATA_ERROR = -3;
        	var Z_BUF_ERROR = -5;
        
        	// Tree
        
        	// see definition of array dist_code below
        	var _dist_code = [ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        			10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
        			12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
        			13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
        			14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
        			14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
        			15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19,
        			20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
        			24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
        			26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
        			27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
        			28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
        			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
        			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 ];
        
        	function Tree() {
        		var that = this;
        
        		// dyn_tree; // the dynamic tree
        		// max_code; // largest code with non zero frequency
        		// stat_desc; // the corresponding static tree
        
        		// Compute the optimal bit lengths for a tree and update the total bit
        		// length
        		// for the current block.
        		// IN assertion: the fields freq and dad are set, heap[heap_max] and
        		// above are the tree nodes sorted by increasing frequency.
        		// OUT assertions: the field len is set to the optimal bit length, the
        		// array bl_count contains the frequencies for each bit length.
        		// The length opt_len is updated; static_len is also updated if stree is
        		// not null.
        		function gen_bitlen(s) {
        			var tree = that.dyn_tree;
        			var stree = that.stat_desc.static_tree;
        			var extra = that.stat_desc.extra_bits;
        			var base = that.stat_desc.extra_base;
        			var max_length = that.stat_desc.max_length;
        			var h; // heap index
        			var n, m; // iterate over the tree elements
        			var bits; // bit length
        			var xbits; // extra bits
        			var f; // frequency
        			var overflow = 0; // number of elements with bit length too large
        
        			for (bits = 0; bits <= MAX_BITS; bits++)
        				s.bl_count[bits] = 0;
        
        			// In a first pass, compute the optimal bit lengths (which may
        			// overflow in the case of the bit length tree).
        			tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
        
        			for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
        				n = s.heap[h];
        				bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
        				if (bits > max_length) {
        					bits = max_length;
        					overflow++;
        				}
        				tree[n * 2 + 1] = bits;
        				// We overwrite tree[n*2+1] which is no longer needed
        
        				if (n > that.max_code)
        					continue; // not a leaf node
        
        				s.bl_count[bits]++;
        				xbits = 0;
        				if (n >= base)
        					xbits = extra[n - base];
        				f = tree[n * 2];
        				s.opt_len += f * (bits + xbits);
        				if (stree)
        					s.static_len += f * (stree[n * 2 + 1] + xbits);
        			}
        			if (overflow === 0)
        				return;
        
        			// This happens for example on obj2 and pic of the Calgary corpus
        			// Find the first bit length which could increase:
        			do {
        				bits = max_length - 1;
        				while (s.bl_count[bits] === 0)
        					bits--;
        				s.bl_count[bits]--; // move one leaf down the tree
        				s.bl_count[bits + 1] += 2; // move one overflow item as its brother
        				s.bl_count[max_length]--;
        				// The brother of the overflow item also moves one step up,
        				// but this does not affect bl_count[max_length]
        				overflow -= 2;
        			} while (overflow > 0);
        
        			for (bits = max_length; bits !== 0; bits--) {
        				n = s.bl_count[bits];
        				while (n !== 0) {
        					m = s.heap[--h];
        					if (m > that.max_code)
        						continue;
        					if (tree[m * 2 + 1] != bits) {
        						s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
        						tree[m * 2 + 1] = bits;
        					}
        					n--;
        				}
        			}
        		}
        
        		// Reverse the first len bits of a code, using straightforward code (a
        		// faster
        		// method would use a table)
        		// IN assertion: 1 <= len <= 15
        		function bi_reverse(code, // the value to invert
        		len // its bit length
        		) {
        			var res = 0;
        			do {
        				res |= code & 1;
        				code >>>= 1;
        				res <<= 1;
        			} while (--len > 0);
        			return res >>> 1;
        		}
        
        		// Generate the codes for a given tree and bit counts (which need not be
        		// optimal).
        		// IN assertion: the array bl_count contains the bit length statistics for
        		// the given tree and the field len is set for all tree elements.
        		// OUT assertion: the field code is set for all tree elements of non
        		// zero code length.
        		function gen_codes(tree, // the tree to decorate
        		max_code, // largest code with non zero frequency
        		bl_count // number of codes at each bit length
        		) {
        			var next_code = []; // next code value for each
        			// bit length
        			var code = 0; // running code value
        			var bits; // bit index
        			var n; // code index
        			var len;
        
        			// The distribution counts are first used to generate the code values
        			// without bit reversal.
        			for (bits = 1; bits <= MAX_BITS; bits++) {
        				next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
        			}
        
        			// Check that the bit counts in bl_count are consistent. The last code
        			// must be all ones.
        			// Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
        			// "inconsistent bit counts");
        			// Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
        
        			for (n = 0; n <= max_code; n++) {
        				len = tree[n * 2 + 1];
        				if (len === 0)
        					continue;
        				// Now reverse the bits
        				tree[n * 2] = bi_reverse(next_code[len]++, len);
        			}
        		}
        
        		// Construct one Huffman tree and assigns the code bit strings and lengths.
        		// Update the total bit length for the current block.
        		// IN assertion: the field freq is set for all tree elements.
        		// OUT assertions: the fields len and code are set to the optimal bit length
        		// and corresponding code. The length opt_len is updated; static_len is
        		// also updated if stree is not null. The field max_code is set.
        		that.build_tree = function(s) {
        			var tree = that.dyn_tree;
        			var stree = that.stat_desc.static_tree;
        			var elems = that.stat_desc.elems;
        			var n, m; // iterate over heap elements
        			var max_code = -1; // largest code with non zero frequency
        			var node; // new node being created
        
        			// Construct the initial heap, with least frequent element in
        			// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
        			// heap[0] is not used.
        			s.heap_len = 0;
        			s.heap_max = HEAP_SIZE;
        
        			for (n = 0; n < elems; n++) {
        				if (tree[n * 2] !== 0) {
        					s.heap[++s.heap_len] = max_code = n;
        					s.depth[n] = 0;
        				} else {
        					tree[n * 2 + 1] = 0;
        				}
        			}
        
        			// The pkzip format requires that at least one distance code exists,
        			// and that at least one bit should be sent even if there is only one
        			// possible code. So to avoid special checks later on we force at least
        			// two codes of non zero frequency.
        			while (s.heap_len < 2) {
        				node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
        				tree[node * 2] = 1;
        				s.depth[node] = 0;
        				s.opt_len--;
        				if (stree)
        					s.static_len -= stree[node * 2 + 1];
        				// node is 0 or 1 so it does not have extra bits
        			}
        			that.max_code = max_code;
        
        			// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
        			// establish sub-heaps of increasing lengths:
        
        			for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
        				s.pqdownheap(tree, n);
        
        			// Construct the Huffman tree by repeatedly combining the least two
        			// frequent nodes.
        
        			node = elems; // next internal node of the tree
        			do {
        				// n = node of least frequency
        				n = s.heap[1];
        				s.heap[1] = s.heap[s.heap_len--];
        				s.pqdownheap(tree, 1);
        				m = s.heap[1]; // m = node of next least frequency
        
        				s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
        				s.heap[--s.heap_max] = m;
        
        				// Create a new node father of n and m
        				tree[node * 2] = (tree[n * 2] + tree[m * 2]);
        				s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
        				tree[n * 2 + 1] = tree[m * 2 + 1] = node;
        
        				// and insert the new node in the heap
        				s.heap[1] = node++;
        				s.pqdownheap(tree, 1);
        			} while (s.heap_len >= 2);
        
        			s.heap[--s.heap_max] = s.heap[1];
        
        			// At this point, the fields freq and dad are set. We can now
        			// generate the bit lengths.
        
        			gen_bitlen(s);
        
        			// The field len is now set, we can generate the bit codes
        			gen_codes(tree, that.max_code, s.bl_count);
        		};
        
        	}
        
        	Tree._length_code = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
        			16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
        			20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
        			22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
        			24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
        			25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
        			26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 ];
        
        	Tree.base_length = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 ];
        
        	Tree.base_dist = [ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,
        			24576 ];
        
        	// Mapping from a distance to a distance code. dist is the distance - 1 and
        	// must not have side effects. _dist_code[256] and _dist_code[257] are never
        	// used.
        	Tree.d_code = function(dist) {
        		return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
        	};
        
        	// extra bits for each length code
        	Tree.extra_lbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 ];
        
        	// extra bits for each distance code
        	Tree.extra_dbits = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];
        
        	// extra bits for each bit length code
        	Tree.extra_blbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 ];
        
        	Tree.bl_order = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
        
        	// StaticTree
        
        	function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
        		var that = this;
        		that.static_tree = static_tree;
        		that.extra_bits = extra_bits;
        		that.extra_base = extra_base;
        		that.elems = elems;
        		that.max_length = max_length;
        	}
        
        	StaticTree.static_ltree = [ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8,
        			130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42,
        			8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8,
        			22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
        			222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113,
        			8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8,
        			69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8,
        			173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,
        			51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9,
        			427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379,
        			9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23,
        			9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9,
        			399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9,
        			223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7,
        			40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8,
        			99, 8, 227, 8 ];
        
        	StaticTree.static_dtree = [ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5,
        			25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 ];
        
        	StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
        
        	StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
        
        	StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
        
        	// Deflate
        
        	var MAX_MEM_LEVEL = 9;
        	var DEF_MEM_LEVEL = 8;
        
        	function Config(good_length, max_lazy, nice_length, max_chain, func) {
        		var that = this;
        		that.good_length = good_length;
        		that.max_lazy = max_lazy;
        		that.nice_length = nice_length;
        		that.max_chain = max_chain;
        		that.func = func;
        	}
        
        	var STORED = 0;
        	var FAST = 1;
        	var SLOW = 2;
        	var config_table = [ new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST),
        			new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW),
        			new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW) ];
        
        	var z_errmsg = [ "need dictionary", // Z_NEED_DICT
        	// 2
        	"stream end", // Z_STREAM_END 1
        	"", // Z_OK 0
        	"", // Z_ERRNO (-1)
        	"stream error", // Z_STREAM_ERROR (-2)
        	"data error", // Z_DATA_ERROR (-3)
        	"", // Z_MEM_ERROR (-4)
        	"buffer error", // Z_BUF_ERROR (-5)
        	"",// Z_VERSION_ERROR (-6)
        	"" ];
        
        	// block not completed, need more input or more output
        	var NeedMore = 0;
        
        	// block flush performed
        	var BlockDone = 1;
        
        	// finish started, need only more output at next deflate
        	var FinishStarted = 2;
        
        	// finish done, accept no more input or output
        	var FinishDone = 3;
        
        	// preset dictionary flag in zlib header
        	var PRESET_DICT = 0x20;
        
        	var INIT_STATE = 42;
        	var BUSY_STATE = 113;
        	var FINISH_STATE = 666;
        
        	// The deflate compression method
        	var Z_DEFLATED = 8;
        
        	var STORED_BLOCK = 0;
        	var STATIC_TREES = 1;
        	var DYN_TREES = 2;
        
        	var MIN_MATCH = 3;
        	var MAX_MATCH = 258;
        	var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
        
        	function smaller(tree, n, m, depth) {
        		var tn2 = tree[n * 2];
        		var tm2 = tree[m * 2];
        		return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
        	}
        
        	function Deflate() {
        
        		var that = this;
        		var strm; // pointer back to this zlib stream
        		var status; // as the name implies
        		// pending_buf; // output still pending
        		var pending_buf_size; // size of pending_buf
        		// pending_out; // next pending byte to output to the stream
        		// pending; // nb of bytes in the pending buffer
        		var method; // STORED (for zip only) or DEFLATED
        		var last_flush; // value of flush param for previous deflate call
        
        		var w_size; // LZ77 window size (32K by default)
        		var w_bits; // log2(w_size) (8..16)
        		var w_mask; // w_size - 1
        
        		var window;
        		// Sliding window. Input bytes are read into the second half of the window,
        		// and move to the first half later to keep a dictionary of at least wSize
        		// bytes. With this organization, matches are limited to a distance of
        		// wSize-MAX_MATCH bytes, but this ensures that IO is always
        		// performed with a length multiple of the block size. Also, it limits
        		// the window size to 64K, which is quite useful on MSDOS.
        		// To do: use the user input buffer as sliding window.
        
        		var window_size;
        		// Actual size of window: 2*wSize, except when the user input buffer
        		// is directly used as sliding window.
        
        		var prev;
        		// Link to older string with same hash index. To limit the size of this
        		// array to 64K, this link is maintained only for the last 32K strings.
        		// An index in this array is thus a window index modulo 32K.
        
        		var head; // Heads of the hash chains or NIL.
        
        		var ins_h; // hash index of string to be inserted
        		var hash_size; // number of elements in hash table
        		var hash_bits; // log2(hash_size)
        		var hash_mask; // hash_size-1
        
        		// Number of bits by which ins_h must be shifted at each input
        		// step. It must be such that after MIN_MATCH steps, the oldest
        		// byte no longer takes part in the hash key, that is:
        		// hash_shift * MIN_MATCH >= hash_bits
        		var hash_shift;
        
        		// Window position at the beginning of the current output block. Gets
        		// negative when the window is moved backwards.
        
        		var block_start;
        
        		var match_length; // length of best match
        		var prev_match; // previous match
        		var match_available; // set if previous match exists
        		var strstart; // start of string to insert
        		var match_start; // start of matching string
        		var lookahead; // number of valid bytes ahead in window
        
        		// Length of the best match at previous step. Matches not greater than this
        		// are discarded. This is used in the lazy match evaluation.
        		var prev_length;
        
        		// To speed up deflation, hash chains are never searched beyond this
        		// length. A higher limit improves compression ratio but degrades the speed.
        		var max_chain_length;
        
        		// Attempt to find a better match only when the current match is strictly
        		// smaller than this value. This mechanism is used only for compression
        		// levels >= 4.
        		var max_lazy_match;
        
        		// Insert new strings in the hash table only if the match length is not
        		// greater than this length. This saves time but degrades compression.
        		// max_insert_length is used only for compression levels <= 3.
        
        		var level; // compression level (1..9)
        		var strategy; // favor or force Huffman coding
        
        		// Use a faster search when the previous match is longer than this
        		var good_match;
        
        		// Stop searching when current match exceeds this
        		var nice_match;
        
        		var dyn_ltree; // literal and length tree
        		var dyn_dtree; // distance tree
        		var bl_tree; // Huffman tree for bit lengths
        
        		var l_desc = new Tree(); // desc for literal tree
        		var d_desc = new Tree(); // desc for distance tree
        		var bl_desc = new Tree(); // desc for bit length tree
        
        		// that.heap_len; // number of elements in the heap
        		// that.heap_max; // element of largest frequency
        		// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
        		// The same heap array is used to build all trees.
        
        		// Depth of each subtree used as tie breaker for trees of equal frequency
        		that.depth = [];
        
        		var l_buf; // index for literals or lengths */
        
        		// Size of match buffer for literals/lengths. There are 4 reasons for
        		// limiting lit_bufsize to 64K:
        		// - frequencies can be kept in 16 bit counters
        		// - if compression is not successful for the first block, all input
        		// data is still in the window so we can still emit a stored block even
        		// when input comes from standard input. (This can also be done for
        		// all blocks if lit_bufsize is not greater than 32K.)
        		// - if compression is not successful for a file smaller than 64K, we can
        		// even emit a stored file instead of a stored block (saving 5 bytes).
        		// This is applicable only for zip (not gzip or zlib).
        		// - creating new Huffman trees less frequently may not provide fast
        		// adaptation to changes in the input data statistics. (Take for
        		// example a binary file with poorly compressible code followed by
        		// a highly compressible string table.) Smaller buffer sizes give
        		// fast adaptation but have of course the overhead of transmitting
        		// trees more frequently.
        		// - I can't count above 4
        		var lit_bufsize;
        
        		var last_lit; // running index in l_buf
        
        		// Buffer for distances. To simplify the code, d_buf and l_buf have
        		// the same number of elements. To use different lengths, an extra flag
        		// array would be necessary.
        
        		var d_buf; // index of pendig_buf
        
        		// that.opt_len; // bit length of current block with optimal trees
        		// that.static_len; // bit length of current block with static trees
        		var matches; // number of string matches in current block
        		var last_eob_len; // bit length of EOB code for last block
        
        		// Output buffer. bits are inserted starting at the bottom (least
        		// significant bits).
        		var bi_buf;
        
        		// Number of valid bits in bi_buf. All bits above the last valid bit
        		// are always zero.
        		var bi_valid;
        
        		// number of codes at each bit length for an optimal tree
        		that.bl_count = [];
        
        		// heap used to build the Huffman trees
        		that.heap = [];
        
        		dyn_ltree = [];
        		dyn_dtree = [];
        		bl_tree = [];
        
        		function lm_init() {
        			var i;
        			window_size = 2 * w_size;
        
        			head[hash_size - 1] = 0;
        			for (i = 0; i < hash_size - 1; i++) {
        				head[i] = 0;
        			}
        
        			// Set the default configuration parameters:
        			max_lazy_match = config_table[level].max_lazy;
        			good_match = config_table[level].good_length;
        			nice_match = config_table[level].nice_length;
        			max_chain_length = config_table[level].max_chain;
        
        			strstart = 0;
        			block_start = 0;
        			lookahead = 0;
        			match_length = prev_length = MIN_MATCH - 1;
        			match_available = 0;
        			ins_h = 0;
        		}
        
        		function init_block() {
        			var i;
        			// Initialize the trees.
        			for (i = 0; i < L_CODES; i++)
        				dyn_ltree[i * 2] = 0;
        			for (i = 0; i < D_CODES; i++)
        				dyn_dtree[i * 2] = 0;
        			for (i = 0; i < BL_CODES; i++)
        				bl_tree[i * 2] = 0;
        
        			dyn_ltree[END_BLOCK * 2] = 1;
        			that.opt_len = that.static_len = 0;
        			last_lit = matches = 0;
        		}
        
        		// Initialize the tree data structures for a new zlib stream.
        		function tr_init() {
        
        			l_desc.dyn_tree = dyn_ltree;
        			l_desc.stat_desc = StaticTree.static_l_desc;
        
        			d_desc.dyn_tree = dyn_dtree;
        			d_desc.stat_desc = StaticTree.static_d_desc;
        
        			bl_desc.dyn_tree = bl_tree;
        			bl_desc.stat_desc = StaticTree.static_bl_desc;
        
        			bi_buf = 0;
        			bi_valid = 0;
        			last_eob_len = 8; // enough lookahead for inflate
        
        			// Initialize the first block of the first file:
        			init_block();
        		}
        
        		// Restore the heap property by moving down the tree starting at node k,
        		// exchanging a node with the smallest of its two sons if necessary,
        		// stopping
        		// when the heap property is re-established (each father smaller than its
        		// two sons).
        		that.pqdownheap = function(tree, // the tree to restore
        		k // node to move down
        		) {
        			var heap = that.heap;
        			var v = heap[k];
        			var j = k << 1; // left son of k
        			while (j <= that.heap_len) {
        				// Set j to the smallest of the two sons:
        				if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
        					j++;
        				}
        				// Exit if v is smaller than both sons
        				if (smaller(tree, v, heap[j], that.depth))
        					break;
        
        				// Exchange v with the smallest son
        				heap[k] = heap[j];
        				k = j;
        				// And continue down the tree, setting j to the left son of k
        				j <<= 1;
        			}
        			heap[k] = v;
        		};
        
        		// Scan a literal or distance tree to determine the frequencies of the codes
        		// in the bit length tree.
        		function scan_tree(tree,// the tree to be scanned
        		max_code // and its largest code of non zero frequency
        		) {
        			var n; // iterates over all tree elements
        			var prevlen = -1; // last emitted length
        			var curlen; // length of current code
        			var nextlen = tree[0 * 2 + 1]; // length of next code
        			var count = 0; // repeat count of the current code
        			var max_count = 7; // max repeat count
        			var min_count = 4; // min repeat count
        
        			if (nextlen === 0) {
        				max_count = 138;
        				min_count = 3;
        			}
        			tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
        
        			for (n = 0; n <= max_code; n++) {
        				curlen = nextlen;
        				nextlen = tree[(n + 1) * 2 + 1];
        				if (++count < max_count && curlen == nextlen) {
        					continue;
        				} else if (count < min_count) {
        					bl_tree[curlen * 2] += count;
        				} else if (curlen !== 0) {
        					if (curlen != prevlen)
        						bl_tree[curlen * 2]++;
        					bl_tree[REP_3_6 * 2]++;
        				} else if (count <= 10) {
        					bl_tree[REPZ_3_10 * 2]++;
        				} else {
        					bl_tree[REPZ_11_138 * 2]++;
        				}
        				count = 0;
        				prevlen = curlen;
        				if (nextlen === 0) {
        					max_count = 138;
        					min_count = 3;
        				} else if (curlen == nextlen) {
        					max_count = 6;
        					min_count = 3;
        				} else {
        					max_count = 7;
        					min_count = 4;
        				}
        			}
        		}
        
        		// Construct the Huffman tree for the bit lengths and return the index in
        		// bl_order of the last bit length code to send.
        		function build_bl_tree() {
        			var max_blindex; // index of last bit length code of non zero freq
        
        			// Determine the bit length frequencies for literal and distance trees
        			scan_tree(dyn_ltree, l_desc.max_code);
        			scan_tree(dyn_dtree, d_desc.max_code);
        
        			// Build the bit length tree:
        			bl_desc.build_tree(that);
        			// opt_len now includes the length of the tree representations, except
        			// the lengths of the bit lengths codes and the 5+5+4 bits for the
        			// counts.
        
        			// Determine the number of bit length codes to send. The pkzip format
        			// requires that at least 4 bit length codes be sent. (appnote.txt says
        			// 3 but the actual value used is 4.)
        			for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
        				if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
        					break;
        			}
        			// Update opt_len to include the bit length tree and counts
        			that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
        
        			return max_blindex;
        		}
        
        		// Output a byte on the stream.
        		// IN assertion: there is enough room in pending_buf.
        		function put_byte(p) {
        			that.pending_buf[that.pending++] = p;
        		}
        
        		function put_short(w) {
        			put_byte(w & 0xff);
        			put_byte((w >>> 8) & 0xff);
        		}
        
        		function putShortMSB(b) {
        			put_byte((b >> 8) & 0xff);
        			put_byte((b & 0xff) & 0xff);
        		}
        
        		function send_bits(value, length) {
        			var val, len = length;
        			if (bi_valid > Buf_size - len) {
        				val = value;
        				// bi_buf |= (val << bi_valid);
        				bi_buf |= ((val << bi_valid) & 0xffff);
        				put_short(bi_buf);
        				bi_buf = val >>> (Buf_size - bi_valid);
        				bi_valid += len - Buf_size;
        			} else {
        				// bi_buf |= (value) << bi_valid;
        				bi_buf |= (((value) << bi_valid) & 0xffff);
        				bi_valid += len;
        			}
        		}
        
        		function send_code(c, tree) {
        			var c2 = c * 2;
        			send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
        		}
        
        		// Send a literal or distance tree in compressed form, using the codes in
        		// bl_tree.
        		function send_tree(tree,// the tree to be sent
        		max_code // and its largest code of non zero frequency
        		) {
        			var n; // iterates over all tree elements
        			var prevlen = -1; // last emitted length
        			var curlen; // length of current code
        			var nextlen = tree[0 * 2 + 1]; // length of next code
        			var count = 0; // repeat count of the current code
        			var max_count = 7; // max repeat count
        			var min_count = 4; // min repeat count
        
        			if (nextlen === 0) {
        				max_count = 138;
        				min_count = 3;
        			}
        
        			for (n = 0; n <= max_code; n++) {
        				curlen = nextlen;
        				nextlen = tree[(n + 1) * 2 + 1];
        				if (++count < max_count && curlen == nextlen) {
        					continue;
        				} else if (count < min_count) {
        					do {
        						send_code(curlen, bl_tree);
        					} while (--count !== 0);
        				} else if (curlen !== 0) {
        					if (curlen != prevlen) {
        						send_code(curlen, bl_tree);
        						count--;
        					}
        					send_code(REP_3_6, bl_tree);
        					send_bits(count - 3, 2);
        				} else if (count <= 10) {
        					send_code(REPZ_3_10, bl_tree);
        					send_bits(count - 3, 3);
        				} else {
        					send_code(REPZ_11_138, bl_tree);
        					send_bits(count - 11, 7);
        				}
        				count = 0;
        				prevlen = curlen;
        				if (nextlen === 0) {
        					max_count = 138;
        					min_count = 3;
        				} else if (curlen == nextlen) {
        					max_count = 6;
        					min_count = 3;
        				} else {
        					max_count = 7;
        					min_count = 4;
        				}
        			}
        		}
        
        		// Send the header for a block using dynamic Huffman trees: the counts, the
        		// lengths of the bit length codes, the literal tree and the distance tree.
        		// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
        		function send_all_trees(lcodes, dcodes, blcodes) {
        			var rank; // index in bl_order
        
        			send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
        			send_bits(dcodes - 1, 5);
        			send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
        			for (rank = 0; rank < blcodes; rank++) {
        				send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
        			}
        			send_tree(dyn_ltree, lcodes - 1); // literal tree
        			send_tree(dyn_dtree, dcodes - 1); // distance tree
        		}
        
        		// Flush the bit buffer, keeping at most 7 bits in it.
        		function bi_flush() {
        			if (bi_valid == 16) {
        				put_short(bi_buf);
        				bi_buf = 0;
        				bi_valid = 0;
        			} else if (bi_valid >= 8) {
        				put_byte(bi_buf & 0xff);
        				bi_buf >>>= 8;
        				bi_valid -= 8;
        			}
        		}
        
        		// Send one empty static block to give enough lookahead for inflate.
        		// This takes 10 bits, of which 7 may remain in the bit buffer.
        		// The current inflate code requires 9 bits of lookahead. If the
        		// last two codes for the previous block (real code plus EOB) were coded
        		// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
        		// the last real code. In this case we send two empty static blocks instead
        		// of one. (There are no problems if the previous block is stored or fixed.)
        		// To simplify the code, we assume the worst case of last real code encoded
        		// on one bit only.
        		function _tr_align() {
        			send_bits(STATIC_TREES << 1, 3);
        			send_code(END_BLOCK, StaticTree.static_ltree);
        
        			bi_flush();
        
        			// Of the 10 bits for the empty block, we have already sent
        			// (10 - bi_valid) bits. The lookahead for the last real code (before
        			// the EOB of the previous block) was thus at least one plus the length
        			// of the EOB plus what we have just sent of the empty static block.
        			if (1 + last_eob_len + 10 - bi_valid < 9) {
        				send_bits(STATIC_TREES << 1, 3);
        				send_code(END_BLOCK, StaticTree.static_ltree);
        				bi_flush();
        			}
        			last_eob_len = 7;
        		}
        
        		// Save the match info and tally the frequency counts. Return true if
        		// the current block must be flushed.
        		function _tr_tally(dist, // distance of matched string
        		lc // match length-MIN_MATCH or unmatched char (if dist==0)
        		) {
        			var out_length, in_length, dcode;
        			that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
        			that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
        
        			that.pending_buf[l_buf + last_lit] = lc & 0xff;
        			last_lit++;
        
        			if (dist === 0) {
        				// lc is the unmatched char
        				dyn_ltree[lc * 2]++;
        			} else {
        				matches++;
        				// Here, lc is the match length - MIN_MATCH
        				dist--; // dist = match distance - 1
        				dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
        				dyn_dtree[Tree.d_code(dist) * 2]++;
        			}
        
        			if ((last_lit & 0x1fff) === 0 && level > 2) {
        				// Compute an upper bound for the compressed length
        				out_length = last_lit * 8;
        				in_length = strstart - block_start;
        				for (dcode = 0; dcode < D_CODES; dcode++) {
        					out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
        				}
        				out_length >>>= 3;
        				if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
        					return true;
        			}
        
        			return (last_lit == lit_bufsize - 1);
        			// We avoid equality with lit_bufsize because of wraparound at 64K
        			// on 16 bit machines and because stored blocks are restricted to
        			// 64K-1 bytes.
        		}
        
        		// Send the block data compressed using the given Huffman trees
        		function compress_block(ltree, dtree) {
        			var dist; // distance of matched string
        			var lc; // match length or unmatched char (if dist === 0)
        			var lx = 0; // running index in l_buf
        			var code; // the code to send
        			var extra; // number of extra bits to send
        
        			if (last_lit !== 0) {
        				do {
        					dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
        					lc = (that.pending_buf[l_buf + lx]) & 0xff;
        					lx++;
        
        					if (dist === 0) {
        						send_code(lc, ltree); // send a literal byte
        					} else {
        						// Here, lc is the match length - MIN_MATCH
        						code = Tree._length_code[lc];
        
        						send_code(code + LITERALS + 1, ltree); // send the length
        						// code
        						extra = Tree.extra_lbits[code];
        						if (extra !== 0) {
        							lc -= Tree.base_length[code];
        							send_bits(lc, extra); // send the extra length bits
        						}
        						dist--; // dist is now the match distance - 1
        						code = Tree.d_code(dist);
        
        						send_code(code, dtree); // send the distance code
        						extra = Tree.extra_dbits[code];
        						if (extra !== 0) {
        							dist -= Tree.base_dist[code];
        							send_bits(dist, extra); // send the extra distance bits
        						}
        					} // literal or match pair ?
        
        					// Check that the overlay between pending_buf and d_buf+l_buf is
        					// ok:
        				} while (lx < last_lit);
        			}
        
        			send_code(END_BLOCK, ltree);
        			last_eob_len = ltree[END_BLOCK * 2 + 1];
        		}
        
        		// Flush the bit buffer and align the output on a byte boundary
        		function bi_windup() {
        			if (bi_valid > 8) {
        				put_short(bi_buf);
        			} else if (bi_valid > 0) {
        				put_byte(bi_buf & 0xff);
        			}
        			bi_buf = 0;
        			bi_valid = 0;
        		}
        
        		// Copy a stored block, storing first the length and its
        		// one's complement if requested.
        		function copy_block(buf, // the input data
        		len, // its length
        		header // true if block header must be written
        		) {
        			bi_windup(); // align on byte boundary
        			last_eob_len = 8; // enough lookahead for inflate
        
        			if (header) {
        				put_short(len);
        				put_short(~len);
        			}
        
        			that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
        			that.pending += len;
        		}
        
        		// Send a stored block
        		function _tr_stored_block(buf, // input block
        		stored_len, // length of input block
        		eof // true if this is the last block for a file
        		) {
        			send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
        			copy_block(buf, stored_len, true); // with header
        		}
        
        		// Determine the best encoding for the current block: dynamic trees, static
        		// trees or store, and output the encoded block to the zip file.
        		function _tr_flush_block(buf, // input block, or NULL if too old
        		stored_len, // length of input block
        		eof // true if this is the last block for a file
        		) {
        			var opt_lenb, static_lenb;// opt_len and static_len in bytes
        			var max_blindex = 0; // index of last bit length code of non zero freq
        
        			// Build the Huffman trees unless a stored block is forced
        			if (level > 0) {
        				// Construct the literal and distance trees
        				l_desc.build_tree(that);
        
        				d_desc.build_tree(that);
        
        				// At this point, opt_len and static_len are the total bit lengths
        				// of
        				// the compressed block data, excluding the tree representations.
        
        				// Build the bit length tree for the above two trees, and get the
        				// index
        				// in bl_order of the last bit length code to send.
        				max_blindex = build_bl_tree();
        
        				// Determine the best encoding. Compute first the block length in
        				// bytes
        				opt_lenb = (that.opt_len + 3 + 7) >>> 3;
        				static_lenb = (that.static_len + 3 + 7) >>> 3;
        
        				if (static_lenb <= opt_lenb)
        					opt_lenb = static_lenb;
        			} else {
        				opt_lenb = static_lenb = stored_len + 5; // force a stored block
        			}
        
        			if ((stored_len + 4 <= opt_lenb) && buf != -1) {
        				// 4: two words for the lengths
        				// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
        				// Otherwise we can't have processed more than WSIZE input bytes
        				// since
        				// the last block flush, because compression would have been
        				// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
        				// transform a block into a stored block.
        				_tr_stored_block(buf, stored_len, eof);
        			} else if (static_lenb == opt_lenb) {
        				send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
        				compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
        			} else {
        				send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
        				send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
        				compress_block(dyn_ltree, dyn_dtree);
        			}
        
        			// The above check is made mod 2^32, for files larger than 512 MB
        			// and uLong implemented on 32 bits.
        
        			init_block();
        
        			if (eof) {
        				bi_windup();
        			}
        		}
        
        		function flush_block_only(eof) {
        			_tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
        			block_start = strstart;
        			strm.flush_pending();
        		}
        
        		// Fill the window when the lookahead becomes insufficient.
        		// Updates strstart and lookahead.
        		//
        		// IN assertion: lookahead < MIN_LOOKAHEAD
        		// OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
        		// At least one byte has been read, or avail_in === 0; reads are
        		// performed for at least two bytes (required for the zip translate_eol
        		// option -- not supported here).
        		function fill_window() {
        			var n, m;
        			var p;
        			var more; // Amount of free space at the end of the window.
        
        			do {
        				more = (window_size - lookahead - strstart);
        
        				// Deal with !@#$% 64K limit:
        				if (more === 0 && strstart === 0 && lookahead === 0) {
        					more = w_size;
        				} else if (more == -1) {
        					// Very unlikely, but possible on 16 bit machine if strstart ==
        					// 0
        					// and lookahead == 1 (input done one byte at time)
        					more--;
        
        					// If the window is almost full and there is insufficient
        					// lookahead,
        					// move the upper half to the lower one to make room in the
        					// upper half.
        				} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
        					window.set(window.subarray(w_size, w_size + w_size), 0);
        
        					match_start -= w_size;
        					strstart -= w_size; // we now have strstart >= MAX_DIST
        					block_start -= w_size;
        
        					// Slide the hash table (could be avoided with 32 bit values
        					// at the expense of memory usage). We slide even when level ==
        					// 0
        					// to keep the hash table consistent if we switch back to level
        					// > 0
        					// later. (Using level 0 permanently is not an optimal usage of
        					// zlib, so we don't care about this pathological case.)
        
        					n = hash_size;
        					p = n;
        					do {
        						m = (head[--p] & 0xffff);
        						head[p] = (m >= w_size ? m - w_size : 0);
        					} while (--n !== 0);
        
        					n = w_size;
        					p = n;
        					do {
        						m = (prev[--p] & 0xffff);
        						prev[p] = (m >= w_size ? m - w_size : 0);
        						// If n is not on any hash chain, prev[n] is garbage but
        						// its value will never be used.
        					} while (--n !== 0);
        					more += w_size;
        				}
        
        				if (strm.avail_in === 0)
        					return;
        
        				// If there was no sliding:
        				// strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
        				// more == window_size - lookahead - strstart
        				// => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
        				// => more >= window_size - 2*WSIZE + 2
        				// In the BIG_MEM or MMAP case (not yet supported),
        				// window_size == input_size + MIN_LOOKAHEAD &&
        				// strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
        				// Otherwise, window_size == 2*WSIZE so more >= 2.
        				// If there was sliding, more >= WSIZE. So in all cases, more >= 2.
        
        				n = strm.read_buf(window, strstart + lookahead, more);
        				lookahead += n;
        
        				// Initialize the hash value now that we have some input:
        				if (lookahead >= MIN_MATCH) {
        					ins_h = window[strstart] & 0xff;
        					ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
        				}
        				// If the whole input has less than MIN_MATCH bytes, ins_h is
        				// garbage,
        				// but this is not important since only literal bytes will be
        				// emitted.
        			} while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
        		}
        
        		// Copy without compression as much as possible from the input stream,
        		// return
        		// the current block state.
        		// This function does not insert new strings in the dictionary since
        		// uncompressible data is probably not useful. This function is used
        		// only for the level=0 compression option.
        		// NOTE: this function should be optimized to avoid extra copying from
        		// window to pending_buf.
        		function deflate_stored(flush) {
        			// Stored blocks are limited to 0xffff bytes, pending_buf is limited
        			// to pending_buf_size, and each stored block has a 5 byte header:
        
        			var max_block_size = 0xffff;
        			var max_start;
        
        			if (max_block_size > pending_buf_size - 5) {
        				max_block_size = pending_buf_size - 5;
        			}
        
        			// Copy as much as possible from input to output:
        			while (true) {
        				// Fill the window as much as possible:
        				if (lookahead <= 1) {
        					fill_window();
        					if (lookahead === 0 && flush == Z_NO_FLUSH)
        						return NeedMore;
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				strstart += lookahead;
        				lookahead = 0;
        
        				// Emit a stored block if pending_buf will be full:
        				max_start = block_start + max_block_size;
        				if (strstart === 0 || strstart >= max_start) {
        					// strstart === 0 is possible when wraparound on 16-bit machine
        					lookahead = (strstart - max_start);
        					strstart = max_start;
        
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        
        				}
        
        				// Flush if we may have to slide, otherwise block_start may become
        				// negative and the data will be gone:
        				if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        				}
        			}
        
        			flush_block_only(flush == Z_FINISH);
        			if (strm.avail_out === 0)
        				return (flush == Z_FINISH) ? FinishStarted : NeedMore;
        
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		function longest_match(cur_match) {
        			var chain_length = max_chain_length; // max hash chain length
        			var scan = strstart; // current string
        			var match; // matched string
        			var len; // length of current match
        			var best_len = prev_length; // best match length so far
        			var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
        			var _nice_match = nice_match;
        
        			// Stop when cur_match becomes <= limit. To simplify the code,
        			// we prevent matches with the string of window index 0.
        
        			var wmask = w_mask;
        
        			var strend = strstart + MAX_MATCH;
        			var scan_end1 = window[scan + best_len - 1];
        			var scan_end = window[scan + best_len];
        
        			// The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
        			// 16.
        			// It is easy to get rid of this optimization if necessary.
        
        			// Do not waste too much time if we already have a good match:
        			if (prev_length >= good_match) {
        				chain_length >>= 2;
        			}
        
        			// Do not look for matches beyond the end of the input. This is
        			// necessary
        			// to make deflate deterministic.
        			if (_nice_match > lookahead)
        				_nice_match = lookahead;
        
        			do {
        				match = cur_match;
        
        				// Skip to next match if the match length cannot increase
        				// or if the match length is less than 2:
        				if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
        						|| window[++match] != window[scan + 1])
        					continue;
        
        				// The check at best_len-1 can be removed because it will be made
        				// again later. (This heuristic is not always a win.)
        				// It is not necessary to compare scan[2] and match[2] since they
        				// are always equal when the other bytes match, given that
        				// the hash keys are equal and that HASH_BITS >= 8.
        				scan += 2;
        				match++;
        
        				// We check for insufficient lookahead only every 8th comparison;
        				// the 256th check will be made at strstart+258.
        				do {
        				} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
        						&& window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
        						&& window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
        
        				len = MAX_MATCH - (strend - scan);
        				scan = strend - MAX_MATCH;
        
        				if (len > best_len) {
        					match_start = cur_match;
        					best_len = len;
        					if (len >= _nice_match)
        						break;
        					scan_end1 = window[scan + best_len - 1];
        					scan_end = window[scan + best_len];
        				}
        
        			} while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);
        
        			if (best_len <= lookahead)
        				return best_len;
        			return lookahead;
        		}
        
        		// Compress as much as possible from the input stream, return the current
        		// block state.
        		// This function does not perform lazy evaluation of matches and inserts
        		// new strings in the dictionary only for unmatched strings or for short
        		// matches. It is used only for the fast compression options.
        		function deflate_fast(flush) {
        			// short hash_head = 0; // head of the hash chain
        			var hash_head = 0; // head of the hash chain
        			var bflush; // set if current block must be flushed
        
        			while (true) {
        				// Make sure that we always have enough lookahead, except
        				// at the end of the input file. We need MAX_MATCH bytes
        				// for the next match, plus MIN_MATCH bytes to insert the
        				// string following the next match.
        				if (lookahead < MIN_LOOKAHEAD) {
        					fill_window();
        					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
        						return NeedMore;
        					}
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				// Insert the string window[strstart .. strstart+2] in the
        				// dictionary, and set hash_head to the head of the hash chain:
        				if (lookahead >= MIN_MATCH) {
        					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        
        					// prev[strstart&w_mask]=hash_head=head[ins_h];
        					hash_head = (head[ins_h] & 0xffff);
        					prev[strstart & w_mask] = head[ins_h];
        					head[ins_h] = strstart;
        				}
        
        				// Find the longest match, discarding those <= prev_length.
        				// At this point we have always match_length < MIN_MATCH
        
        				if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
        					// To simplify the code, we prevent matches with the string
        					// of window index 0 (in particular we have to avoid a match
        					// of the string with itself at the start of the input file).
        					if (strategy != Z_HUFFMAN_ONLY) {
        						match_length = longest_match(hash_head);
        					}
        					// longest_match() sets match_start
        				}
        				if (match_length >= MIN_MATCH) {
        					// check_match(strstart, match_start, match_length);
        
        					bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
        
        					lookahead -= match_length;
        
        					// Insert new strings in the hash table only if the match length
        					// is not too large. This saves time but degrades compression.
        					if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
        						match_length--; // string at strstart already in hash table
        						do {
        							strstart++;
        
        							ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        							// prev[strstart&w_mask]=hash_head=head[ins_h];
        							hash_head = (head[ins_h] & 0xffff);
        							prev[strstart & w_mask] = head[ins_h];
        							head[ins_h] = strstart;
        
        							// strstart never exceeds WSIZE-MAX_MATCH, so there are
        							// always MIN_MATCH bytes ahead.
        						} while (--match_length !== 0);
        						strstart++;
        					} else {
        						strstart += match_length;
        						match_length = 0;
        						ins_h = window[strstart] & 0xff;
        
        						ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
        						// If lookahead < MIN_MATCH, ins_h is garbage, but it does
        						// not
        						// matter since it will be recomputed at next deflate call.
        					}
        				} else {
        					// No match, output a literal byte
        
        					bflush = _tr_tally(0, window[strstart] & 0xff);
        					lookahead--;
        					strstart++;
        				}
        				if (bflush) {
        
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        				}
        			}
        
        			flush_block_only(flush == Z_FINISH);
        			if (strm.avail_out === 0) {
        				if (flush == Z_FINISH)
        					return FinishStarted;
        				else
        					return NeedMore;
        			}
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		// Same as above, but achieves better compression. We use a lazy
        		// evaluation for matches: a match is finally adopted only if there is
        		// no better match at the next window position.
        		function deflate_slow(flush) {
        			// short hash_head = 0; // head of hash chain
        			var hash_head = 0; // head of hash chain
        			var bflush; // set if current block must be flushed
        			var max_insert;
        
        			// Process the input block.
        			while (true) {
        				// Make sure that we always have enough lookahead, except
        				// at the end of the input file. We need MAX_MATCH bytes
        				// for the next match, plus MIN_MATCH bytes to insert the
        				// string following the next match.
        
        				if (lookahead < MIN_LOOKAHEAD) {
        					fill_window();
        					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
        						return NeedMore;
        					}
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				// Insert the string window[strstart .. strstart+2] in the
        				// dictionary, and set hash_head to the head of the hash chain:
        
        				if (lookahead >= MIN_MATCH) {
        					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        					// prev[strstart&w_mask]=hash_head=head[ins_h];
        					hash_head = (head[ins_h] & 0xffff);
        					prev[strstart & w_mask] = head[ins_h];
        					head[ins_h] = strstart;
        				}
        
        				// Find the longest match, discarding those <= prev_length.
        				prev_length = match_length;
        				prev_match = match_start;
        				match_length = MIN_MATCH - 1;
        
        				if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
        					// To simplify the code, we prevent matches with the string
        					// of window index 0 (in particular we have to avoid a match
        					// of the string with itself at the start of the input file).
        
        					if (strategy != Z_HUFFMAN_ONLY) {
        						match_length = longest_match(hash_head);
        					}
        					// longest_match() sets match_start
        
        					if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {
        
        						// If prev_match is also MIN_MATCH, match_start is garbage
        						// but we will ignore the current match anyway.
        						match_length = MIN_MATCH - 1;
        					}
        				}
        
        				// If there was a match at the previous step and the current
        				// match is not better, output the previous match:
        				if (prev_length >= MIN_MATCH && match_length <= prev_length) {
        					max_insert = strstart + lookahead - MIN_MATCH;
        					// Do not insert strings in hash table beyond this.
        
        					// check_match(strstart-1, prev_match, prev_length);
        
        					bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
        
        					// Insert in hash table all strings up to the end of the match.
        					// strstart-1 and strstart are already inserted. If there is not
        					// enough lookahead, the last two strings are not inserted in
        					// the hash table.
        					lookahead -= prev_length - 1;
        					prev_length -= 2;
        					do {
        						if (++strstart <= max_insert) {
        							ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        							// prev[strstart&w_mask]=hash_head=head[ins_h];
        							hash_head = (head[ins_h] & 0xffff);
        							prev[strstart & w_mask] = head[ins_h];
        							head[ins_h] = strstart;
        						}
        					} while (--prev_length !== 0);
        					match_available = 0;
        					match_length = MIN_MATCH - 1;
        					strstart++;
        
        					if (bflush) {
        						flush_block_only(false);
        						if (strm.avail_out === 0)
        							return NeedMore;
        					}
        				} else if (match_available !== 0) {
        
        					// If there was no match at the previous position, output a
        					// single literal. If there was a match but the current match
        					// is longer, truncate the previous match to a single literal.
        
        					bflush = _tr_tally(0, window[strstart - 1] & 0xff);
        
        					if (bflush) {
        						flush_block_only(false);
        					}
        					strstart++;
        					lookahead--;
        					if (strm.avail_out === 0)
        						return NeedMore;
        				} else {
        					// There is no previous match to compare with, wait for
        					// the next step to decide.
        
        					match_available = 1;
        					strstart++;
        					lookahead--;
        				}
        			}
        
        			if (match_available !== 0) {
        				bflush = _tr_tally(0, window[strstart - 1] & 0xff);
        				match_available = 0;
        			}
        			flush_block_only(flush == Z_FINISH);
        
        			if (strm.avail_out === 0) {
        				if (flush == Z_FINISH)
        					return FinishStarted;
        				else
        					return NeedMore;
        			}
        
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		function deflateReset(strm) {
        			strm.total_in = strm.total_out = 0;
        			strm.msg = null; //
        			
        			that.pending = 0;
        			that.pending_out = 0;
        
        			status = BUSY_STATE;
        
        			last_flush = Z_NO_FLUSH;
        
        			tr_init();
        			lm_init();
        			return Z_OK;
        		}
        
        		that.deflateInit = function(strm, _level, bits, _method, memLevel, _strategy) {
        			if (!_method)
        				_method = Z_DEFLATED;
        			if (!memLevel)
        				memLevel = DEF_MEM_LEVEL;
        			if (!_strategy)
        				_strategy = Z_DEFAULT_STRATEGY;
        
        			// byte[] my_version=ZLIB_VERSION;
        
        			//
        			// if (!version || version[0] != my_version[0]
        			// || stream_size != sizeof(z_stream)) {
        			// return Z_VERSION_ERROR;
        			// }
        
        			strm.msg = null;
        
        			if (_level == Z_DEFAULT_COMPRESSION)
        				_level = 6;
        
        			if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
        					|| _strategy > Z_HUFFMAN_ONLY) {
        				return Z_STREAM_ERROR;
        			}
        
        			strm.dstate = that;
        
        			w_bits = bits;
        			w_size = 1 << w_bits;
        			w_mask = w_size - 1;
        
        			hash_bits = memLevel + 7;
        			hash_size = 1 << hash_bits;
        			hash_mask = hash_size - 1;
        			hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
        
        			window = new Uint8Array(w_size * 2);
        			prev = [];
        			head = [];
        
        			lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
        
        			// We overlay pending_buf and d_buf+l_buf. This works since the average
        			// output size for (length,distance) codes is <= 24 bits.
        			that.pending_buf = new Uint8Array(lit_bufsize * 4);
        			pending_buf_size = lit_bufsize * 4;
        
        			d_buf = Math.floor(lit_bufsize / 2);
        			l_buf = (1 + 2) * lit_bufsize;
        
        			level = _level;
        
        			strategy = _strategy;
        			method = _method & 0xff;
        
        			return deflateReset(strm);
        		};
        
        		that.deflateEnd = function() {
        			if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
        				return Z_STREAM_ERROR;
        			}
        			// Deallocate in reverse order of allocations:
        			that.pending_buf = null;
        			head = null;
        			prev = null;
        			window = null;
        			// free
        			that.dstate = null;
        			return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
        		};
        
        		that.deflateParams = function(strm, _level, _strategy) {
        			var err = Z_OK;
        
        			if (_level == Z_DEFAULT_COMPRESSION) {
        				_level = 6;
        			}
        			if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
        				return Z_STREAM_ERROR;
        			}
        
        			if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
        				// Flush the last buffer:
        				err = strm.deflate(Z_PARTIAL_FLUSH);
        			}
        
        			if (level != _level) {
        				level = _level;
        				max_lazy_match = config_table[level].max_lazy;
        				good_match = config_table[level].good_length;
        				nice_match = config_table[level].nice_length;
        				max_chain_length = config_table[level].max_chain;
        			}
        			strategy = _strategy;
        			return err;
        		};
        
        		that.deflateSetDictionary = function(strm, dictionary, dictLength) {
        			var length = dictLength;
        			var n, index = 0;
        
        			if (!dictionary || status != INIT_STATE)
        				return Z_STREAM_ERROR;
        
        			if (length < MIN_MATCH)
        				return Z_OK;
        			if (length > w_size - MIN_LOOKAHEAD) {
        				length = w_size - MIN_LOOKAHEAD;
        				index = dictLength - length; // use the tail of the dictionary
        			}
        			window.set(dictionary.subarray(index, index + length), 0);
        
        			strstart = length;
        			block_start = length;
        
        			// Insert all strings in the hash table (except for the last two bytes).
        			// s->lookahead stays null, so s->ins_h will be recomputed at the next
        			// call of fill_window.
        
        			ins_h = window[0] & 0xff;
        			ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
        
        			for (n = 0; n <= length - MIN_MATCH; n++) {
        				ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        				prev[n & w_mask] = head[ins_h];
        				head[ins_h] = n;
        			}
        			return Z_OK;
        		};
        
        		that.deflate = function(_strm, flush) {
        			var i, header, level_flags, old_flush, bstate;
        
        			if (flush > Z_FINISH || flush < 0) {
        				return Z_STREAM_ERROR;
        			}
        
        			if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
        				return Z_STREAM_ERROR;
        			}
        			if (_strm.avail_out === 0) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			strm = _strm; // just in case
        			old_flush = last_flush;
        			last_flush = flush;
        
        			// Write the zlib header
        			if (status == INIT_STATE) {
        				header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
        				level_flags = ((level - 1) & 0xff) >> 1;
        
        				if (level_flags > 3)
        					level_flags = 3;
        				header |= (level_flags << 6);
        				if (strstart !== 0)
        					header |= PRESET_DICT;
        				header += 31 - (header % 31);
        
        				status = BUSY_STATE;
        				putShortMSB(header);
        			}
        
        			// Flush as much pending output as possible
        			if (that.pending !== 0) {
        				strm.flush_pending();
        				if (strm.avail_out === 0) {
        					// console.log(" avail_out==0");
        					// Since avail_out is 0, deflate will be called again with
        					// more output space, but possibly with both pending and
        					// avail_in equal to zero. There won't be anything to do,
        					// but this is not an error situation so make sure we
        					// return OK instead of BUF_ERROR at next call of deflate:
        					last_flush = -1;
        					return Z_OK;
        				}
        
        				// Make sure there is something to do and avoid duplicate
        				// consecutive
        				// flushes. For repeated and useless calls with Z_FINISH, we keep
        				// returning Z_STREAM_END instead of Z_BUFF_ERROR.
        			} else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
        				strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			// User must not provide more input after the first FINISH:
        			if (status == FINISH_STATE && strm.avail_in !== 0) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			// Start a new block or continue the current one.
        			if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
        				bstate = -1;
        				switch (config_table[level].func) {
        				case STORED:
        					bstate = deflate_stored(flush);
        					break;
        				case FAST:
        					bstate = deflate_fast(flush);
        					break;
        				case SLOW:
        					bstate = deflate_slow(flush);
        					break;
        				default:
        				}
        
        				if (bstate == FinishStarted || bstate == FinishDone) {
        					status = FINISH_STATE;
        				}
        				if (bstate == NeedMore || bstate == FinishStarted) {
        					if (strm.avail_out === 0) {
        						last_flush = -1; // avoid BUF_ERROR next call, see above
        					}
        					return Z_OK;
        					// If flush != Z_NO_FLUSH && avail_out === 0, the next call
        					// of deflate should use the same flush parameter to make sure
        					// that the flush is complete. So we don't have to output an
        					// empty block here, this will be done at next call. This also
        					// ensures that for a very small output buffer, we emit at most
        					// one empty block.
        				}
        
        				if (bstate == BlockDone) {
        					if (flush == Z_PARTIAL_FLUSH) {
        						_tr_align();
        					} else { // FULL_FLUSH or SYNC_FLUSH
        						_tr_stored_block(0, 0, false);
        						// For a full flush, this empty block will be recognized
        						// as a special marker by inflate_sync().
        						if (flush == Z_FULL_FLUSH) {
        							// state.head[s.hash_size-1]=0;
        							for (i = 0; i < hash_size/*-1*/; i++)
        								// forget history
        								head[i] = 0;
        						}
        					}
        					strm.flush_pending();
        					if (strm.avail_out === 0) {
        						last_flush = -1; // avoid BUF_ERROR at next call, see above
        						return Z_OK;
        					}
        				}
        			}
        
        			if (flush != Z_FINISH)
        				return Z_OK;
        			return Z_STREAM_END;
        		};
        	}
        
        	// ZStream
        
        	function ZStream() {
        		var that = this;
        		that.next_in_index = 0;
        		that.next_out_index = 0;
        		// that.next_in; // next input byte
        		that.avail_in = 0; // number of bytes available at next_in
        		that.total_in = 0; // total nb of input bytes read so far
        		// that.next_out; // next output byte should be put there
        		that.avail_out = 0; // remaining free space at next_out
        		that.total_out = 0; // total nb of bytes output so far
        		// that.msg;
        		// that.dstate;
        	}
        
        	ZStream.prototype = {
        		deflateInit : function(level, bits) {
        			var that = this;
        			that.dstate = new Deflate();
        			if (!bits)
        				bits = MAX_BITS;
        			return that.dstate.deflateInit(that, level, bits);
        		},
        
        		deflate : function(flush) {
        			var that = this;
        			if (!that.dstate) {
        				return Z_STREAM_ERROR;
        			}
        			return that.dstate.deflate(that, flush);
        		},
        
        		deflateEnd : function() {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			var ret = that.dstate.deflateEnd();
        			that.dstate = null;
        			return ret;
        		},
        
        		deflateParams : function(level, strategy) {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			return that.dstate.deflateParams(that, level, strategy);
        		},
        
        		deflateSetDictionary : function(dictionary, dictLength) {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
        		},
        
        		// Read a new buffer from the current input stream, update the
        		// total number of bytes read. All deflate() input goes through
        		// this function so some applications may wish to modify it to avoid
        		// allocating a large strm->next_in buffer and copying from it.
        		// (See also flush_pending()).
        		read_buf : function(buf, start, size) {
        			var that = this;
        			var len = that.avail_in;
        			if (len > size)
        				len = size;
        			if (len === 0)
        				return 0;
        			that.avail_in -= len;
        			buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
        			that.next_in_index += len;
        			that.total_in += len;
        			return len;
        		},
        
        		// Flush as much pending output as possible. All deflate() output goes
        		// through this function so some applications may wish to modify it
        		// to avoid allocating a large strm->next_out buffer and copying into it.
        		// (See also read_buf()).
        		flush_pending : function() {
        			var that = this;
        			var len = that.dstate.pending;
        
        			if (len > that.avail_out)
        				len = that.avail_out;
        			if (len === 0)
        				return;
        
        			// if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
        			// || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
        			// len)) {
        			// console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
        			// that.next_out_index + ", " + len);
        			// console.log("avail_out=" + that.avail_out);
        			// }
        
        			that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
        
        			that.next_out_index += len;
        			that.dstate.pending_out += len;
        			that.total_out += len;
        			that.avail_out -= len;
        			that.dstate.pending -= len;
        			if (that.dstate.pending === 0) {
        				that.dstate.pending_out = 0;
        			}
        		}
        	};
        
        	// Deflater
        
        	function Deflater(options) {
        		var that = this;
        		var z = new ZStream();
        		var bufsize = 512;
        		var flush = Z_NO_FLUSH;
        		var buf = new Uint8Array(bufsize);
        		var level = options ? options.level : Z_DEFAULT_COMPRESSION;
        		if (typeof level == "undefined")
        			level = Z_DEFAULT_COMPRESSION;
        		z.deflateInit(level);
        		z.next_out = buf;
        
        		that.append = function(data, onprogress) {
        			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
        			if (!data.length)
        				return;
        			z.next_in_index = 0;
        			z.next_in = data;
        			z.avail_in = data.length;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				err = z.deflate(flush);
        				if (err != Z_OK)
        					throw new Error("deflating: " + z.msg);
        				if (z.next_out_index)
        					if (z.next_out_index == bufsize)
        						buffers.push(new Uint8Array(buf));
        					else
        						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
        					onprogress(z.next_in_index);
        					lastIndex = z.next_in_index;
        				}
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        		that.flush = function() {
        			var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				err = z.deflate(Z_FINISH);
        				if (err != Z_STREAM_END && err != Z_OK)
        					throw new Error("deflating: " + z.msg);
        				if (bufsize - z.avail_out > 0)
        					buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			z.deflateEnd();
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        	}
        
        	// 'zip' may not be defined in z-worker and some tests
        	var env = global.zip || global;
        	env.Deflater = env._jzlib_Deflater = Deflater;
        })(this);
      • inflate.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright 
         notice, this list of conditions and the following disclaimer in 
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        /*
         * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
         * JZlib is based on zlib-1.1.3, so all credit should go authors
         * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
         * and contributors of zlib.
         */
        
        (function(global) {
        	"use strict";
        
        	// Global
        	var MAX_BITS = 15;
        
        	var Z_OK = 0;
        	var Z_STREAM_END = 1;
        	var Z_NEED_DICT = 2;
        	var Z_STREAM_ERROR = -2;
        	var Z_DATA_ERROR = -3;
        	var Z_MEM_ERROR = -4;
        	var Z_BUF_ERROR = -5;
        
        	var inflate_mask = [ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff,
        			0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff ];
        
        	var MANY = 1440;
        
        	// JZlib version : "1.0.2"
        	var Z_NO_FLUSH = 0;
        	var Z_FINISH = 4;
        
        	// InfTree
        	var fixed_bl = 9;
        	var fixed_bd = 5;
        
        	var fixed_tl = [ 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0,
        			0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40,
        			0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13,
        			0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60,
        			0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7,
        			35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8,
        			26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80,
        			7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0,
        			8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0,
        			8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97,
        			0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210,
        			81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117,
        			0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154,
        			84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83,
        			0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230,
        			80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139,
        			0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174,
        			0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111,
        			0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9,
        			193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8,
        			120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8,
        			227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8,
        			92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9,
        			249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8,
        			130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9,
        			181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8,
        			102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9,
        			221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0,
        			8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9,
        			147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8,
        			85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9,
        			235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8,
        			141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9,
        			167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8,
        			107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9,
        			207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8,
        			127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255 ];
        	var fixed_td = [ 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5,
        			8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5,
        			24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 ];
        
        	// Tables for deflate from PKZIP's appnote.txt.
        	var cplens = [ // Copy lengths for literal codes 257..285
        	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 ];
        
        	// see note #13 above about 258
        	var cplext = [ // Extra bits for literal codes 257..285
        	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
        	];
        
        	var cpdist = [ // Copy offsets for distance codes 0..29
        	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];
        
        	var cpdext = [ // Extra bits for distance codes
        	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];
        
        	// If BMAX needs to be larger than 16, then h and x[] should be uLong.
        	var BMAX = 15; // maximum bit length of any code
        
        	function InfTree() {
        		var that = this;
        
        		var hn; // hufts used in space
        		var v; // work area for huft_build
        		var c; // bit length count table
        		var r; // table entry for structure assignment
        		var u; // table stack
        		var x; // bit offsets, then code stack
        
        		function huft_build(b, // code lengths in bits (all assumed <=
        		// BMAX)
        		bindex, n, // number of codes (assumed <= 288)
        		s, // number of simple-valued codes (0..s-1)
        		d, // list of base values for non-simple codes
        		e, // list of extra bits for non-simple codes
        		t, // result: starting table
        		m, // maximum lookup bits, returns actual
        		hp,// space for trees
        		hn,// hufts used in space
        		v // working area: values in order of bit length
        		) {
        			// Given a list of code lengths and a maximum table size, make a set of
        			// tables to decode that set of codes. Return Z_OK on success,
        			// Z_BUF_ERROR
        			// if the given code set is incomplete (the tables are still built in
        			// this
        			// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set
        			// of
        			// lengths), or Z_MEM_ERROR if not enough memory.
        
        			var a; // counter for codes of length k
        			var f; // i repeats in table every f entries
        			var g; // maximum code length
        			var h; // table level
        			var i; // counter, current code
        			var j; // counter
        			var k; // number of bits in current code
        			var l; // bits per table (returned in m)
        			var mask; // (1 << w) - 1, to avoid cc -O bug on HP
        			var p; // pointer into c[], b[], or v[]
        			var q; // points to current table
        			var w; // bits before this table == (l * h)
        			var xp; // pointer into x
        			var y; // number of dummy codes added
        			var z; // number of entries in current table
        
        			// Generate counts for each bit length
        
        			p = 0;
        			i = n;
        			do {
        				c[b[bindex + p]]++;
        				p++;
        				i--; // assume all entries <= BMAX
        			} while (i !== 0);
        
        			if (c[0] == n) { // null input--all zero length codes
        				t[0] = -1;
        				m[0] = 0;
        				return Z_OK;
        			}
        
        			// Find minimum and maximum length, bound *m by those
        			l = m[0];
        			for (j = 1; j <= BMAX; j++)
        				if (c[j] !== 0)
        					break;
        			k = j; // minimum code length
        			if (l < j) {
        				l = j;
        			}
        			for (i = BMAX; i !== 0; i--) {
        				if (c[i] !== 0)
        					break;
        			}
        			g = i; // maximum code length
        			if (l > i) {
        				l = i;
        			}
        			m[0] = l;
        
        			// Adjust last length count to fill out codes, if needed
        			for (y = 1 << j; j < i; j++, y <<= 1) {
        				if ((y -= c[j]) < 0) {
        					return Z_DATA_ERROR;
        				}
        			}
        			if ((y -= c[i]) < 0) {
        				return Z_DATA_ERROR;
        			}
        			c[i] += y;
        
        			// Generate starting offsets into the value table for each length
        			x[1] = j = 0;
        			p = 1;
        			xp = 2;
        			while (--i !== 0) { // note that i == g from above
        				x[xp] = (j += c[p]);
        				xp++;
        				p++;
        			}
        
        			// Make a table of values in order of bit lengths
        			i = 0;
        			p = 0;
        			do {
        				if ((j = b[bindex + p]) !== 0) {
        					v[x[j]++] = i;
        				}
        				p++;
        			} while (++i < n);
        			n = x[g]; // set n to length of v
        
        			// Generate the Huffman codes and for each, make the table entries
        			x[0] = i = 0; // first Huffman code is zero
        			p = 0; // grab values in bit order
        			h = -1; // no tables yet--level -1
        			w = -l; // bits decoded == (l * h)
        			u[0] = 0; // just to keep compilers happy
        			q = 0; // ditto
        			z = 0; // ditto
        
        			// go through the bit lengths (k already is bits in shortest code)
        			for (; k <= g; k++) {
        				a = c[k];
        				while (a-- !== 0) {
        					// here i is the Huffman code of length k bits for value *p
        					// make tables up to required level
        					while (k > w + l) {
        						h++;
        						w += l; // previous table always l bits
        						// compute minimum size table less than or equal to l bits
        						z = g - w;
        						z = (z > l) ? l : z; // table size upper limit
        						if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table
        							// too few codes for
        							// k-w bit table
        							f -= a + 1; // deduct codes from patterns left
        							xp = k;
        							if (j < z) {
        								while (++j < z) { // try smaller tables up to z bits
        									if ((f <<= 1) <= c[++xp])
        										break; // enough codes to use up j bits
        									f -= c[xp]; // else deduct codes from patterns
        								}
        							}
        						}
        						z = 1 << j; // table entries for j-bit table
        
        						// allocate new table
        						if (hn[0] + z > MANY) { // (note: doesn't matter for fixed)
        							return Z_DATA_ERROR; // overflow of MANY
        						}
        						u[h] = q = /* hp+ */hn[0]; // DEBUG
        						hn[0] += z;
        
        						// connect to last table, if there is one
        						if (h !== 0) {
        							x[h] = i; // save pattern for backing up
        							r[0] = /* (byte) */j; // bits in this table
        							r[1] = /* (byte) */l; // bits to dump before this table
        							j = i >>> (w - l);
        							r[2] = /* (int) */(q - u[h - 1] - j); // offset to this table
        							hp.set(r, (u[h - 1] + j) * 3);
        							// to
        							// last
        							// table
        						} else {
        							t[0] = q; // first table is returned result
        						}
        					}
        
        					// set up table entry in r
        					r[1] = /* (byte) */(k - w);
        					if (p >= n) {
        						r[0] = 128 + 64; // out of values--invalid code
        					} else if (v[p] < s) {
        						r[0] = /* (byte) */(v[p] < 256 ? 0 : 32 + 64); // 256 is
        						// end-of-block
        						r[2] = v[p++]; // simple code is just the value
        					} else {
        						r[0] = /* (byte) */(e[v[p] - s] + 16 + 64); // non-simple--look
        						// up in lists
        						r[2] = d[v[p++] - s];
        					}
        
        					// fill code-like entries with r
        					f = 1 << (k - w);
        					for (j = i >>> w; j < z; j += f) {
        						hp.set(r, (q + j) * 3);
        					}
        
        					// backwards increment the k-bit code i
        					for (j = 1 << (k - 1); (i & j) !== 0; j >>>= 1) {
        						i ^= j;
        					}
        					i ^= j;
        
        					// backup over finished tables
        					mask = (1 << w) - 1; // needed on HP, cc -O bug
        					while ((i & mask) != x[h]) {
        						h--; // don't need to update q
        						w -= l;
        						mask = (1 << w) - 1;
        					}
        				}
        			}
        			// Return Z_BUF_ERROR if we were given an incomplete table
        			return y !== 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
        		}
        
        		function initWorkArea(vsize) {
        			var i;
        			if (!hn) {
        				hn = []; // []; //new Array(1);
        				v = []; // new Array(vsize);
        				c = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
        				r = []; // new Array(3);
        				u = new Int32Array(BMAX); // new Array(BMAX);
        				x = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
        			}
        			if (v.length < vsize) {
        				v = []; // new Array(vsize);
        			}
        			for (i = 0; i < vsize; i++) {
        				v[i] = 0;
        			}
        			for (i = 0; i < BMAX + 1; i++) {
        				c[i] = 0;
        			}
        			for (i = 0; i < 3; i++) {
        				r[i] = 0;
        			}
        			// for(int i=0; i<BMAX; i++){u[i]=0;}
        			u.set(c.subarray(0, BMAX), 0);
        			// for(int i=0; i<BMAX+1; i++){x[i]=0;}
        			x.set(c.subarray(0, BMAX + 1), 0);
        		}
        
        		that.inflate_trees_bits = function(c, // 19 code lengths
        		bb, // bits tree desired/actual depth
        		tb, // bits tree result
        		hp, // space for trees
        		z // for messages
        		) {
        			var result;
        			initWorkArea(19);
        			hn[0] = 0;
        			result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
        
        			if (result == Z_DATA_ERROR) {
        				z.msg = "oversubscribed dynamic bit lengths tree";
        			} else if (result == Z_BUF_ERROR || bb[0] === 0) {
        				z.msg = "incomplete dynamic bit lengths tree";
        				result = Z_DATA_ERROR;
        			}
        			return result;
        		};
        
        		that.inflate_trees_dynamic = function(nl, // number of literal/length codes
        		nd, // number of distance codes
        		c, // that many (total) code lengths
        		bl, // literal desired/actual bit depth
        		bd, // distance desired/actual bit depth
        		tl, // literal/length tree result
        		td, // distance tree result
        		hp, // space for trees
        		z // for messages
        		) {
        			var result;
        
        			// build literal/length tree
        			initWorkArea(288);
        			hn[0] = 0;
        			result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
        			if (result != Z_OK || bl[0] === 0) {
        				if (result == Z_DATA_ERROR) {
        					z.msg = "oversubscribed literal/length tree";
        				} else if (result != Z_MEM_ERROR) {
        					z.msg = "incomplete literal/length tree";
        					result = Z_DATA_ERROR;
        				}
        				return result;
        			}
        
        			// build distance tree
        			initWorkArea(288);
        			result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
        
        			if (result != Z_OK || (bd[0] === 0 && nl > 257)) {
        				if (result == Z_DATA_ERROR) {
        					z.msg = "oversubscribed distance tree";
        				} else if (result == Z_BUF_ERROR) {
        					z.msg = "incomplete distance tree";
        					result = Z_DATA_ERROR;
        				} else if (result != Z_MEM_ERROR) {
        					z.msg = "empty distance tree with lengths";
        					result = Z_DATA_ERROR;
        				}
        				return result;
        			}
        
        			return Z_OK;
        		};
        
        	}
        
        	InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth
        	bd, // distance desired/actual bit depth
        	tl,// literal/length tree result
        	td// distance tree result
        	) {
        		bl[0] = fixed_bl;
        		bd[0] = fixed_bd;
        		tl[0] = fixed_tl;
        		td[0] = fixed_td;
        		return Z_OK;
        	};
        
        	// InfCodes
        
        	// waiting for "i:"=input,
        	// "o:"=output,
        	// "x:"=nothing
        	var START = 0; // x: set up for LEN
        	var LEN = 1; // i: get length/literal/eob next
        	var LENEXT = 2; // i: getting length extra (have base)
        	var DIST = 3; // i: get distance next
        	var DISTEXT = 4;// i: getting distance extra
        	var COPY = 5; // o: copying bytes in window, waiting
        	// for space
        	var LIT = 6; // o: got literal, waiting for output
        	// space
        	var WASH = 7; // o: got eob, possibly still output
        	// waiting
        	var END = 8; // x: got eob and all data flushed
        	var BADCODE = 9;// x: got error
        
        	function InfCodes() {
        		var that = this;
        
        		var mode; // current inflate_codes mode
        
        		// mode dependent information
        		var len = 0;
        
        		var tree; // pointer into tree
        		var tree_index = 0;
        		var need = 0; // bits needed
        
        		var lit = 0;
        
        		// if EXT or COPY, where and how much
        		var get = 0; // bits to get for extra
        		var dist = 0; // distance back to copy from
        
        		var lbits = 0; // ltree bits decoded per branch
        		var dbits = 0; // dtree bits decoder per branch
        		var ltree; // literal/length/eob tree
        		var ltree_index = 0; // literal/length/eob tree
        		var dtree; // distance tree
        		var dtree_index = 0; // distance tree
        
        		// Called with number of bytes left to write in window at least 258
        		// (the maximum string length) and number of input bytes available
        		// at least ten. The ten bytes are six bytes for the longest length/
        		// distance pair plus four bytes for overloading the bit buffer.
        
        		function inflate_fast(bl, bd, tl, tl_index, td, td_index, s, z) {
        			var t; // temporary pointer
        			var tp; // temporary pointer
        			var tp_index; // temporary pointer
        			var e; // extra bits or operation
        			var b; // bit buffer
        			var k; // bits in bit buffer
        			var p; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        			var ml; // mask for literal/length tree
        			var md; // mask for distance tree
        			var c; // bytes to copy
        			var d; // distance back to copy from
        			var r; // copy source pointer
        
        			var tp_index_t_3; // (tp_index+t)*3
        
        			// load input, output, bit values
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = s.bitb;
        			k = s.bitk;
        			q = s.write;
        			m = q < s.read ? s.read - q - 1 : s.end - q;
        
        			// initialize masks
        			ml = inflate_mask[bl];
        			md = inflate_mask[bd];
        
        			// do until not enough input or output space for fast loop
        			do { // assume called with m >= 258 && n >= 10
        				// get literal/length code
        				while (k < (20)) { // max bits for literal/length code
        					n--;
        					b |= (z.read_byte(p++) & 0xff) << k;
        					k += 8;
        				}
        
        				t = b & ml;
        				tp = tl;
        				tp_index = tl_index;
        				tp_index_t_3 = (tp_index + t) * 3;
        				if ((e = tp[tp_index_t_3]) === 0) {
        					b >>= (tp[tp_index_t_3 + 1]);
        					k -= (tp[tp_index_t_3 + 1]);
        
        					s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
        					m--;
        					continue;
        				}
        				do {
        
        					b >>= (tp[tp_index_t_3 + 1]);
        					k -= (tp[tp_index_t_3 + 1]);
        
        					if ((e & 16) !== 0) {
        						e &= 15;
        						c = tp[tp_index_t_3 + 2] + (/* (int) */b & inflate_mask[e]);
        
        						b >>= e;
        						k -= e;
        
        						// decode distance base of block to copy
        						while (k < (15)) { // max bits for distance code
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						t = b & md;
        						tp = td;
        						tp_index = td_index;
        						tp_index_t_3 = (tp_index + t) * 3;
        						e = tp[tp_index_t_3];
        
        						do {
        
        							b >>= (tp[tp_index_t_3 + 1]);
        							k -= (tp[tp_index_t_3 + 1]);
        
        							if ((e & 16) !== 0) {
        								// get extra bits to add to distance base
        								e &= 15;
        								while (k < (e)) { // get extra bits (up to 13)
        									n--;
        									b |= (z.read_byte(p++) & 0xff) << k;
        									k += 8;
        								}
        
        								d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
        
        								b >>= (e);
        								k -= (e);
        
        								// do the copy
        								m -= c;
        								if (q >= d) { // offset before dest
        									// just copy
        									r = q - d;
        									if (q - r > 0 && 2 > (q - r)) {
        										s.window[q++] = s.window[r++]; // minimum
        										// count is
        										// three,
        										s.window[q++] = s.window[r++]; // so unroll
        										// loop a
        										// little
        										c -= 2;
        									} else {
        										s.window.set(s.window.subarray(r, r + 2), q);
        										q += 2;
        										r += 2;
        										c -= 2;
        									}
        								} else { // else offset after destination
        									r = q - d;
        									do {
        										r += s.end; // force pointer in window
        									} while (r < 0); // covers invalid distances
        									e = s.end - r;
        									if (c > e) { // if source crosses,
        										c -= e; // wrapped copy
        										if (q - r > 0 && e > (q - r)) {
        											do {
        												s.window[q++] = s.window[r++];
        											} while (--e !== 0);
        										} else {
        											s.window.set(s.window.subarray(r, r + e), q);
        											q += e;
        											r += e;
        											e = 0;
        										}
        										r = 0; // copy rest from start of window
        									}
        
        								}
        
        								// copy all or what's left
        								if (q - r > 0 && c > (q - r)) {
        									do {
        										s.window[q++] = s.window[r++];
        									} while (--c !== 0);
        								} else {
        									s.window.set(s.window.subarray(r, r + c), q);
        									q += c;
        									r += c;
        									c = 0;
        								}
        								break;
        							} else if ((e & 64) === 0) {
        								t += tp[tp_index_t_3 + 2];
        								t += (b & inflate_mask[e]);
        								tp_index_t_3 = (tp_index + t) * 3;
        								e = tp[tp_index_t_3];
        							} else {
        								z.msg = "invalid distance code";
        
        								c = z.avail_in - n;
        								c = (k >> 3) < c ? k >> 3 : c;
        								n += c;
        								p -= c;
        								k -= c << 3;
        
        								s.bitb = b;
        								s.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								s.write = q;
        
        								return Z_DATA_ERROR;
        							}
        						} while (true);
        						break;
        					}
        
        					if ((e & 64) === 0) {
        						t += tp[tp_index_t_3 + 2];
        						t += (b & inflate_mask[e]);
        						tp_index_t_3 = (tp_index + t) * 3;
        						if ((e = tp[tp_index_t_3]) === 0) {
        
        							b >>= (tp[tp_index_t_3 + 1]);
        							k -= (tp[tp_index_t_3 + 1]);
        
        							s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
        							m--;
        							break;
        						}
        					} else if ((e & 32) !== 0) {
        
        						c = z.avail_in - n;
        						c = (k >> 3) < c ? k >> 3 : c;
        						n += c;
        						p -= c;
        						k -= c << 3;
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        
        						return Z_STREAM_END;
        					} else {
        						z.msg = "invalid literal/length code";
        
        						c = z.avail_in - n;
        						c = (k >> 3) < c ? k >> 3 : c;
        						n += c;
        						p -= c;
        						k -= c << 3;
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        
        						return Z_DATA_ERROR;
        					}
        				} while (true);
        			} while (m >= 258 && n >= 10);
        
        			// not enough input or output--restore pointers and return
        			c = z.avail_in - n;
        			c = (k >> 3) < c ? k >> 3 : c;
        			n += c;
        			p -= c;
        			k -= c << 3;
        
        			s.bitb = b;
        			s.bitk = k;
        			z.avail_in = n;
        			z.total_in += p - z.next_in_index;
        			z.next_in_index = p;
        			s.write = q;
        
        			return Z_OK;
        		}
        
        		that.init = function(bl, bd, tl, tl_index, td, td_index) {
        			mode = START;
        			lbits = /* (byte) */bl;
        			dbits = /* (byte) */bd;
        			ltree = tl;
        			ltree_index = tl_index;
        			dtree = td;
        			dtree_index = td_index;
        			tree = null;
        		};
        
        		that.proc = function(s, z, r) {
        			var j; // temporary storage
        			var tindex; // temporary pointer
        			var e; // extra bits or operation
        			var b = 0; // bit buffer
        			var k = 0; // bits in bit buffer
        			var p = 0; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        			var f; // pointer to copy strings from
        
        			// copy input/output information to locals (UPDATE macro restores)
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = s.bitb;
        			k = s.bitk;
        			q = s.write;
        			m = q < s.read ? s.read - q - 1 : s.end - q;
        
        			// process input and output based on current state
        			while (true) {
        				switch (mode) {
        				// waiting for "i:"=input, "o:"=output, "x:"=nothing
        				case START: // x: set up for LEN
        					if (m >= 258 && n >= 10) {
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        						r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);
        
        						p = z.next_in_index;
        						n = z.avail_in;
        						b = s.bitb;
        						k = s.bitk;
        						q = s.write;
        						m = q < s.read ? s.read - q - 1 : s.end - q;
        
        						if (r != Z_OK) {
        							mode = r == Z_STREAM_END ? WASH : BADCODE;
        							break;
        						}
        					}
        					need = lbits;
        					tree = ltree;
        					tree_index = ltree_index;
        
        					mode = LEN;
        					/* falls through */
        				case LEN: // i: get length/literal/eob next
        					j = need;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					tindex = (tree_index + (b & inflate_mask[j])) * 3;
        
        					b >>>= (tree[tindex + 1]);
        					k -= (tree[tindex + 1]);
        
        					e = tree[tindex];
        
        					if (e === 0) { // literal
        						lit = tree[tindex + 2];
        						mode = LIT;
        						break;
        					}
        					if ((e & 16) !== 0) { // length
        						get = e & 15;
        						len = tree[tindex + 2];
        						mode = LENEXT;
        						break;
        					}
        					if ((e & 64) === 0) { // next table
        						need = e;
        						tree_index = tindex / 3 + tree[tindex + 2];
        						break;
        					}
        					if ((e & 32) !== 0) { // end of block
        						mode = WASH;
        						break;
        					}
        					mode = BADCODE; // invalid code
        					z.msg = "invalid literal/length code";
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case LENEXT: // i: getting length extra (have base)
        					j = get;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					len += (b & inflate_mask[j]);
        
        					b >>= j;
        					k -= j;
        
        					need = dbits;
        					tree = dtree;
        					tree_index = dtree_index;
        					mode = DIST;
        					/* falls through */
        				case DIST: // i: get distance next
        					j = need;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					tindex = (tree_index + (b & inflate_mask[j])) * 3;
        
        					b >>= tree[tindex + 1];
        					k -= tree[tindex + 1];
        
        					e = (tree[tindex]);
        					if ((e & 16) !== 0) { // distance
        						get = e & 15;
        						dist = tree[tindex + 2];
        						mode = DISTEXT;
        						break;
        					}
        					if ((e & 64) === 0) { // next table
        						need = e;
        						tree_index = tindex / 3 + tree[tindex + 2];
        						break;
        					}
        					mode = BADCODE; // invalid code
        					z.msg = "invalid distance code";
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case DISTEXT: // i: getting distance extra
        					j = get;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					dist += (b & inflate_mask[j]);
        
        					b >>= j;
        					k -= j;
        
        					mode = COPY;
        					/* falls through */
        				case COPY: // o: copying bytes in window, waiting for space
        					f = q - dist;
        					while (f < 0) { // modulo window size-"while" instead
        						f += s.end; // of "if" handles invalid distances
        					}
        					while (len !== 0) {
        
        						if (m === 0) {
        							if (q == s.end && s.read !== 0) {
        								q = 0;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        							}
        							if (m === 0) {
        								s.write = q;
        								r = s.inflate_flush(z, r);
        								q = s.write;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        
        								if (q == s.end && s.read !== 0) {
        									q = 0;
        									m = q < s.read ? s.read - q - 1 : s.end - q;
        								}
        
        								if (m === 0) {
        									s.bitb = b;
        									s.bitk = k;
        									z.avail_in = n;
        									z.total_in += p - z.next_in_index;
        									z.next_in_index = p;
        									s.write = q;
        									return s.inflate_flush(z, r);
        								}
        							}
        						}
        
        						s.window[q++] = s.window[f++];
        						m--;
        
        						if (f == s.end)
        							f = 0;
        						len--;
        					}
        					mode = START;
        					break;
        				case LIT: // o: got literal, waiting for output space
        					if (m === 0) {
        						if (q == s.end && s.read !== 0) {
        							q = 0;
        							m = q < s.read ? s.read - q - 1 : s.end - q;
        						}
        						if (m === 0) {
        							s.write = q;
        							r = s.inflate_flush(z, r);
        							q = s.write;
        							m = q < s.read ? s.read - q - 1 : s.end - q;
        
        							if (q == s.end && s.read !== 0) {
        								q = 0;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        							}
        							if (m === 0) {
        								s.bitb = b;
        								s.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								s.write = q;
        								return s.inflate_flush(z, r);
        							}
        						}
        					}
        					r = Z_OK;
        
        					s.window[q++] = /* (byte) */lit;
        					m--;
        
        					mode = START;
        					break;
        				case WASH: // o: got eob, possibly more output
        					if (k > 7) { // return unused byte, if any
        						k -= 8;
        						n++;
        						p--; // can always return one
        					}
        
        					s.write = q;
        					r = s.inflate_flush(z, r);
        					q = s.write;
        					m = q < s.read ? s.read - q - 1 : s.end - q;
        
        					if (s.read != s.write) {
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        						return s.inflate_flush(z, r);
        					}
        					mode = END;
        					/* falls through */
        				case END:
        					r = Z_STREAM_END;
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case BADCODE: // x: got error
        
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				default:
        					r = Z_STREAM_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        				}
        			}
        		};
        
        		that.free = function() {
        			// ZFREE(z, c);
        		};
        
        	}
        
        	// InfBlocks
        
        	// Table for deflate from PKZIP's appnote.txt.
        	var border = [ // Order of the bit length code lengths
        	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
        
        	var TYPE = 0; // get type bits (3, including end bit)
        	var LENS = 1; // get lengths for stored
        	var STORED = 2;// processing stored block
        	var TABLE = 3; // get table lengths
        	var BTREE = 4; // get bit lengths tree for a dynamic
        	// block
        	var DTREE = 5; // get length, distance trees for a
        	// dynamic block
        	var CODES = 6; // processing fixed or dynamic block
        	var DRY = 7; // output remaining window bytes
        	var DONELOCKS = 8; // finished last block, done
        	var BADBLOCKS = 9; // ot a data error--stuck here
        
        	function InfBlocks(z, w) {
        		var that = this;
        
        		var mode = TYPE; // current inflate_block mode
        
        		var left = 0; // if STORED, bytes left to copy
        
        		var table = 0; // table lengths (14 bits)
        		var index = 0; // index into blens (or border)
        		var blens; // bit lengths of codes
        		var bb = [ 0 ]; // bit length tree depth
        		var tb = [ 0 ]; // bit length decoding tree
        
        		var codes = new InfCodes(); // if CODES, current state
        
        		var last = 0; // true if this block is the last block
        
        		var hufts = new Int32Array(MANY * 3); // single malloc for tree space
        		var check = 0; // check on output
        		var inftree = new InfTree();
        
        		that.bitk = 0; // bits in bit buffer
        		that.bitb = 0; // bit buffer
        		that.window = new Uint8Array(w); // sliding window
        		that.end = w; // one byte after sliding window
        		that.read = 0; // window read pointer
        		that.write = 0; // window write pointer
        
        		that.reset = function(z, c) {
        			if (c)
        				c[0] = check;
        			// if (mode == BTREE || mode == DTREE) {
        			// }
        			if (mode == CODES) {
        				codes.free(z);
        			}
        			mode = TYPE;
        			that.bitk = 0;
        			that.bitb = 0;
        			that.read = that.write = 0;
        		};
        
        		that.reset(z, null);
        
        		// copy as much as possible from the sliding window to the output area
        		that.inflate_flush = function(z, r) {
        			var n;
        			var p;
        			var q;
        
        			// local copies of source and destination pointers
        			p = z.next_out_index;
        			q = that.read;
        
        			// compute number of bytes to copy as far as end of window
        			n = /* (int) */((q <= that.write ? that.write : that.end) - q);
        			if (n > z.avail_out)
        				n = z.avail_out;
        			if (n !== 0 && r == Z_BUF_ERROR)
        				r = Z_OK;
        
        			// update counters
        			z.avail_out -= n;
        			z.total_out += n;
        
        			// copy as far as end of window
        			z.next_out.set(that.window.subarray(q, q + n), p);
        			p += n;
        			q += n;
        
        			// see if more to copy at beginning of window
        			if (q == that.end) {
        				// wrap pointers
        				q = 0;
        				if (that.write == that.end)
        					that.write = 0;
        
        				// compute bytes to copy
        				n = that.write - q;
        				if (n > z.avail_out)
        					n = z.avail_out;
        				if (n !== 0 && r == Z_BUF_ERROR)
        					r = Z_OK;
        
        				// update counters
        				z.avail_out -= n;
        				z.total_out += n;
        
        				// copy
        				z.next_out.set(that.window.subarray(q, q + n), p);
        				p += n;
        				q += n;
        			}
        
        			// update pointers
        			z.next_out_index = p;
        			that.read = q;
        
        			// done
        			return r;
        		};
        
        		that.proc = function(z, r) {
        			var t; // temporary storage
        			var b; // bit buffer
        			var k; // bits in bit buffer
        			var p; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        
        			var i;
        
        			// copy input/output information to locals (UPDATE macro restores)
        			// {
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = that.bitb;
        			k = that.bitk;
        			// }
        			// {
        			q = that.write;
        			m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        			// }
        
        			// process input based on current state
        			// DEBUG dtree
        			while (true) {
        				switch (mode) {
        				case TYPE:
        
        					while (k < (3)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        					t = /* (int) */(b & 7);
        					last = t & 1;
        
        					switch (t >>> 1) {
        					case 0: // stored
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        						t = k & 7; // go to byte boundary
        
        						// {
        						b >>>= (t);
        						k -= (t);
        						// }
        						mode = LENS; // get length of stored block
        						break;
        					case 1: // fixed
        						// {
        						var bl = []; // new Array(1);
        						var bd = []; // new Array(1);
        						var tl = [ [] ]; // new Array(1);
        						var td = [ [] ]; // new Array(1);
        
        						InfTree.inflate_trees_fixed(bl, bd, tl, td);
        						codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
        						// }
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        
        						mode = CODES;
        						break;
        					case 2: // dynamic
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        
        						mode = TABLE;
        						break;
        					case 3: // illegal
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        						mode = BADBLOCKS;
        						z.msg = "invalid block type";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					break;
        				case LENS:
        
        					while (k < (32)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) {
        						mode = BADBLOCKS;
        						z.msg = "invalid stored block lengths";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					left = (b & 0xffff);
        					b = k = 0; // dump bits
        					mode = left !== 0 ? STORED : (last !== 0 ? DRY : TYPE);
        					break;
        				case STORED:
        					if (n === 0) {
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        
        					if (m === 0) {
        						if (q == that.end && that.read !== 0) {
        							q = 0;
        							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        						}
        						if (m === 0) {
        							that.write = q;
        							r = that.inflate_flush(z, r);
        							q = that.write;
        							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        							if (q == that.end && that.read !== 0) {
        								q = 0;
        								m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        							}
        							if (m === 0) {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        						}
        					}
        					r = Z_OK;
        
        					t = left;
        					if (t > n)
        						t = n;
        					if (t > m)
        						t = m;
        					that.window.set(z.read_buf(p, t), q);
        					p += t;
        					n -= t;
        					q += t;
        					m -= t;
        					if ((left -= t) !== 0)
        						break;
        					mode = last !== 0 ? DRY : TYPE;
        					break;
        				case TABLE:
        
        					while (k < (14)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					table = t = (b & 0x3fff);
        					if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {
        						mode = BADBLOCKS;
        						z.msg = "too many length or distance symbols";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
        					if (!blens || blens.length < t) {
        						blens = []; // new Array(t);
        					} else {
        						for (i = 0; i < t; i++) {
        							blens[i] = 0;
        						}
        					}
        
        					// {
        					b >>>= (14);
        					k -= (14);
        					// }
        
        					index = 0;
        					mode = BTREE;
        					/* falls through */
        				case BTREE:
        					while (index < 4 + (table >>> 10)) {
        						while (k < (3)) {
        							if (n !== 0) {
        								r = Z_OK;
        							} else {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						blens[border[index++]] = b & 7;
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        					}
        
        					while (index < 19) {
        						blens[border[index++]] = 0;
        					}
        
        					bb[0] = 7;
        					t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
        					if (t != Z_OK) {
        						r = t;
        						if (r == Z_DATA_ERROR) {
        							blens = null;
        							mode = BADBLOCKS;
        						}
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        
        					index = 0;
        					mode = DTREE;
        					/* falls through */
        				case DTREE:
        					while (true) {
        						t = table;
        						if (index >= 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) {
        							break;
        						}
        
        						var j, c;
        
        						t = bb[0];
        
        						while (k < (t)) {
        							if (n !== 0) {
        								r = Z_OK;
        							} else {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						// if (tb[0] == -1) {
        						// System.err.println("null...");
        						// }
        
        						t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
        						c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
        
        						if (c < 16) {
        							b >>>= (t);
        							k -= (t);
        							blens[index++] = c;
        						} else { // c == 16..18
        							i = c == 18 ? 7 : c - 14;
        							j = c == 18 ? 11 : 3;
        
        							while (k < (t + i)) {
        								if (n !== 0) {
        									r = Z_OK;
        								} else {
        									that.bitb = b;
        									that.bitk = k;
        									z.avail_in = n;
        									z.total_in += p - z.next_in_index;
        									z.next_in_index = p;
        									that.write = q;
        									return that.inflate_flush(z, r);
        								}
        								n--;
        								b |= (z.read_byte(p++) & 0xff) << k;
        								k += 8;
        							}
        
        							b >>>= (t);
        							k -= (t);
        
        							j += (b & inflate_mask[i]);
        
        							b >>>= (i);
        							k -= (i);
        
        							i = index;
        							t = table;
        							if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) {
        								blens = null;
        								mode = BADBLOCKS;
        								z.msg = "invalid bit length repeat";
        								r = Z_DATA_ERROR;
        
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        
        							c = c == 16 ? blens[i - 1] : 0;
        							do {
        								blens[i++] = c;
        							} while (--j !== 0);
        							index = i;
        						}
        					}
        
        					tb[0] = -1;
        					// {
        					var bl_ = []; // new Array(1);
        					var bd_ = []; // new Array(1);
        					var tl_ = []; // new Array(1);
        					var td_ = []; // new Array(1);
        					bl_[0] = 9; // must be <= 9 for lookahead assumptions
        					bd_[0] = 6; // must be <= 9 for lookahead assumptions
        
        					t = table;
        					t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl_, bd_, tl_, td_, hufts, z);
        
        					if (t != Z_OK) {
        						if (t == Z_DATA_ERROR) {
        							blens = null;
        							mode = BADBLOCKS;
        						}
        						r = t;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0]);
        					// }
        					mode = CODES;
        					/* falls through */
        				case CODES:
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        
        					if ((r = codes.proc(that, z, r)) != Z_STREAM_END) {
        						return that.inflate_flush(z, r);
        					}
        					r = Z_OK;
        					codes.free(z);
        
        					p = z.next_in_index;
        					n = z.avail_in;
        					b = that.bitb;
        					k = that.bitk;
        					q = that.write;
        					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        
        					if (last === 0) {
        						mode = TYPE;
        						break;
        					}
        					mode = DRY;
        					/* falls through */
        				case DRY:
        					that.write = q;
        					r = that.inflate_flush(z, r);
        					q = that.write;
        					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        					if (that.read != that.write) {
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					mode = DONELOCKS;
        					/* falls through */
        				case DONELOCKS:
        					r = Z_STREAM_END;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        				case BADBLOCKS:
        					r = Z_DATA_ERROR;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        
        				default:
        					r = Z_STREAM_ERROR;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        				}
        			}
        		};
        
        		that.free = function(z) {
        			that.reset(z, null);
        			that.window = null;
        			hufts = null;
        			// ZFREE(z, s);
        		};
        
        		that.set_dictionary = function(d, start, n) {
        			that.window.set(d.subarray(start, start + n), 0);
        			that.read = that.write = n;
        		};
        
        		// Returns true if inflate is currently at the end of a block generated
        		// by Z_SYNC_FLUSH or Z_FULL_FLUSH.
        		that.sync_point = function() {
        			return mode == LENS ? 1 : 0;
        		};
        
        	}
        
        	// Inflate
        
        	// preset dictionary flag in zlib header
        	var PRESET_DICT = 0x20;
        
        	var Z_DEFLATED = 8;
        
        	var METHOD = 0; // waiting for method byte
        	var FLAG = 1; // waiting for flag byte
        	var DICT4 = 2; // four dictionary check bytes to go
        	var DICT3 = 3; // three dictionary check bytes to go
        	var DICT2 = 4; // two dictionary check bytes to go
        	var DICT1 = 5; // one dictionary check byte to go
        	var DICT0 = 6; // waiting for inflateSetDictionary
        	var BLOCKS = 7; // decompressing blocks
        	var DONE = 12; // finished check, done
        	var BAD = 13; // got an error--stay here
        
        	var mark = [ 0, 0, 0xff, 0xff ];
        
        	function Inflate() {
        		var that = this;
        
        		that.mode = 0; // current inflate mode
        
        		// mode dependent information
        		that.method = 0; // if FLAGS, method byte
        
        		// if CHECK, check values to compare
        		that.was = [ 0 ]; // new Array(1); // computed check value
        		that.need = 0; // stream check value
        
        		// if BAD, inflateSync's marker bytes count
        		that.marker = 0;
        
        		// mode independent information
        		that.wbits = 0; // log2(window size) (8..15, defaults to 15)
        
        		// this.blocks; // current inflate_blocks state
        
        		function inflateReset(z) {
        			if (!z || !z.istate)
        				return Z_STREAM_ERROR;
        
        			z.total_in = z.total_out = 0;
        			z.msg = null;
        			z.istate.mode = BLOCKS;
        			z.istate.blocks.reset(z, null);
        			return Z_OK;
        		}
        
        		that.inflateEnd = function(z) {
        			if (that.blocks)
        				that.blocks.free(z);
        			that.blocks = null;
        			// ZFREE(z, z->state);
        			return Z_OK;
        		};
        
        		that.inflateInit = function(z, w) {
        			z.msg = null;
        			that.blocks = null;
        
        			// set window size
        			if (w < 8 || w > 15) {
        				that.inflateEnd(z);
        				return Z_STREAM_ERROR;
        			}
        			that.wbits = w;
        
        			z.istate.blocks = new InfBlocks(z, 1 << w);
        
        			// reset state
        			inflateReset(z);
        			return Z_OK;
        		};
        
        		that.inflate = function(z, f) {
        			var r;
        			var b;
        
        			if (!z || !z.istate || !z.next_in)
        				return Z_STREAM_ERROR;
        			f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
        			r = Z_BUF_ERROR;
        			while (true) {
        				// System.out.println("mode: "+z.istate.mode);
        				switch (z.istate.mode) {
        				case METHOD:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					if (((z.istate.method = z.read_byte(z.next_in_index++)) & 0xf) != Z_DEFLATED) {
        						z.istate.mode = BAD;
        						z.msg = "unknown compression method";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        					if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
        						z.istate.mode = BAD;
        						z.msg = "invalid window size";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        					z.istate.mode = FLAG;
        					/* falls through */
        				case FLAG:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					b = (z.read_byte(z.next_in_index++)) & 0xff;
        
        					if ((((z.istate.method << 8) + b) % 31) !== 0) {
        						z.istate.mode = BAD;
        						z.msg = "incorrect header check";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        
        					if ((b & PRESET_DICT) === 0) {
        						z.istate.mode = BLOCKS;
        						break;
        					}
        					z.istate.mode = DICT4;
        					/* falls through */
        				case DICT4:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need = ((z.read_byte(z.next_in_index++) & 0xff) << 24) & 0xff000000;
        					z.istate.mode = DICT3;
        					/* falls through */
        				case DICT3:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 16) & 0xff0000;
        					z.istate.mode = DICT2;
        					/* falls through */
        				case DICT2:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 8) & 0xff00;
        					z.istate.mode = DICT1;
        					/* falls through */
        				case DICT1:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += (z.read_byte(z.next_in_index++) & 0xff);
        					z.istate.mode = DICT0;
        					return Z_NEED_DICT;
        				case DICT0:
        					z.istate.mode = BAD;
        					z.msg = "need dictionary";
        					z.istate.marker = 0; // can try inflateSync
        					return Z_STREAM_ERROR;
        				case BLOCKS:
        
        					r = z.istate.blocks.proc(z, r);
        					if (r == Z_DATA_ERROR) {
        						z.istate.mode = BAD;
        						z.istate.marker = 0; // can try inflateSync
        						break;
        					}
        					if (r == Z_OK) {
        						r = f;
        					}
        					if (r != Z_STREAM_END) {
        						return r;
        					}
        					r = f;
        					z.istate.blocks.reset(z, z.istate.was);
        					z.istate.mode = DONE;
        					/* falls through */
        				case DONE:
        					return Z_STREAM_END;
        				case BAD:
        					return Z_DATA_ERROR;
        				default:
        					return Z_STREAM_ERROR;
        				}
        			}
        		};
        
        		that.inflateSetDictionary = function(z, dictionary, dictLength) {
        			var index = 0;
        			var length = dictLength;
        			if (!z || !z.istate || z.istate.mode != DICT0)
        				return Z_STREAM_ERROR;
        
        			if (length >= (1 << z.istate.wbits)) {
        				length = (1 << z.istate.wbits) - 1;
        				index = dictLength - length;
        			}
        			z.istate.blocks.set_dictionary(dictionary, index, length);
        			z.istate.mode = BLOCKS;
        			return Z_OK;
        		};
        
        		that.inflateSync = function(z) {
        			var n; // number of bytes to look at
        			var p; // pointer to bytes
        			var m; // number of marker bytes found in a row
        			var r, w; // temporaries to save total_in and total_out
        
        			// set up
        			if (!z || !z.istate)
        				return Z_STREAM_ERROR;
        			if (z.istate.mode != BAD) {
        				z.istate.mode = BAD;
        				z.istate.marker = 0;
        			}
        			if ((n = z.avail_in) === 0)
        				return Z_BUF_ERROR;
        			p = z.next_in_index;
        			m = z.istate.marker;
        
        			// search
        			while (n !== 0 && m < 4) {
        				if (z.read_byte(p) == mark[m]) {
        					m++;
        				} else if (z.read_byte(p) !== 0) {
        					m = 0;
        				} else {
        					m = 4 - m;
        				}
        				p++;
        				n--;
        			}
        
        			// restore
        			z.total_in += p - z.next_in_index;
        			z.next_in_index = p;
        			z.avail_in = n;
        			z.istate.marker = m;
        
        			// return no joy or set up to restart on a new block
        			if (m != 4) {
        				return Z_DATA_ERROR;
        			}
        			r = z.total_in;
        			w = z.total_out;
        			inflateReset(z);
        			z.total_in = r;
        			z.total_out = w;
        			z.istate.mode = BLOCKS;
        			return Z_OK;
        		};
        
        		// Returns true if inflate is currently at the end of a block generated
        		// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
        		// implementation to provide an additional safety check. PPP uses
        		// Z_SYNC_FLUSH
        		// but removes the length bytes of the resulting empty stored block. When
        		// decompressing, PPP checks that at the end of input packet, inflate is
        		// waiting for these length bytes.
        		that.inflateSyncPoint = function(z) {
        			if (!z || !z.istate || !z.istate.blocks)
        				return Z_STREAM_ERROR;
        			return z.istate.blocks.sync_point();
        		};
        	}
        
        	// ZStream
        
        	function ZStream() {
        	}
        
        	ZStream.prototype = {
        		inflateInit : function(bits) {
        			var that = this;
        			that.istate = new Inflate();
        			if (!bits)
        				bits = MAX_BITS;
        			return that.istate.inflateInit(that, bits);
        		},
        
        		inflate : function(f) {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflate(that, f);
        		},
        
        		inflateEnd : function() {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			var ret = that.istate.inflateEnd(that);
        			that.istate = null;
        			return ret;
        		},
        
        		inflateSync : function() {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflateSync(that);
        		},
        		inflateSetDictionary : function(dictionary, dictLength) {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflateSetDictionary(that, dictionary, dictLength);
        		},
        		read_byte : function(start) {
        			var that = this;
        			return that.next_in.subarray(start, start + 1)[0];
        		},
        		read_buf : function(start, size) {
        			var that = this;
        			return that.next_in.subarray(start, start + size);
        		}
        	};
        
        	// Inflater
        
        	function Inflater() {
        		var that = this;
        		var z = new ZStream();
        		var bufsize = 512;
        		var flush = Z_NO_FLUSH;
        		var buf = new Uint8Array(bufsize);
        		var nomoreinput = false;
        
        		z.inflateInit();
        		z.next_out = buf;
        
        		that.append = function(data, onprogress) {
        			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
        			if (data.length === 0)
        				return;
        			z.next_in_index = 0;
        			z.next_in = data;
        			z.avail_in = data.length;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				if ((z.avail_in === 0) && (!nomoreinput)) { // if buffer is empty and more input is available, refill it
        					z.next_in_index = 0;
        					nomoreinput = true;
        				}
        				err = z.inflate(flush);
        				if (nomoreinput && (err === Z_BUF_ERROR)) {
        					if (z.avail_in !== 0)
        						throw new Error("inflating: bad input");
        				} else if (err !== Z_OK && err !== Z_STREAM_END)
        					throw new Error("inflating: " + z.msg);
        				if ((nomoreinput || err === Z_STREAM_END) && (z.avail_in === data.length))
        					throw new Error("inflating: bad input");
        				if (z.next_out_index)
        					if (z.next_out_index === bufsize)
        						buffers.push(new Uint8Array(buf));
        					else
        						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
        					onprogress(z.next_in_index);
        					lastIndex = z.next_in_index;
        				}
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        		that.flush = function() {
        			z.inflateEnd();
        		};
        	}
        
        	// 'zip' may not be defined in z-worker and some tests
        	var env = global.zip || global;
        	env.Inflater = env._jzlib_Inflater = Inflater;
        })(this);
      • zip.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        (function(obj) {
        	"use strict";
        
        	var ERR_BAD_FORMAT = "File format is not recognized.";
        	var ERR_CRC = "CRC failed.";
        	var ERR_ENCRYPTED = "File contains encrypted entry.";
        	var ERR_ZIP64 = "File is using Zip64 (4gb+ file size).";
        	var ERR_READ = "Error while reading zip file.";
        	var ERR_WRITE = "Error while writing zip file.";
        	var ERR_WRITE_DATA = "Error while writing file data.";
        	var ERR_READ_DATA = "Error while reading file data.";
        	var ERR_DUPLICATED_NAME = "File already exists.";
        	var CHUNK_SIZE = 512 * 1024;
        	
        	var TEXT_PLAIN = "text/plain";
        
        	var appendABViewSupported;
        	try {
        		appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
        	} catch (e) {
        	}
        
        	function Crc32() {
        		this.crc = -1;
        	}
        	Crc32.prototype.append = function append(data) {
        		var crc = this.crc | 0, table = this.table;
        		for (var offset = 0, len = data.length | 0; offset < len; offset++)
        			crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
        		this.crc = crc;
        	};
        	Crc32.prototype.get = function get() {
        		return ~this.crc;
        	};
        	Crc32.prototype.table = (function() {
        		var i, j, t, table = []; // Uint32Array is actually slower than []
        		for (i = 0; i < 256; i++) {
        			t = i;
        			for (j = 0; j < 8; j++)
        				if (t & 1)
        					t = (t >>> 1) ^ 0xEDB88320;
        				else
        					t = t >>> 1;
        			table[i] = t;
        		}
        		return table;
        	})();
        	
        	// "no-op" codec
        	function NOOP() {}
        	NOOP.prototype.append = function append(bytes, onprogress) {
        		return bytes;
        	};
        	NOOP.prototype.flush = function flush() {};
        
        	function blobSlice(blob, index, length) {
        		if (index < 0 || length < 0 || index + length > blob.size)
        			throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);
        		if (blob.slice)
        			return blob.slice(index, index + length);
        		else if (blob.webkitSlice)
        			return blob.webkitSlice(index, index + length);
        		else if (blob.mozSlice)
        			return blob.mozSlice(index, index + length);
        		else if (blob.msSlice)
        			return blob.msSlice(index, index + length);
        	}
        
        	function getDataHelper(byteLength, bytes) {
        		var dataBuffer, dataArray;
        		dataBuffer = new ArrayBuffer(byteLength);
        		dataArray = new Uint8Array(dataBuffer);
        		if (bytes)
        			dataArray.set(bytes, 0);
        		return {
        			buffer : dataBuffer,
        			array : dataArray,
        			view : new DataView(dataBuffer)
        		};
        	}
        
        	// Readers
        	function Reader() {
        	}
        
        	function TextReader(text) {
        		var that = this, blobReader;
        
        		function init(callback, onerror) {
        			var blob = new Blob([ text ], {
        				type : TEXT_PLAIN
        			});
        			blobReader = new BlobReader(blob);
        			blobReader.init(function() {
        				that.size = blobReader.size;
        				callback();
        			}, onerror);
        		}
        
        		function readUint8Array(index, length, callback, onerror) {
        			blobReader.readUint8Array(index, length, callback, onerror);
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	TextReader.prototype = new Reader();
        	TextReader.prototype.constructor = TextReader;
        
        	function Data64URIReader(dataURI) {
        		var that = this, dataStart;
        
        		function init(callback) {
        			var dataEnd = dataURI.length;
        			while (dataURI.charAt(dataEnd - 1) == "=")
        				dataEnd--;
        			dataStart = dataURI.indexOf(",") + 1;
        			that.size = Math.floor((dataEnd - dataStart) * 0.75);
        			callback();
        		}
        
        		function readUint8Array(index, length, callback) {
        			var i, data = getDataHelper(length);
        			var start = Math.floor(index / 3) * 4;
        			var end = Math.ceil((index + length) / 3) * 4;
        			var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));
        			var delta = index - Math.floor(start / 4) * 3;
        			for (i = delta; i < delta + length; i++)
        				data.array[i - delta] = bytes.charCodeAt(i);
        			callback(data.array);
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	Data64URIReader.prototype = new Reader();
        	Data64URIReader.prototype.constructor = Data64URIReader;
        
        	function BlobReader(blob) {
        		var that = this;
        
        		function init(callback) {
        			that.size = blob.size;
        			callback();
        		}
        
        		function readUint8Array(index, length, callback, onerror) {
        			var reader = new FileReader();
        			reader.onload = function(e) {
        				callback(new Uint8Array(e.target.result));
        			};
        			reader.onerror = onerror;
        			try {
        				reader.readAsArrayBuffer(blobSlice(blob, index, length));
        			} catch (e) {
        				onerror(e);
        			}
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	BlobReader.prototype = new Reader();
        	BlobReader.prototype.constructor = BlobReader;
        
        	// Writers
        
        	function Writer() {
        	}
        	Writer.prototype.getData = function(callback) {
        		callback(this.data);
        	};
        
        	function TextWriter(encoding) {
        		var that = this, blob;
        
        		function init(callback) {
        			blob = new Blob([], {
        				type : TEXT_PLAIN
        			});
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
        				type : TEXT_PLAIN
        			});
        			callback();
        		}
        
        		function getData(callback, onerror) {
        			var reader = new FileReader();
        			reader.onload = function(e) {
        				callback(e.target.result);
        			};
        			reader.onerror = onerror;
        			reader.readAsText(blob, encoding);
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	TextWriter.prototype = new Writer();
        	TextWriter.prototype.constructor = TextWriter;
        
        	function Data64URIWriter(contentType) {
        		var that = this, data = "", pending = "";
        
        		function init(callback) {
        			data += "data:" + (contentType || "") + ";base64,";
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			var i, delta = pending.length, dataString = pending;
        			pending = "";
        			for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
        				dataString += String.fromCharCode(array[i]);
        			for (; i < array.length; i++)
        				pending += String.fromCharCode(array[i]);
        			if (dataString.length > 2)
        				data += obj.btoa(dataString);
        			else
        				pending = dataString;
        			callback();
        		}
        
        		function getData(callback) {
        			callback(data + obj.btoa(pending));
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	Data64URIWriter.prototype = new Writer();
        	Data64URIWriter.prototype.constructor = Data64URIWriter;
        
        	function BlobWriter(contentType) {
        		var blob, that = this;
        
        		function init(callback) {
        			blob = new Blob([], {
        				type : contentType
        			});
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
        				type : contentType
        			});
        			callback();
        		}
        
        		function getData(callback) {
        			callback(blob);
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	BlobWriter.prototype = new Writer();
        	BlobWriter.prototype.constructor = BlobWriter;
        
        	/** 
        	 * inflate/deflate core functions
        	 * @param worker {Worker} web worker for the task.
        	 * @param initialMessage {Object} initial message to be sent to the worker. should contain
        	 *   sn(serial number for distinguishing multiple tasks sent to the worker), and codecClass.
        	 *   This function may add more properties before sending.
        	 */
        	function launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror) {
        		var chunkIndex = 0, index, outputSize, sn = initialMessage.sn, crc;
        
        		function onflush() {
        			worker.removeEventListener('message', onmessage, false);
        			onend(outputSize, crc);
        		}
        
        		function onmessage(event) {
        			var message = event.data, data = message.data, err = message.error;
        			if (err) {
        				err.toString = function () { return 'Error: ' + this.message; };
        				onreaderror(err);
        				return;
        			}
        			if (message.sn !== sn)
        				return;
        			if (typeof message.codecTime === 'number')
        				worker.codecTime += message.codecTime; // should be before onflush()
        			if (typeof message.crcTime === 'number')
        				worker.crcTime += message.crcTime;
        
        			switch (message.type) {
        				case 'append':
        					if (data) {
        						outputSize += data.length;
        						writer.writeUint8Array(data, function() {
        							step();
        						}, onwriteerror);
        					} else
        						step();
        					break;
        				case 'flush':
        					crc = message.crc;
        					if (data) {
        						outputSize += data.length;
        						writer.writeUint8Array(data, function() {
        							onflush();
        						}, onwriteerror);
        					} else
        						onflush();
        					break;
        				case 'progress':
        					if (onprogress)
        						onprogress(index + message.loaded, size);
        					break;
        				case 'importScripts': //no need to handle here
        				case 'newTask':
        				case 'echo':
        					break;
        				default:
        					console.warn('zip.js:launchWorkerProcess: unknown message: ', message);
        			}
        		}
        
        		function step() {
        			index = chunkIndex * CHUNK_SIZE;
        			if (index < size) {
        				reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {
        					if (onprogress)
        						onprogress(index, size);
        					var msg = index === 0 ? initialMessage : {sn : sn};
        					msg.type = 'append';
        					msg.data = array;
        					worker.postMessage(msg, [array.buffer]);
        					chunkIndex++;
        				}, onreaderror);
        			} else {
        				worker.postMessage({
        					sn: sn,
        					type: 'flush'
        				});
        			}
        		}
        
        		outputSize = 0;
        		worker.addEventListener('message', onmessage, false);
        		step();
        	}
        
        	function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {
        		var chunkIndex = 0, index, outputSize = 0,
        			crcInput = crcType === 'input',
        			crcOutput = crcType === 'output',
        			crc = new Crc32();
        		function step() {
        			var outputData;
        			index = chunkIndex * CHUNK_SIZE;
        			if (index < size)
        				reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {
        					var outputData;
        					try {
        						outputData = process.append(inputData, function(loaded) {
        							if (onprogress)
        								onprogress(index + loaded, size);
        						});
        					} catch (e) {
        						onreaderror(e);
        						return;
        					}
        					if (outputData) {
        						outputSize += outputData.length;
        						writer.writeUint8Array(outputData, function() {
        							chunkIndex++;
        							setTimeout(step, 1);
        						}, onwriteerror);
        						if (crcOutput)
        							crc.append(outputData);
        					} else {
        						chunkIndex++;
        						setTimeout(step, 1);
        					}
        					if (crcInput)
        						crc.append(inputData);
        					if (onprogress)
        						onprogress(index, size);
        				}, onreaderror);
        			else {
        				try {
        					outputData = process.flush();
        				} catch (e) {
        					onreaderror(e);
        					return;
        				}
        				if (outputData) {
        					if (crcOutput)
        						crc.append(outputData);
        					outputSize += outputData.length;
        					writer.writeUint8Array(outputData, function() {
        						onend(outputSize, crc.get());
        					}, onwriteerror);
        				} else
        					onend(outputSize, crc.get());
        			}
        		}
        
        		step();
        	}
        
        	function inflate(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = computeCrc32 ? 'output' : 'none';
        		if (obj.zip.useWebWorkers) {
        			var initialMessage = {
        				sn: sn,
        				codecClass: 'Inflater',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	function deflate(worker, sn, reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = 'input';
        		if (obj.zip.useWebWorkers) {
        			var initialMessage = {
        				sn: sn,
        				options: {level: level},
        				codecClass: 'Deflater',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, 0, reader.size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = 'input';
        		if (obj.zip.useWebWorkers && computeCrc32) {
        			var initialMessage = {
        				sn: sn,
        				codecClass: 'NOOP',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	// ZipReader
        
        	function decodeASCII(str) {
        		var i, out = "", charCode, extendedASCII = [ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB',
        				'\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5', '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9',
        				'\u00FF', '\u00D6', '\u00DC', '\u00F8', '\u00A3', '\u00D8', '\u00D7', '\u0192', '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1',
        				'\u00AA', '\u00BA', '\u00BF', '\u00AE', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB', '_', '_', '_', '\u00A6', '\u00A6',
        				'\u00C1', '\u00C2', '\u00C0', '\u00A9', '\u00A6', '\u00A6', '+', '+', '\u00A2', '\u00A5', '+', '+', '-', '-', '+', '-', '+', '\u00E3',
        				'\u00C3', '+', '+', '-', '-', '\u00A6', '-', '+', '\u00A4', '\u00F0', '\u00D0', '\u00CA', '\u00CB', '\u00C8', 'i', '\u00CD', '\u00CE',
        				'\u00CF', '+', '+', '_', '_', '\u00A6', '\u00CC', '_', '\u00D3', '\u00DF', '\u00D4', '\u00D2', '\u00F5', '\u00D5', '\u00B5', '\u00FE',
        				'\u00DE', '\u00DA', '\u00DB', '\u00D9', '\u00FD', '\u00DD', '\u00AF', '\u00B4', '\u00AD', '\u00B1', '_', '\u00BE', '\u00B6', '\u00A7',
        				'\u00F7', '\u00B8', '\u00B0', '\u00A8', '\u00B7', '\u00B9', '\u00B3', '\u00B2', '_', ' ' ];
        		for (i = 0; i < str.length; i++) {
        			charCode = str.charCodeAt(i) & 0xFF;
        			if (charCode > 127)
        				out += extendedASCII[charCode - 128];
        			else
        				out += String.fromCharCode(charCode);
        		}
        		return out;
        	}
        
        	function decodeUTF8(string) {
        		return decodeURIComponent(escape(string));
        	}
        
        	function getString(bytes) {
        		var i, str = "";
        		for (i = 0; i < bytes.length; i++)
        			str += String.fromCharCode(bytes[i]);
        		return str;
        	}
        
        	function getDate(timeRaw) {
        		var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
        		try {
        			return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,
        					(time & 0x001F) * 2, 0);
        		} catch (e) {
        		}
        	}
        
        	function readCommonHeader(entry, data, index, centralDirectory, onerror) {
        		entry.version = data.view.getUint16(index, true);
        		entry.bitFlag = data.view.getUint16(index + 2, true);
        		entry.compressionMethod = data.view.getUint16(index + 4, true);
        		entry.lastModDateRaw = data.view.getUint32(index + 6, true);
        		entry.lastModDate = getDate(entry.lastModDateRaw);
        		if ((entry.bitFlag & 0x01) === 0x01) {
        			onerror(ERR_ENCRYPTED);
        			return;
        		}
        		if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {
        			entry.crc32 = data.view.getUint32(index + 10, true);
        			entry.compressedSize = data.view.getUint32(index + 14, true);
        			entry.uncompressedSize = data.view.getUint32(index + 18, true);
        		}
        		if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {
        			onerror(ERR_ZIP64);
        			return;
        		}
        		entry.filenameLength = data.view.getUint16(index + 22, true);
        		entry.extraFieldLength = data.view.getUint16(index + 24, true);
        	}
        
        	function createZipReader(reader, callback, onerror) {
        		var inflateSN = 0;
        
        		function Entry() {
        		}
        
        		Entry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {
        			var that = this;
        
        			function testCrc32(crc32) {
        				var dataCrc32 = getDataHelper(4);
        				dataCrc32.view.setUint32(0, crc32);
        				return that.crc32 == dataCrc32.view.getUint32(0);
        			}
        
        			function getWriterData(uncompressedSize, crc32) {
        				if (checkCrc32 && !testCrc32(crc32))
        					onerror(ERR_CRC);
        				else
        					writer.getData(function(data) {
        						onend(data);
        					});
        			}
        
        			function onreaderror(err) {
        				onerror(err || ERR_READ_DATA);
        			}
        
        			function onwriteerror(err) {
        				onerror(err || ERR_WRITE_DATA);
        			}
        
        			reader.readUint8Array(that.offset, 30, function(bytes) {
        				var data = getDataHelper(bytes.length, bytes), dataOffset;
        				if (data.view.getUint32(0) != 0x504b0304) {
        					onerror(ERR_BAD_FORMAT);
        					return;
        				}
        				readCommonHeader(that, data, 4, false, onerror);
        				dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
        				writer.init(function() {
        					if (that.compressionMethod === 0)
        						copy(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
        					else
        						inflate(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
        				}, onwriteerror);
        			}, onreaderror);
        		};
        
        		function seekEOCDR(eocdrCallback) {
        			// "End of central directory record" is the last part of a zip archive, and is at least 22 bytes long.
        			// Zip file comment is the last part of EOCDR and has max length of 64KB,
        			// so we only have to search the last 64K + 22 bytes of a archive for EOCDR signature (0x06054b50).
        			var EOCDR_MIN = 22;
        			if (reader.size < EOCDR_MIN) {
        				onerror(ERR_BAD_FORMAT);
        				return;
        			}
        			var ZIP_COMMENT_MAX = 256 * 256, EOCDR_MAX = EOCDR_MIN + ZIP_COMMENT_MAX;
        
        			// In most cases, the EOCDR is EOCDR_MIN bytes long
        			doSeek(EOCDR_MIN, function() {
        				// If not found, try within EOCDR_MAX bytes
        				doSeek(Math.min(EOCDR_MAX, reader.size), function() {
        					onerror(ERR_BAD_FORMAT);
        				});
        			});
        
        			// seek last length bytes of file for EOCDR
        			function doSeek(length, eocdrNotFoundCallback) {
        				reader.readUint8Array(reader.size - length, length, function(bytes) {
        					for (var i = bytes.length - EOCDR_MIN; i >= 0; i--) {
        						if (bytes[i] === 0x50 && bytes[i + 1] === 0x4b && bytes[i + 2] === 0x05 && bytes[i + 3] === 0x06) {
        							eocdrCallback(new DataView(bytes.buffer, i, EOCDR_MIN));
        							return;
        						}
        					}
        					eocdrNotFoundCallback();
        				}, function() {
        					onerror(ERR_READ);
        				});
        			}
        		}
        
        		var zipReader = {
        			getEntries : function(callback) {
        				var worker = this._worker;
        				// look for End of central directory record
        				seekEOCDR(function(dataView) {
        					var datalength, fileslength;
        					datalength = dataView.getUint32(16, true);
        					fileslength = dataView.getUint16(8, true);
        					if (datalength < 0 || datalength >= reader.size) {
        						onerror(ERR_BAD_FORMAT);
        						return;
        					}
        					reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
        						var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);
        						for (i = 0; i < fileslength; i++) {
        							entry = new Entry();
        							entry._worker = worker;
        							if (data.view.getUint32(index) != 0x504b0102) {
        								onerror(ERR_BAD_FORMAT);
        								return;
        							}
        							readCommonHeader(entry, data, index + 6, true, onerror);
        							entry.commentLength = data.view.getUint16(index + 32, true);
        							entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
        							entry.offset = data.view.getUint32(index + 42, true);
        							filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));
        							entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);
        							if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == "/")
        								entry.directory = true;
        							comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46
        									+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));
        							entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);
        							entries.push(entry);
        							index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;
        						}
        						callback(entries);
        					}, function() {
        						onerror(ERR_READ);
        					});
        				});
        			},
        			close : function(callback) {
        				if (this._worker) {
        					this._worker.terminate();
        					this._worker = null;
        				}
        				if (callback)
        					callback();
        			},
        			_worker: null
        		};
        
        		if (!obj.zip.useWebWorkers)
        			callback(zipReader);
        		else {
        			createWorker('inflater',
        				function(worker) {
        					zipReader._worker = worker;
        					callback(zipReader);
        				},
        				function(err) {
        					onerror(err);
        				}
        			);
        		}
        	}
        
        	// ZipWriter
        
        	function encodeUTF8(string) {
        		return unescape(encodeURIComponent(string));
        	}
        
        	function getBytes(str) {
        		var i, array = [];
        		for (i = 0; i < str.length; i++)
        			array.push(str.charCodeAt(i));
        		return array;
        	}
        
        	function createZipWriter(writer, callback, onerror, dontDeflate) {
        		var files = {}, filenames = [], datalength = 0;
        		var deflateSN = 0;
        
        		function onwriteerror(err) {
        			onerror(err || ERR_WRITE);
        		}
        
        		function onreaderror(err) {
        			onerror(err || ERR_READ_DATA);
        		}
        
        		var zipWriter = {
        			add : function(name, reader, onend, onprogress, options) {
        				var header, filename, date;
        				var worker = this._worker;
        
        				function writeHeader(callback) {
        					var data;
        					date = options.lastModDate || new Date();
        					header = getDataHelper(26);
        					files[name] = {
        						headerArray : header.array,
        						directory : options.directory,
        						filename : filename,
        						offset : datalength,
        						comment : getBytes(encodeUTF8(options.comment || ""))
        					};
        					header.view.setUint32(0, 0x14000808);
        					if (options.version)
        						header.view.setUint8(0, options.version);
        					if (!dontDeflate && options.level !== 0 && !options.directory)
        						header.view.setUint16(4, 0x0800);
        					header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
        					header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
        					header.view.setUint16(22, filename.length, true);
        					data = getDataHelper(30 + filename.length);
        					data.view.setUint32(0, 0x504b0304);
        					data.array.set(header.array, 4);
        					data.array.set(filename, 30);
        					datalength += data.array.length;
        					writer.writeUint8Array(data.array, callback, onwriteerror);
        				}
        
        				function writeFooter(compressedLength, crc32) {
        					var footer = getDataHelper(16);
        					datalength += compressedLength || 0;
        					footer.view.setUint32(0, 0x504b0708);
        					if (typeof crc32 != "undefined") {
        						header.view.setUint32(10, crc32, true);
        						footer.view.setUint32(4, crc32, true);
        					}
        					if (reader) {
        						footer.view.setUint32(8, compressedLength, true);
        						header.view.setUint32(14, compressedLength, true);
        						footer.view.setUint32(12, reader.size, true);
        						header.view.setUint32(18, reader.size, true);
        					}
        					writer.writeUint8Array(footer.array, function() {
        						datalength += 16;
        						onend();
        					}, onwriteerror);
        				}
        
        				function writeFile() {
        					options = options || {};
        					name = name.trim();
        					if (options.directory && name.charAt(name.length - 1) != "/")
        						name += "/";
        					if (files.hasOwnProperty(name)) {
        						onerror(ERR_DUPLICATED_NAME);
        						return;
        					}
        					filename = getBytes(encodeUTF8(name));
        					filenames.push(name);
        					writeHeader(function() {
        						if (reader)
        							if (dontDeflate || options.level === 0)
        								copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
        							else
        								deflate(worker, deflateSN++, reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
        						else
        							writeFooter();
        					}, onwriteerror);
        				}
        
        				if (reader)
        					reader.init(writeFile, onreaderror);
        				else
        					writeFile();
        			},
        			close : function(callback) {
        				if (this._worker) {
        					this._worker.terminate();
        					this._worker = null;
        				}
        
        				var data, length = 0, index = 0, indexFilename, file;
        				for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
        					file = files[filenames[indexFilename]];
        					length += 46 + file.filename.length + file.comment.length;
        				}
        				data = getDataHelper(length + 22);
        				for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
        					file = files[filenames[indexFilename]];
        					data.view.setUint32(index, 0x504b0102);
        					data.view.setUint16(index + 4, 0x1400);
        					data.array.set(file.headerArray, index + 6);
        					data.view.setUint16(index + 32, file.comment.length, true);
        					if (file.directory)
        						data.view.setUint8(index + 38, 0x10);
        					data.view.setUint32(index + 42, file.offset, true);
        					data.array.set(file.filename, index + 46);
        					data.array.set(file.comment, index + 46 + file.filename.length);
        					index += 46 + file.filename.length + file.comment.length;
        				}
        				data.view.setUint32(index, 0x504b0506);
        				data.view.setUint16(index + 8, filenames.length, true);
        				data.view.setUint16(index + 10, filenames.length, true);
        				data.view.setUint32(index + 12, length, true);
        				data.view.setUint32(index + 16, datalength, true);
        				writer.writeUint8Array(data.array, function() {
        					writer.getData(callback);
        				}, onwriteerror);
        			},
        			_worker: null
        		};
        
        		if (!obj.zip.useWebWorkers)
        			callback(zipWriter);
        		else {
        			createWorker('deflater',
        				function(worker) {
        					zipWriter._worker = worker;
        					callback(zipWriter);
        				},
        				function(err) {
        					onerror(err);
        				}
        			);
        		}
        	}
        
        	function resolveURLs(urls) {
        		var a = document.createElement('a');
        		return urls.map(function(url) {
        			a.href = url;
        			return a.href;
        		});
        	}
        
        	var DEFAULT_WORKER_SCRIPTS = {
        		deflater: ['z-worker.js', 'deflate.js'],
        		inflater: ['z-worker.js', 'inflate.js']
        	};
        	function createWorker(type, callback, onerror) {
        		if (obj.zip.workerScripts !== null && obj.zip.workerScriptsPath !== null) {
        			onerror(new Error('Either zip.workerScripts or zip.workerScriptsPath may be set, not both.'));
        			return;
        		}
        		var scripts;
        		if (obj.zip.workerScripts) {
        			scripts = obj.zip.workerScripts[type];
        			if (!Array.isArray(scripts)) {
        				onerror(new Error('zip.workerScripts.' + type + ' is not an array!'));
        				return;
        			}
        			scripts = resolveURLs(scripts);
        		} else {
        			scripts = DEFAULT_WORKER_SCRIPTS[type].slice(0);
        			scripts[0] = (obj.zip.workerScriptsPath || '') + scripts[0];
        		}
        		var worker = new Worker(scripts[0]);
        		// record total consumed time by inflater/deflater/crc32 in this worker
        		worker.codecTime = worker.crcTime = 0;
        		worker.postMessage({ type: 'importScripts', scripts: scripts.slice(1) });
        		worker.addEventListener('message', onmessage);
        		function onmessage(ev) {
        			var msg = ev.data;
        			if (msg.error) {
        				worker.terminate(); // should before onerror(), because onerror() may throw.
        				onerror(msg.error);
        				return;
        			}
        			if (msg.type === 'importScripts') {
        				worker.removeEventListener('message', onmessage);
        				worker.removeEventListener('error', errorHandler);
        				callback(worker);
        			}
        		}
        		// catch entry script loading error and other unhandled errors
        		worker.addEventListener('error', errorHandler);
        		function errorHandler(err) {
        			worker.terminate();
        			onerror(err);
        		}
        	}
        
        	function onerror_default(error) {
        		console.error(error);
        	}
        	obj.zip = {
        		Reader : Reader,
        		Writer : Writer,
        		BlobReader : BlobReader,
        		Data64URIReader : Data64URIReader,
        		TextReader : TextReader,
        		BlobWriter : BlobWriter,
        		Data64URIWriter : Data64URIWriter,
        		TextWriter : TextWriter,
        		createReader : function(reader, callback, onerror) {
        			onerror = onerror || onerror_default;
        
        			reader.init(function() {
        				createZipReader(reader, callback, onerror);
        			}, onerror);
        		},
        		createWriter : function(writer, callback, onerror, dontDeflate) {
        			onerror = onerror || onerror_default;
        			dontDeflate = !!dontDeflate;
        
        			writer.init(function() {
        				createZipWriter(writer, callback, onerror, dontDeflate);
        			}, onerror);
        		},
        		useWebWorkers : true,
        		/**
        		 * Directory containing the default worker scripts (z-worker.js, deflate.js, and inflate.js), relative to current base url.
        		 * E.g.: zip.workerScripts = './';
        		 */
        		workerScriptsPath : null,
        		/**
        		 * Advanced option to control which scripts are loaded in the Web worker. If this option is specified, then workerScriptsPath must not be set.
        		 * workerScripts.deflater/workerScripts.inflater should be arrays of urls to scripts for deflater/inflater, respectively.
        		 * Scripts in the array are executed in order, and the first one should be z-worker.js, which is used to start the worker.
        		 * All urls are relative to current base url.
        		 * E.g.:
        		 * zip.workerScripts = {
        		 *   deflater: ['z-worker.js', 'deflate.js'],
        		 *   inflater: ['z-worker.js', 'inflate.js']
        		 * };
        		 */
        		workerScripts : null,
        	};
        
        })(this);
  • nodeAPI
    • modules
      • fs.ts
        module portabled.nodeAPI.modules.fs {
        
          export class fsModule {
        
            constructor(private _drive: persistence.Drive) {
            }
        
            rename: (oldPath: string, newPath: string, callback: (error: Error) => void) => void;
            renameSync(oldPath: string, newPath: string) {
              var content = this._drive.read(oldPath);
              if (content === null) throw new Error('File cannot be found.');
        
              this._drive.timestamp = dateNow();
              this._drive.write(newPath, content);
              this._drive.write(oldPath, null);
            }
        
          	ftruncate: (fd: any, len: number, callback: (error: Error) => void) => void;
          	ftruncateSync(fd: any, len: number) {
              var content = this._drive.read(fd);
              if (content === null) throw new Error('File cannot be found.');
        
              this._drive.timestamp = dateNow();
              this._drive.write(fd, content.slice(0, len));
            }
          }
        
        }
  • persistence
    • Drive.ts
      module portabled.persistence {
      
        export interface Drive {
      
          timestamp: number;
      
          files(): string[];
      
          read(file: string): string;
      
          write(file: string, content: string);
      
        }
      
        export module Drive {
      
          export interface Shadow {
      
            timestamp: number;
      
            write(file: string, content: string): void;
      
          }
      
          export interface Optional {
      
            detect(uniqueKey: string, callback: (detached: Detached) => void): void;
      
          }
      
          export interface Detached {
      
            timestamp: number;
      
            applyTo(mainDrive: Drive, callback: Detached.CallbackWithShadow): void;
      
            purge(callback: Detached.CallbackWithShadow): void;
      
          }
      
          export module Detached {
            export interface CallbackWithShadow {
      
              (loaded: Shadow): void;
              progress?: (current: number, total: number) => void;
      
            }
          }
      
        }
      
      }
    • indexedDB.ts
      module portabled {
      
        function getIndexedDB() {
          try {
          	return typeof indexedDB === 'undefined' || typeof indexedDB.open !== 'function' ? null : indexedDB;
          }
          catch (error) {
            return null;
          }
        }
      
        export module persistence.indexedDB {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
            try {
              detectCore(uniqueKey, callback);
            }
            catch (error) {
              callback(null);
            }
          }
      
          function detectCore(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
      
            var indexedDBInstance = getIndexedDB();
            if (!indexedDBInstance) {
              callback(null);
              return;
            }
      
            var dbName = uniqueKey || 'portabled';
      
            var openRequest = indexedDBInstance.open(dbName, 1);
            openRequest.onerror = (errorEvent) => callback(null);
      
            openRequest.onupgradeneeded = createDBAndTables;
      
            openRequest.onsuccess = (event) => {
              var db: IDBDatabase = openRequest.result;
      
              try {
                var transaction = db.transaction(['files', 'metadata']);
                // files mentioned here, but not really used to detect
                // broken multi-store transaction implementation in Safari
      
                transaction.onerror = (errorEvent) => callback(null);
              
                var metadataStore = transaction.objectStore('metadata');
                var filesStore = transaction.objectStore('files');
                var editedUTCRequest = metadataStore.get('editedUTC');
              }
              catch (getStoreError) {
                callback(null);
                return;
              }
      
              if (!editedUTCRequest) {
                callback(null);
                return;
              }
      
              editedUTCRequest.onerror = (errorEvent) => {
                var detached = new IndexedDBDetached(db, null);
                callback(detached);
              };
      
              editedUTCRequest.onsuccess = (event) => {
                var result: MetadataData = editedUTCRequest.result;
                var detached = new IndexedDBDetached(db, result && typeof result.value === 'number' ? result.value : null);
                callback(detached);
              };
      
            };
            
            function createDBAndTables() {
              var db: IDBDatabase = openRequest.result;
              var filesStore = db.createObjectStore('files', { keyPath: 'path' });
              var metadataStore = db.createObjectStore('metadata', { keyPath: 'property' });
            }
          }
      
          class IndexedDBDetached implements Drive.Detached {
      
            constructor(
              private _db: IDBDatabase,
              public timestamp: number) {
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
              var metadataStore = transaction.objectStore('metadata');
              var filesStore = transaction.objectStore('files');
      
              var countRequest = filesStore.count();
              countRequest.onerror = (errorEvent) => {
                console.error('Could not count files store.');
                callback(null);
              };
      
              countRequest.onsuccess = (event) => {
      
                var storeCount: number = countRequest.result;
      
                var cursorRequest = filesStore.openCursor();
                cursorRequest.onerror = (errorEvent) => callback(null);
      
                // to cleanup any files which content is the same on the main drive
                var deleteList: string[] = [];
                var anyLeft = false;
      
                var processedCount = 0;
      
                cursorRequest.onsuccess = (event) => {
                  var cursor: IDBCursor = cursorRequest.result;
      
                  if (!cursor) {
      
                    // cleaning up files whose content is duplicating the main drive
                    if (anyLeft) {
                      for (var i = 0; i < deleteList.length; i++) {
                        filesStore['delete'](deleteList[i]);
                      }
                    }
                    else {
                      filesStore.clear();
                      metadataStore.clear();
                    }
      
                    callback(new IndexedDBShadow(this._db, this.timestamp));
                    return;
                  }
      
                  if (callback.progress)
                    callback.progress(processedCount, storeCount);
                  processedCount++;
      
                  var result: FileData = (<any>cursor).value;
                  if (result && result.path) {
      
                    var existingContent = mainDrive.read(result.path);
                    if (existingContent === result.content) {
                      deleteList.push(result.path);
                    }
                    else {
                      mainDrive.timestamp = this.timestamp;
                      mainDrive.write(result.path, result.content);
                      anyLeft = true;
                    }
                  }
      
                  cursor['continue']();
                }; // cursorRequest.onsuccess
      
              }; // countRequest.onsuccess
      
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
      
              var filesStore = transaction.objectStore('files');
              filesStore.clear();
      
              var metadataStore = transaction.objectStore('metadata');
              metadataStore.clear();
      
              callback(new IndexedDBShadow(this._db, -1));
            }
      
          }
      
          class IndexedDBShadow implements Drive.Shadow {
      
            constructor(private _db: IDBDatabase, public timestamp: number) {
            }
      
            write(file: string, content: string) {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
              var filesStore = transaction.objectStore('files');
              var metadataStore = transaction.objectStore('metadata');
      
              // no file deletion here: we need to keep account of deletions too!
              var fileData: FileData = {
                path: file,
                content: content,
                state: null
              };
      
              var putFile = filesStore.put(fileData);
      
              var md: MetadataData = {
                property: 'editedUTC',
                value: Date.now()
              };
      
              metadataStore.put(md);
      
            }
          }
      
      
          interface FileData {
            path: string;
            content: string;
            state: string;
          }
      
          interface MetadataData {
            property: string;
            value: any;
          }
      
      
        }
      
      }
    • localStorage.ts
      module portabled {
        
        function getLocalStorage() {
          return typeof localStorage === 'undefined' || typeof localStorage.length !== 'number' ? null : localStorage;
        }
      
        // is it OK&
        export module persistence.localStorage {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
            var localStorageInstance = getLocalStorage();
            if (!localStorageInstance) {
              callback(null);
              return;
            }
      
            var access = new LocalStorageAccess(localStorageInstance, uniqueKey);
            var dt = new LocalStorageDetached(access);
            callback(dt);
          }
          
          class LocalStorageAccess {
            private _cache: { [key: string]: string; } = {};
      
            constructor(private _localStorage: Storage, private _prefix: string) {
            }
      
            get (key: string): string {
              var k = this._expandKey(key);
              var r = this._localStorage.getItem(k);
              return r;
            }
          
          	set(key: string, value: string): void {
              var k = this._expandKey(key);
              return this._localStorage.setItem(k, value);
            }
      
            remove(key: string): void {
              var k = this._expandKey(key);
              return this._localStorage.removeItem(k);
            }
      
            keys(): string[] {
              var result: string[] = [];
              var len = this._localStorage.length;
              for (var i = 0; i < len; i++) {
                var str = this._localStorage.key(i);
                if (str.length > this._prefix.length && str.slice(0, this._prefix.length) === this._prefix)
                  result.push(str.slice(this._prefix.length));
              }
              return result;
            }
      
            private _expandKey(key: string): string {
              var k: string;
      
              if (!key) {
                k = this._prefix;
              }
              else {
                k = this._cache[key];
                if (!k)
                  this._cache[key] = k = this._prefix + key;
              }
              
              return k;
            }
        	}
      
      
          class LocalStorageDetached implements Drive.Detached {
      
            timestamp: number = 0;
      
            constructor(private _access: LocalStorageAccess) {
              var timestampStr = this._access.get('*timestamp');
              if (timestampStr && timestampStr.charAt(0)>='0' && timestampStr.charAt(0)<='9') {
                try {
                  this.timestamp = parseInt(timestampStr);
                }
                catch (parseError) {
                }
              }
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              var keys = this._access.keys();
              for (var i = 0; i < keys.length; i++) {
                var k = keys[i];
                if (k.charAt(0)==='/') {
                  var value = this._access.get(k);
                  mainDrive.write(k, value);
                }
              }
              
              var shadow = new LocalStorageShadow(this._access, mainDrive.timestamp);
              callback(shadow);
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              var keys = this._access.keys();
              for (var i = 0; i < keys.length; i++) {
                var k = keys[i];
                if (k.charAt(0)==='/') {
                  var value = this._access.remove(k);
                }
              }
      
              var shadow = new LocalStorageShadow(this._access, this.timestamp);
              callback(shadow);
            }
      
          }
          
          class LocalStorageShadow implements Drive.Shadow {
      
            constructor(private _access: LocalStorageAccess, public timestamp: number) {
            }
      
            write(file: string, content: string) {
              this._access.set(file, content);
              this._access.set('*timestamp', <any>this.timestamp);
            }
      
          }
      
        }
        
      }
      
    • mountDrive.ts
      module portabled.persistence {
      
        export function defaultPersistenceModules() {
          return [
            persistence.indexedDB,
            persistence.webSQL,
            persistence.localStorage
          ];
        }
      
        export function mountDrive(
          dom: Drive,
          uniqueKey: string,
          domTimestamp: number,
          optionalModules: Drive.Optional[],
          callback: mountDrive.Callback): void {
      
          var driveIndex = 0;
      
          loadNextOptional();
      
          function loadNextOptional() {
      
            while (driveIndex < optionalModules.length &&
              (!optionalModules[driveIndex] || typeof optionalModules[driveIndex].detect !== 'function')) {
              driveIndex++;
            }
      
            if (driveIndex >= optionalModules.length) {
              callback(new MountedDrive(dom, null));
              return;
            }
      
            var op = optionalModules[driveIndex];
            op.detect(
              uniqueKey,
              detached => {
                if (!detached) {
                  driveIndex++;
                  loadNextOptional();
                  return;
                }
      
                if (detached.timestamp > domTimestamp) {
                  var callbackWithShadow: Drive.Detached.CallbackWithShadow = loadedDrive => {
                    dom.timestamp = detached.timestamp;
                    callback(new MountedDrive(dom, loadedDrive));
                  };
                  if (callback.progress)
                    callbackWithShadow.progress = callback.progress;
                  detached.applyTo(dom, callbackWithShadow);
                }
                else {
                  var callbackWithShadow: Drive.Detached.CallbackWithShadow = loadedDrive => {
                    callback(new MountedDrive(dom, loadedDrive));
                  };
                  if (callback.progress)
                    callbackWithShadow.progress = callback.progress;
                  detached.purge(callbackWithShadow);
                }
              });
          }
      
        }
        
        export module mountDrive {
          
          export interface Callback {
      
            (drive: Drive): void;
      
            progress?: (current: number, total: number) => void;
      
          }
          
        }
        
        class MountedDrive implements Drive {
      
          timestamp: number = 0;
      
          constructor (private _dom: Drive, private _shadow: Drive.Shadow) {
            this.timestamp = this._dom.timestamp;
          }
          
          files(): string[] {
            return this._dom.files();
          }
      
          read(file: string): string {
            return this._dom.read(file);
          }
      
          write(file: string, content: string) {
            this._dom.timestamp = this.timestamp;
            this._dom.write(file, content);
            if (this._shadow) {
              this._shadow.timestamp = this.timestamp;
              this._shadow.write(file, content);
            }
          }
        }
        
      }
    • webSQL.ts
      module portabled {
      
        function getOpenDatabase() {
          return typeof openDatabase !== 'function' ? null : openDatabase;
        }
      
        export module persistence.webSQL {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
      
            var openDatabaseInstance = getOpenDatabase();
            if (!openDatabaseInstance) {
              callback(null);
              return;
            }
      
            var dbName = uniqueKey || 'portabled';
      
            var db = openDatabase(
              dbName, // name
              1, // version
              'Portabled virtual filesystem data', // displayName
              1024 * 1024); // size
              // upgradeCallback?
      
      
            db.readTransaction(
              transaction => {
                transaction.executeSql(
                  'SELECT value from "*metadata" WHERE name=\'editedUTC\'',
                  [],
                  (transaction, result) => {
                    var editedValue: number = null;
                    if (result.rows && result.rows.length === 1) {
                      var editedValueStr = result.rows.item(0).value;
                      if (typeof editedValueStr === 'string') {
                        try {
                          editedValue = parseInt(editedValueStr);
                        }
                        catch (error) {
                          // unexpected value for the timestamp, continue as if no value found
                        }
                      }
                      else if (typeof editedValueStr === 'number') {
                        editedValue = editedValueStr;
                      }
                    }
      
                    callback(new WebSQLDetached(db, editedValue || 0, true));
                  },
                  (transaction, sqlError) => {
                    // no data
                    callback(new WebSQLDetached(db, 0, false));
                  });
              },
              sqlError=> {
                // failed to load
                callback(null);
              });
      
          }
      
          class WebSQLDetached implements Drive.Detached {
      
            constructor(
              private _db: Database,
              public timestamp: number,
            	private _metadataTableIsValid: boolean) {
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              this._db.readTransaction(
                transaction => listAllTables(
                  transaction,
                  tables => {
                    
                    var ftab = getFilenamesFromTables(tables);
      
                    this._applyToWithFiles(transaction, ftab, mainDrive, callback);
                  },
                  sqlError => {
                    reportSQLError('Failed to list tables for the webSQL database.', sqlError);
                    callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                  }),
                sqlError => {
                  reportSQLError('Failed to open read transaction for the webSQL database.', sqlError);
                  callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                });
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              this._db.transaction(
                transaction => listAllTables(
                  transaction,
                  tables => {
                    this._purgeWithTables(transaction, tables, callback);
                  },
                  sqlError => {
                  	reportSQLError('Failed to list tables for the webSQL database.', sqlError);
                    callback(new WebSQLShadow(this._db, 0, false));
                  }),
                sqlError => {
                  reportSQLError('Failed to open read-write transaction for the webSQL database.', sqlError);
                  callback(new WebSQLShadow(this._db, 0, false));
              });
          	}
            
            private _applyToWithFiles(transaction: SQLTransaction, ftab: { file: string; table: string; }[], mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
      
              if (!ftab.length) {
                callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                return;
              }
      
              var reportedFileCount = 0;
              
              var completeOne = () => {
                reportedFileCount++;
                if (reportedFileCount===ftab.length) {
                  callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                }
              };
            
              var applyFile = (file: string, table: string) => {
                transaction.executeSql(
                  'SELECT * FROM "' + table + '"',
                  [],
                  (transaction, result) => {
                    if (result.rows.length) {
                      var row = result.rows.item(0);
                      if (row.value === null)
                        mainDrive.write(file, null);
                      else if (typeof row.value === 'string')
                        mainDrive.write(file, fromSqlText(row.value));
                    }
                    completeOne();
                  },
                  sqlError => {
                    completeOne();
                  });
              };
              
              for (var i = 0; i < ftab.length; i++) {
                applyFile(ftab[i].file, ftab[i].table);
              }
      
            }
            
            private _purgeWithTables(transaction: SQLTransaction, tables: string[], callback: Drive.Detached.CallbackWithShadow) {
              if (!tables.length) {
                callback(new WebSQLShadow(this._db, 0, false));
                return;
              }
      
              var droppedCount = 0;
      
              var completeOne = () => {
                droppedCount++;
                if(droppedCount === tables.length){
                  callback(new WebSQLShadow(this._db, 0, false));
                }
              };
      
              for (var i = 0; i < tables.length; i++) {
                transaction.executeSql(
                  'DROP TABLE "' + tables[i] + '"',
                  [],
                  (transaction, result) => {
                    completeOne();
                  },
                  (transaction, sqlError) => {
                    reportSQLError('Failed to drop table for the webSQL database.', sqlError);
                    completeOne();
                  });
              }
            }
      
          }
      
          class WebSQLShadow implements Drive.Shadow {
      
            private _cachedUpdateStatementsByFile: { [name: string]: string; } = {};
            private _closures = {
              updateMetadata: (transaction: SQLTransaction) => this._updateMetadata(transaction)
            };
      
            constructor(private _db: Database, public timestamp: number, private _metadataTableIsValid: boolean) {
            }
      
            write(file: string, content: string) {
              
              if (content || typeof content === 'string') {
                this._updateCore(file, content);
              }
              else {
                this._dropFileTable(file);
              }
            }
            
            private _updateCore(file: string, content: string) {
                var updateSQL = this._cachedUpdateStatementsByFile[file];
                if (!updateSQL) {
                  var tableName = mangleDatabaseObjectName(file);
                  updateSQL = this._createUpdateStatement(file, tableName);
                }
                this._db.transaction(
                  transaction => {
                    transaction.executeSql(
                      updateSQL,
                      ['content', content],
                      this._closures.updateMetadata,
                      (transaction, sqlError) => this._createTableAndUpdate(transaction, file, tableName, updateSQL, content));
                  },
                  sqlError => {
                    reportSQLError('Transaction failure updating file "' + file + '".', sqlError);
                  });
            }
            
            private _createTableAndUpdate(transaction: SQLTransaction, file: string, tableName: string, updateSQL: string, content: string) {
              if (!tableName)
                tableName = mangleDatabaseObjectName(file);
      
              transaction.executeSql(
                'CREATE TABLE "' + tableName + '" (name PRIMARY KEY, value)',
                [],
                (transaction, result) => {
                  transaction.executeSql(
                    updateSQL,
                    ['content', content],
                    this._closures.updateMetadata,
                    (transaction, sqlError) => {
                      reportSQLError('Failed to update table "' + tableName + '" for file "' + file + '" after creation.', sqlError);
                    });
                },
                (transaction, sqlError) => {
                  reportSQLError('Failed to create a table "' + tableName + '" for file "' + file + '".', sqlError);
                });
            }
            
            private _dropFileTable(file: string) {
              var tableName = mangleDatabaseObjectName(file);
              this._db.transaction(
                transaction => {
                  transaction.executeSql(
                    'DROP TABLE "' + tableName + '"',
                    [],
                    this._closures.updateMetadata,
                    (transaction, sqlError) => {
                      reportSQLError('Failed to drop table "' + tableName + '" for file "' + file + '".', sqlError);
                    });
                },
                sqlError => {
                  reportSQLError('Transaction failure dropping table "' + tableName + '" for file "' + file + '".', sqlError);
                });
            }
            
            private _updateMetadata(transaction: SQLTransaction) {
              var updateMetadataSQL = 'INSERT OR REPLACE INTO "*metadata" VALUES (?,?)';
              transaction.executeSql(
                updateMetadataSQL,
                ['editedUTC', this.timestamp],
                (transaction, result) => { }, // TODO: generate closure statically
                (transaction, error) => {
                  transaction.executeSql(
                    'CREATE TABLE "*metadata" (name PRIMARY KEY, value)',
                    [],
                    (transaction, result) => {
                      transaction.executeSql(updateMetadataSQL, [],() => { },() => { });
                    },
                    (transaction, sqlError) => {
                      reportSQLError('Failed to update metadata table after creation.', sqlError);
                    });
                });
                
            }
            
            private _createUpdateStatement(file: string, tableName: string): string {
              return this._cachedUpdateStatementsByFile[file] =
                'INSERT OR REPLACE INTO "' + tableName + '" VALUES (?,?)';
            }
          }
          
          
          function mangleDatabaseObjectName(name: string): string {
            // no need to polyfill btoa, if webSQL exists
            if (name.toLowerCase() === name)
              return name;
            else
              return '='+btoa(name);
          }
      
          function unmangleDatabaseObjectName(name: string): string {
            if (!name || name.charAt(0) === '*') return null;
            
            if (name.charAt(0) !== '=') return name;
      
            try {
              return atob(name.slice(1));
            }
            catch (error) {
              return name;
            }
          }
      
          export function listAllTables(
            transaction: SQLTransaction,
            callback: (tables: string[]) => void,
            errorCallback: (sqlError: SQLError)=>void) {
            transaction.executeSql(
              'SELECT tbl_name  from sqlite_master WHERE type=\'table\'',
              [],
              (transaction, result) => {
                var tables: string[] = [];
                for (var i = 0; i < result.rows.length; i++) {
                  var row = result.rows.item(i);
                  var table = row.tbl_name;
                  if(!table || (table[0] !== '*' && table.charAt(0) !== '=' && table.charAt(0) !== '/')) continue;
                  tables.push(row.tbl_name);
                }
                callback(tables);
              },
              (transaction, sqlError) => errorCallback(sqlError));
          }
          
          function getFilenamesFromTables(tables: string[]) {
            var filenames: { table: string; file: string; }[] = [];
            for (var i = 0; i < tables.length; i++) {
              var file = unmangleDatabaseObjectName(tables[i]);
              if (file)
              	filenames.push({ table: tables[i], file: file });
            }
            return filenames;
          }
      
          function toSqlText(text: string) {
            if (text.indexOf('\u00FF') < 0 && text.indexOf('\u0000') < 0) return text;
      
            return text.replace(/\u00FF/g, '\u00FFf').replace(/\u0000/g, '\u00FF0');
          }
      
          function fromSqlText(sqlText: string) { 
            if (sqlText.indexOf('\u00FF') < 0 && sqlText.indexOf('\u0000') < 0) return sqlText;
      
            return sqlText.replace(/\u00FFf/g, '\u00FF').replace(/\u00FF0/g, '\u0000');
          }
          
          function reportSQLError(message: string, sqlError: SQLError);
          function reportSQLError(sqlError: SQLError);
          function reportSQLError(message, sqlError?) {
            if (typeof console !== 'undefined' && typeof console.error === 'function') {
              if (sqlError)
                console.error(message, sqlError);
              else
                console.error(sqlError);
            }
          }
      
      
        }
      
      }
  • shell
    • consoleUI
      • ConsoleUI.ts
        module portabled.shell.consoleUI {
        
          export class ConsoleUI {
        
            cm: CodeMirror;
            doc: CodeMirror.Doc;
        
            constructor(private _host: HTMLElement) {
        
              this.cm = new CodeMirror(element => {
                element.style.position = 'absolute';
                element.style.height = '100%';
                element.style.width = '100%';
                this._host.appendChild(element);
              }, {
                lineNumbers: true,
                theme: '3024-night'
              });
              this.doc = this.cm.getDoc();
              
              setTimeout(() => this.cm.focus(), 100);
        
            }
        
            log(message: any, ...optionalParameters: any[]) {
              this.doc.replaceSelection(message);
            }
        
          }
        }
    • extensions
      • ExtensionHost.ts
        module portabled.shell.extensions {
        
          
        
        }
    • panels
      • Panels.ts
        module portabled.shell.panels {
        
          export class Panels {
        
            private _leftHost = element('div', {
              position: 'fixed',
              width: '49.9%',
              top: '0px', bottom: '3em',
              padding: '0.25em',
              background: 'cornflowerBlue',
              opacity: '0.5',
              zIndex: 100
            }, this._host);
        
            private _leftPanel = element('div', {
              width: '100%', height: '100%',
              border: 'solid 1px white',
              padding: '0.25em'
            }, this._leftHost);
        
            private _rightHost = element('div', {
              position: 'fixed',
              left: '50.2%',
              width: '49.9%',
              top: '0px', bottom: '3em',
              padding: '0.25em',
              background: 'cornflowerBlue',
              opacity: '0.5',
              zIndex: 100
            }, this._host);
        
            private _rightPanel = element('div', {
              width: '100%', height: '100%',
              border: 'solid 1px white',
              padding: '0.25em'
            }, this._rightHost);  
            
            constructor(private _host: HTMLElement) {
              setTextContent(this._rightPanel, 'one two');
            }
        
          }
        
        }
    • basic-html-body.css
      html {
        box-sizing: border-box;
        background: black;
        color: silver;
      }
      
      *, *:before, *:after {
        box-sizing: inherit;
      }
      
      html {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
      body {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
    • boot-initial.css
      body {
        opacity: 0.3;
      
      	filter: blur(2px);
      
        filter: url("#boot_gaussian_blur");
        -webkit-filter: blur(2px);
        -o-filter: blur(3px);
      }
    • boot-loaded.css
      body {
        opacity: 1;
        filter: none;
        -webkit-filter: none;
        -o-filter: none;
      }
    • index.html
      <!doctype html>
      <html>
        <head>
      		<meta charset="utf-8">
          <title> portable shell </title>
      
          <!-- main and boot time CSS -->
          <svg style="display: none;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <defs><filter id="boot_gaussian_blur"><feGaussianBlur in="SourceGraphic" stdDeviation="2" /></filter></defs>
        	</svg>
          <style>
      <%=uglifyCSS('shell/basic-html-body.css', 'shell/boot-initial.css')%>
          </style>
      
          <!-- CodeMiror CSS -->
          <style>
            <%=uglifyCSS(
              'imports/codemirror/lib/codemirror.css',
            	'imports/codemirror/theme/3024-night.css',
              'imports/codemirror/addon/hint/show-hint.css',
              'imports/codemirror/addon/dialog/dialog.css',
              'imports/codemirror/addon/merge/merge.css')%>
          </style>
      
        </head>
        <body>
      
          <!-- Error handling script -->
          <script data-legit=portabled><%=embedFile('errors.js')%></script>
      
          <!-- ES5 shim/sham, JSON3 -->
          <script data-legit=portabled>
            <%=embedFile('imports/es5-shim/es5-shim.min.js','imports/es5-shim/es5-sham.min.js', 'imports/json3/json3.min.js')%>
          </script>
      
      
          <!-- CodeMirror -->
          <script data-legit=portabled>
            <%=uglifyJS([
              'imports/codemirror/lib/codemirror.js',
              'imports/codemirror/addon/dialog/dialog.js',
              'imports/codemirror/addon/search/search.js',
              'imports/codemirror/addon/search/searchcursor.js',
              'imports/codemirror/addon/hint/show-hint.js',
              'imports/codemirror/mode/javascript/javascript.js',
              'imports/codemirror/addon/tern/tern.js',
              'imports/codemirror/addon/hint/javascript-hint.js',
              'imports/codemirror/mode/css/css.js',
              'imports/codemirror/addon/hint/css-hint.js',
              'imports/codemirror/mode/sass/sass.js',
              'imports/codemirror/mode/xml/xml.js',
              'imports/codemirror/addon/hint/xml-hint.js',
              'imports/codemirror/mode/htmlmixed/htmlmixed.js',
              'imports/codemirror/mode/htmlembedded/htmlembedded.js',
              'imports/codemirror/addon/hint/html-hint.js',
              'imports/codemirror/mode/markdown/markdown.js',
              'imports/codemirror/addon/edit/matchbrackets.js',
              'imports/codemirror/addon/selection/active-line.js'])%>
          </script>
      
      
          <!-- Main portabled JS code -->
          <script data-legit=portabled><%=typescriptBuild()%></script>
      
          <script data-legit=portabled> if (typeof portabled !== 'undefined') portabled.shell.start(); </script>
      
      
      
          <!-- finished loaded CSS -->
          <style><%=uglifyCSS('shell/boot-loaded.css')%></style>
      
        </body>
      </html>
    • start.ts
      module portabled.shell {
      
        export function start() {
      
          addEventListener(window, 'load', () => {
            var co = new consoleUI.ConsoleUI(document.body);
            var pan = new panels.Panels(document.body);
          });
        }
      
      }
  • typescript
    • ExternalDocument.ts
      module portabled.typescript {
        
        export interface ExternalDocument {
          
          text(): string;
          changes(): ts.TextChangeRange[];
          
        }
        
      }
    • ScriptDocumentSnapshot.ts
      module portabled.typescript {
      
        export class ScriptDocumentSnapshot implements ts.IScriptSnapshot {
      
          changes: ts.TextChangeRange[];
      
          private _text: string;
          private _lineStartPositions: number[] = null;
      
          constructor(doc: ExternalDocument) {
            this._text = doc.text();
            this.changes = doc.changes().slice(0);
          }
      
          getText(start: number, end: number): string {
            if (!this._text)
              return '';
            return this._text.slice(start, end);
          }
      
          getLength(): number {
            if (!this._text)
              return 0;
            return this._text.length;
          }
      
          getChangeRange(oldSnapshot: ts.IScriptSnapshot): ts.TextChangeRange {
      
            if (!this.changes.length)
              return ts.unchangedTextChangeRange;
      
            var typedOldSnapshot = <ScriptDocumentSnapshot>oldSnapshot;
            var chunk = typedOldSnapshot.changes ?
              this.changes.slice(typedOldSnapshot.changes.length) :
              this.changes;
      
            var result = ts.collapseTextChangeRangesAcrossMultipleVersions(chunk);
      
            return result;
      
          }
      
      
        }
        
      }
    • ScriptDocumentState.ts
      module portabled.typescript {
        
        export class ScriptDocumentState {
      
          private _snapshot: ScriptDocumentSnapshot = null;
      
          constructor(public doc: ExternalDocument) {
          }
      
          getScriptSnapshot() {
            if (!this._snapshot || this._snapshot.changes.length != this.doc.changes().length)
              this._snapshot = new ScriptDocumentSnapshot(this.doc);
            return this._snapshot;
          }
      
          getScriptVersion() {
            var changes = this.doc.changes();
            return changes.length;
          }
      
        }
        
      }
    • TypeScriptService.ts
      module portabled.typescript {
      
        export class TypeScriptService {
      
          private _service: ts.LanguageService;
      
          compilerOptions: ts.CompilerOptions;
          cancellation: ts.CancellationToken = null;
          currentDirectory = '/';
          defaultLibFilenames = ['#core.d.ts', '#extensions.d.ts', '#dom.generated.d.ts'];
      
          log: (text: string) => void = null;
      
          host: ts.LanguageServiceHost;
      
          private _scriptFileNames: string[] = null;
          private _scripts: { [fullPath: string]: ScriptDocumentState; } = {};
          private _defaultLibSnapshots: { [file: string]: ts.IScriptSnapshot; } = {};
      
          private _preloadScriptFileNames: string[] = [];
          private _preloadPendingScriptFileNames: string[] = [];
          private _preloadTimeout = 0;
      
          constructor() {
            this.compilerOptions = ts.getDefaultCompilerOptions();
            this.compilerOptions.target = ts.ScriptTarget.ES5;
            this.host = this._createHost();
            this._service = ts.createLanguageService(
              this.host,
              this._createRegistry());
          }
        
          stopPreloading() {
            if (this._preloadScriptFileNames) {
      
              // from now on stop pretending only a subset of files exists, report all of them in host.getScriptFileNames()
              this._preloadScriptFileNames = null;
              this._preloadPendingScriptFileNames = null;
            }
          }
      
          service() {
            this.stopPreloading();
      
            return this._service;
          }
      
          addFile(file: string, doc: ExternalDocument) {
            var script = new ScriptDocumentState(doc);
            this._scripts[file] = script;
            this._scriptFileNames = null;
      
            if (this._preloadPendingScriptFileNames) {
              this._preloadPendingScriptFileNames.push(file);
              if (this._preloadTimeout)
                clearTimeout(this._preloadTimeout);
              this._preloadTimeout = setTimeout(() => {
                if (this._preloadPendingScriptFileNames)
                  this._preloadPendingScriptFileNames.sort();
                this._continuePreload();
              }, 2000);
            }
          }
      
          removeFile(file: string) {
            delete this._scripts[file];
            this._scriptFileNames = null;
      
            if (this._preloadScriptFileNames) {
              for (var i = 0; i < this._preloadPendingScriptFileNames.length; i++) {
                if (this._preloadPendingScriptFileNames[i] === file) {
                  delete this._preloadPendingScriptFileNames[i];
                  break;
                }
              }
            }
            if (this._preloadScriptFileNames) {
              for (var i = 0; i < this._preloadScriptFileNames.length; i++) {
                if (this._preloadScriptFileNames[i] === file) {
                  delete this._preloadScriptFileNames[i];
                  break;
                }
              }
            }
          }
      
          private _continuePreload() {
      
            this._preloadTimeout = 0;
      
            if (!this._preloadScriptFileNames || !this._preloadPendingScriptFileNames)
              return;
      
            var reportErrors: (errors: ts.Diagnostic[]) => void;
            if (this._preloadScriptFileNames.length < this.defaultLibFilenames.length) {
              // first work through the default libs
              var nextFile = this._preloadScriptFileNames[this._preloadScriptFileNames.length] = this.defaultLibFilenames[this._preloadScriptFileNames.length];
              reportErrors = errors => {
                if (console && typeof console.error == 'function') {
                  console.error(nextFile + ' ' + errors.length + ' errors:');
                  for (var i = 0; i < errors.length; i++) {
                    var err = errors[i];
                    console.error(err.file.getLineAndCharacterOfPosition(err.start), ' ', err.messageText);
                  }
                }
                else {
                  var all = [];
                  for (var i = 0; i < errors.length; i++) {
                    var err = errors[i];
                    var pos = err.file.getLineAndCharacterOfPosition(err.start); 
                    all.push(pos.line + ':' + pos.character + ' ' + err.messageText);
                    alert(nextFile + ' ' + errors.length + ' errors:\n' + all.join('\n'));
                  }
                }
              };
            }
            else {
              if (!this._preloadPendingScriptFileNames.length) {
      
                // finished preloading, from now on report all files instead of a subset
                this._preloadScriptFileNames = null;
                this._preloadPendingScriptFileNames = null;
                return; // TODO: call some event to notify it's all clear now
              }
      
              // after default libs are preloaded, get the other ordinary files
              var nextFile = this._preloadPendingScriptFileNames.shift();
              this._preloadScriptFileNames.push(nextFile);
            }
      
            var startPreload = dateNow();
            var errors= this._service.getSyntacticDiagnostics(nextFile);
            var preloadTimeSpent = dateNow() - startPreload;
      
            if (errors && errors.length && reportErrors)
              reportErrors(errors);
      
            var idleQuantum = Math.max(10, Math.min(300, preloadTimeSpent * 2));
      
            this._preloadTimeout = setTimeout(() => {
      
              if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
              var startPreload2 = dateNow();
              var errors = this._service.getSemanticDiagnostics(nextFile);
              var preloadTimeSpent2 = dateNow() - startPreload2;
      
              if (errors && errors.length && reportErrors)
                reportErrors(errors);
      
              var idleQuantum = Math.max(10, Math.min(200, preloadTimeSpent2 * 2));
      
              this._preloadTimeout = setTimeout(() => {
      
                if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
                var startPreload3 = dateNow();
                this._service.getEmitOutput(nextFile);
                var preloadTimeSpent3 = dateNow() - startPreload3;
      
                var idleQuantum = Math.max(10, Math.min(200, preloadTimeSpent3 * 2));
      
                this._preloadTimeout = setTimeout(() => {
      
                  if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
                  if (typeof console !== 'undefined' && typeof console.log === 'function')
                    console.log(
                      'TS preloaded ' + nextFile + ' ' +
                      (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3) / 1000 + ' sec. ' +
                      Math.floor(preloadTimeSpent * 100 / (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3)) + ':' +
                      Math.floor(preloadTimeSpent2 * 100 / (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3)) + '%' +
                      (this._preloadPendingScriptFileNames && this._preloadPendingScriptFileNames.length ? ' (' + this._preloadPendingScriptFileNames.length + ' to go)' : ''));
      
                  this._continuePreload();
      
                }, idleQuantum);
              }, idleQuantum);
            }, idleQuantum);
          }
      
          private _createRegistry() {
            return ts.createDocumentRegistry();
          }
      
          private _createHost(): ts.LanguageServiceHost {
            var result: ts.LanguageServiceHost = {
              getCompilationSettings: () => this.compilerOptions,
              getScriptFileNames: () => {
                if (this._preloadScriptFileNames) {
                  return this._preloadScriptFileNames;
                }
      
                if (!this._scriptFileNames) {
                  this._scriptFileNames = [];
                  for (var k in this._scripts) if (this._scripts.hasOwnProperty(k) && this._scripts[k])
                    this._scriptFileNames.push(k);
                  for (var i = 0; i < this.defaultLibFilenames.length; i++) {
                    this._scriptFileNames.push(this.defaultLibFilenames[i]);
                  }
                  this._scriptFileNames.sort();
                }
                return this._scriptFileNames;
              },
              getScriptVersion: (file) => {
                if (this.defaultLibFilenames.indexOf(file) >= 0)
                  return 'base';
      
                var script = this._scripts[file];
                return 'v' + script.getScriptVersion();
              },
              getScriptSnapshot: (file) => {
                if (this.defaultLibFilenames.indexOf(file) >= 0) {
                  if (!this._defaultLibSnapshots[file]) {
                    var elementId = file.charAt(0) === '#' ? file.slice(1) : file;
                    var scriptElement = <HTMLScriptElement>document.getElementById(elementId);
                    if (scriptElement == null)
                      return null;
                    this._defaultLibSnapshots[file] = ts.ScriptSnapshot.fromString(scriptElement.text || scriptElement.textContent || scriptElement.innerText);
                  }
                  return this._defaultLibSnapshots[file];
                }
      
                return this._scripts[file].getScriptSnapshot();
              },
              getLocalizedDiagnosticMessages: () => null,
              getCancellationToken: () => this.cancellation,
              getCurrentDirectory: () => this.currentDirectory,
              getNewLine: () => '\n',
              getDefaultLibFileName: () => this.defaultLibFilenames[0],
              log: (text) => {
                if (this.log) {
                  this.log(text);
                }
                else {
                  if (typeof console != 'indefined') {
                    if (typeof console.groupCollapsed === 'function' && typeof console.groupEnd === 'function') {
                      console.groupCollapsed('TS');
                      if (typeof console.log === 'function')
                        console.log(text);
                      console.groupEnd();
                    }
                    else if (typeof console.info === 'function') {
                      console.info('*** TS ' + text);
                    }
                    else if (typeof console.log === 'function') {
                      console.log('*** TS ' + text);
                    }
                  }
                }
              }
            };
            return result;
      
          }
      
        }
      
      }
  • typings
    • codemirror.addons.d.ts
      interface CodeMirror {
      
        showHint(options: CodeMirror.showHint.Options);
      
      }
      
      declare module CodeMirror {
      
        module showHint {
          
          interface Options {
            
            /**
             * A hinting function. It is possible to set the async property on a hinting function to true,
             * in which case it will be called with arguments (cm, callback, ?options),
             * and the completion interface will only be popped up when the hinting function calls the callback,
             * passing it the object holding the completions.
             */
            hint: Function;
      
            /**
             * Determines whether, when only a single completion is available, it is completed without showing the dialog.
             * Defaults to true.
             */
            completeSingle?: boolean;
      
            /**
             * Whether the pop - up should be horizontally aligned with the start of the word (true, default),
             * or with the cursor (false).
             */
            alignWithWord?: boolean;
      
            /**
             * When enabled (which is the default), the pop - up will close when the editor is unfocused.
             */
            closeOnUnfocus?: boolean;
      
            /**
             * Allows you to provide a custom key map of keys to be active when the pop - up is active.
             * The handlers will be called with an extra argument, a handle to the completion menu,
             * which has moveFocus(n), setFocus(n), pick(), and close() methods (see the source for details),
             * that can be used to change the focused element, pick the current element or close the menu.
             * Additionnaly menuSize() can give you access to the size of the current dropdown menu,
             * length give you the number of availlable completions,
             * and data give you full access to the completion returned by the hinting function.
             */
            customKeys?: any;
      
            /**
             * Like customKeys above, but the bindings will be added to the set of default bindings,
             * instead of replacing them.
             */
            extraKeys?: any;
      
          }
            
          interface CompletionResult {
            list: Completion[];
            from: CodeMirror.Pos;
            to: CodeMirror.Pos;
          }
      
          interface Completion {
            
            /** The completion text. This is the only required property. */
            text: string;
      
            /** The text that should be displayed in the menu. */
            displayText?: string;
      
            /** A CSS class name to apply to the completion's line in the menu. */
            className?: string;
      
            /** A method used to create the DOM structure for showing the completion
             * by appending it to its first argument. */
            render?: (element: HTMLElement, self, data) => void;
      
            /** A method used to actually apply the completion, instead of the default behavior. */
            hint?: (cm: CodeMirror, self, data) => void;
      
            /** Optional from position that will be used by pick()
             * instead of the global one passed with the full list of completions. */
            from?: CodeMirror.Pos;
      
            /** Optional to position that will be used by pick() instead of the global one
             * passed with the full list of completions. */
            to?: CodeMirror.Pos;
      
          }
          
        }
      
        interface CodeMirrorStatic {
          
          /** Fired when the pop-up is shown. */
          on(completion: showHint.Options, eventName: 'shown', handler: (instance: showHint.CompletionResult) => void);
          off(completion: showHint.Options, eventName: 'shown', handler: (instance: showHint.CompletionResult) => void);
      
          /**
           * Fired when a completion is selected.
           * Passed the completion value (string or object) and the DOM node that represents it in the menu.
           */
          on(completion: showHint.Options, eventName: 'select', handler: (instance: showHint.CompletionResult, completion: showHint.Completion, element: HTMLElement) => void);
          off(completion: showHint.Options, eventName: 'select', handler: (instance: showHint.CompletionResult, completion: showHint.Completion, element: HTMLElement) => void);
      
          /**
           * Fired when a completion is picked. Passed the completion value (string or object).
           */
          on(completion: showHint.Options, eventName: 'pick', handler: (instance: showHint.CompletionResult, completion: showHint.Completion) => void);
          off(completion: showHint.Options, eventName: 'pick', handler: (instance: showHint.CompletionResult, completion: showHint.Completion) => void);
      
          /** Fired when the completion is finished. */
          on(completion: showHint.Options, eventName: 'close', handler: (instance: showHint.CompletionResult) => void);
          off(completion: showHint.Options, eventName: 'close', handler: (instance: showHint.CompletionResult) => void);
      
        }
      
      }
    • codemirror.d.ts
      declare var CodeMirror : CodeMirror.CodeMirrorStatic;
      
      interface CodeMirror {
      
        /** Tells you whether the editor currently has focus. */
        hasFocus(): boolean;
      
        /** Used to find the target position for horizontal cursor motion.start is a { line , ch } object,
        amount an integer(may be negative), and unit one of the string "char", "column", or "word".
        Will return a position that is produced by moving amount times the distance specified by unit.
        When visually is true , motion in right - to - left text will be visual rather than logical.
        When the motion was clipped by hitting the end or start of the document, the returned value will have a hitSide property set to true. */
        findPosH(start: CodeMirror.Pos, amount: number, unit: string, visually: boolean): { line: number; ch: number; hitSide?: boolean; };
      
        /** Similar to findPosH , but used for vertical motion.unit may be "line" or "page".
        The other arguments and the returned value have the same interpretation as they have in findPosH. */
        findPosV(start: CodeMirror.Pos, amount: number, unit: string): { line: number; ch: number; hitSide?: boolean; };
      
      
        /** Change the configuration of the editor. option should the name of an option, and value should be a valid value for that option. */
        setOption(option: string, value: any);
      
        /** Retrieves the current value of the given option for this editor instance. */
        getOption(option: string): any;
      
        /** Attach an additional keymap to the editor.
        This is mostly useful for add - ons that need to register some key handlers without trampling on the extraKeys option.
        Maps added in this way have a higher precedence than the extraKeys and keyMap options, and between them,
        the maps added earlier have a lower precedence than those added later, unless the bottom argument was passed,
        in which case they end up below other keymaps added with this method. */
        addKeyMap(map: any, bottom?: boolean);
      
        /** Disable a keymap added with addKeyMap.Either pass in the keymap object itself , or a string,
        which will be compared against the name property of the active keymaps. */
        removeKeyMap(map: any);
      
        /** Enable a highlighting overlay.This is a stateless mini - mode that can be used to add extra highlighting.
        For example, the search add - on uses it to highlight the term that's currently being searched.
        mode can be a mode spec or a mode object (an object with a token method). The options parameter is optional. If given, it should be an object.
        Currently, only the opaque option is recognized. This defaults to off, but can be given to allow the overlay styling, when not null,
        to override the styling of the base mode entirely, instead of the two being applied together. */
        addOverlay(mode: any, options?: any);
      
        /** Pass this the exact argument passed for the mode parameter to addOverlay to remove an overlay again. */
        removeOverlay(mode: any);
      
      
        /** Retrieve the currently active document from an editor. */
        getDoc(): CodeMirror.Doc;
      
        /** Attach a new document to the editor. Returns the old document, which is now no longer associated with an editor. */
        swapDoc(doc: CodeMirror.Doc): CodeMirror.Doc;
      
      
      
        /** Sets the gutter marker for the given gutter (identified by its CSS class, see the gutters option) to the given value.
        Value can be either null, to clear the marker, or a DOM element, to set it. The DOM element will be shown in the specified gutter next to the specified line. */
        setGutterMarker(line: any, gutterID: string, value: HTMLElement): CodeMirror.LineHandle;
      
        /** Remove all gutter markers in the gutter with the given ID. */
        clearGutter(gutterID: string);
      
        /** Set a CSS class name for the given line.line can be a number or a line handle.
        where determines to which element this class should be applied, can can be one of "text" (the text element, which lies in front of the selection),
        "background"(a background element that will be behind the selection),
        or "wrap" (the wrapper node that wraps all of the line's elements, including gutter elements).
        class should be the name of the class to apply. */
        addLineClass(line: any, where: string, _class_: string): CodeMirror.LineHandle;
      
        /** Remove a CSS class from a line.line can be a line handle or number.
        where should be one of "text", "background", or "wrap"(see addLineClass).
        class can be left off to remove all classes for the specified node, or be a string to remove only a specific class. */
        removeLineClass(line: any, where: string, class_: string): CodeMirror.LineHandle;
      
        /** Returns the line number, text content, and marker status of the given line, which can be either a number or a line handle. */
        lineInfo(line: any): {
            line: any;
            handle: any;
            text: string;
            /** Object mapping gutter IDs to marker elements. */
            gutterMarks: any;
            textClass: string;
            bgClass: string;
            wrapClass: string;
            /** Array of line widgets attached to this line. */
            widgets: any;
        };
      
        /** Puts node, which should be an absolutely positioned DOM node, into the editor, positioned right below the given { line , ch } position.
        When scrollIntoView is true, the editor will ensure that the entire node is visible (if possible).
        To remove the widget again, simply use DOM methods (move it somewhere else, or call removeChild on its parent). */
        addWidget(pos: CodeMirror.Pos, node: HTMLElement, scrollIntoView: boolean);
      
        /** Adds a line widget, an element shown below a line, spanning the whole of the editor's width, and moving the lines below it downwards.
        line should be either an integer or a line handle, and node should be a DOM node, which will be displayed below the given line.
        options, when given, should be an object that configures the behavior of the widget.
        Note that the widget node will become a descendant of nodes with CodeMirror-specific CSS classes, and those classes might in some cases affect it. */
        addLineWidget(line: any, node: HTMLElement, options?: {
            /** Whether the widget should cover the gutter. */
            coverGutter: boolean;
            /** Whether the widget should stay fixed in the face of horizontal scrolling. */
            noHScroll: boolean;
            /** Causes the widget to be placed above instead of below the text of the line. */
            above: boolean;
            /** When true, will cause the widget to be rendered even if the line it is associated with is hidden. */
            showIfHidden: boolean;
        }): CodeMirror.LineWidget;
      
      
        /** Programatically set the size of the editor (overriding the applicable CSS rules).
        width and height height can be either numbers(interpreted as pixels) or CSS units ("100%", for example).
        You can pass null for either of them to indicate that that dimension should not be changed. */
        setSize(width: any, height: any);
      
        /** Scroll the editor to a given(pixel) position.Both arguments may be left as null or undefined to have no effect. */
        scrollTo(x: number, y: number);
      
        /** Get an { left , top , width , height , clientWidth , clientHeight } object that represents the current scroll position, the size of the scrollable area,
        and the size of the visible area(minus scrollbars). */
        getScrollInfo(): CodeMirror.ScrollInfo;
      
        /** Scrolls the given element into view. pos is a { line , ch } position, referring to a given character, null, to refer to the cursor.
        The margin parameter is optional. When given, it indicates the amount of pixels around the given area that should be made visible as well. */
        scrollIntoView(pos: CodeMirror.Pos, margin?: number);
      
        /** Scrolls the given element into view. pos is a { left , top , right , bottom } object, in editor-local coordinates.
        The margin parameter is optional. When given, it indicates the amount of pixels around the given area that should be made visible as well. */
        scrollIntoView(pos: { left: number; top: number; right: number; bottom: number; }, margin: number);
      
        /** Returns an { left , top , bottom } object containing the coordinates of the cursor position.
        If mode is "local" , they will be relative to the top-left corner of the editable document.
        If it is "page" or not given, they are relative to the top-left corner of the page.
        where is a boolean indicating whether you want the start(true) or the end(false) of the selection. */
        cursorCoords(where: boolean, mode: string): { left: number; top: number; bottom: number; };
      
        /** Returns an { left , top , bottom } object containing the coordinates of the cursor position.
        If mode is "local" , they will be relative to the top-left corner of the editable document.
        If it is "page" or not given, they are relative to the top-left corner of the page.
        where specifies the precise position at which you want to measure. */
        cursorCoords(where: CodeMirror.Pos, mode: string): { left: number; top: number; bottom: number; };
      
        /** Returns the position and dimensions of an arbitrary character.pos should be a { line , ch } object.
        This differs from cursorCoords in that it'll give the size of the whole character,
        rather than just the position that the cursor would have when it would sit at that position. */
        charCoords(pos: CodeMirror.Pos, mode: string): { left: number; right: number; top: number; bottom: number; };
      
        /** Given an { left , top } object , returns the { line , ch } position that corresponds to it.
        The optional mode parameter determines relative to what the coordinates are interpreted. It may be "window" , "page"(the default) , or "local". */
        coordsChar(object: { left: number; top: number; }, mode?: string): CodeMirror.Pos;
      
        lineAtHeight(height: number, mode?: string): number;
        heightAtLine(line: number, mode?: string): number;
      
        /** Returns the line height of the default font for the editor. */
        defaultTextHeight(): number;
      
        /** Returns the pixel width of an 'x' in the default font for the editor.
        (Note that for non - monospace fonts , this is mostly useless, and even for monospace fonts, non - ascii characters might have a different width). */
        defaultCharWidth(): number;
      
        /** Returns a { from , to } object indicating the start (inclusive) and end (exclusive) of the currently rendered part of the document.
        In big documents, when most content is scrolled out of view, CodeMirror will only render the visible part, and a margin around it.
        See also the viewportChange event. */
        getViewport(): { from: number; to: number };
      
        /** If your code does something to change the size of the editor element (window resizes are already listened for), or unhides it,
        you should probably follow up by calling this method to ensure CodeMirror is still looking as intended. */
        refresh();
      
      
        /** Retrieves information about the token the current mode found before the given position (a {line, ch} object). */
        getTokenAt(pos: CodeMirror.Pos): {
            /** The character(on the given line) at which the token starts. */
            start: number;
            /** The character at which the token ends. */
            end: number;
            /** The token's string. */
            string: string;
            /** The token type the mode assigned to the token, such as "keyword" or "comment" (may also be null). */
            type: string;
            /** The mode's state at the end of this token. */
            state: any;            
        };
      
        /** Returns the mode's parser state, if any, at the end of the given line number.
        If no line number is given, the state at the end of the document is returned.
        This can be useful for storing parsing errors in the state, or getting other kinds of contextual information for a line. */
        getStateAfter(line?: number): any;
      
        /** CodeMirror internally buffers changes and only updates its DOM structure after it has finished performing some operation.
        If you need to perform a lot of operations on a CodeMirror instance, you can call this method with a function argument.
        It will call the function, buffering up all changes, and only doing the expensive update after the function returns.
        This can be a lot faster. The return value from this method will be the return value of your function. */
        operation<T>(fn: ()=> T): T;
      
        /** Adjust the indentation of the given line.
        The second argument (which defaults to "smart") may be one of:
        "prev" Base indentation on the indentation of the previous line.
        "smart" Use the mode's smart indentation if available, behave like "prev" otherwise.
        "add" Increase the indentation of the line by one indent unit.
        "subtract" Reduce the indentation of the line. */
        indentLine(line: number, dir?: string);
      
      
        /** Give the editor focus. */
        focus();
      
        /** Returns the hidden textarea used to read input. */
        getInputField(): HTMLTextAreaElement;
      
        /** Returns the DOM node that represents the editor, and controls its size. Remove this from your tree to delete an editor instance. */
        getWrapperElement(): HTMLElement;
      
        /** Returns the DOM node that is responsible for the scrolling of the editor. */
        getScrollerElement(): HTMLElement;
      
        /** Fetches the DOM node that contains the editor gutters. */
        getGutterElement(): HTMLElement;
      
      
      
        /** Events are registered with the on method (and removed with the off method).
        These are the events that fire on the instance object. The name of the event is followed by the arguments that will be passed to the handler.
        The instance argument always refers to the editor instance. */
        on(eventName: string, handler: (instance: CodeMirror) => void );
        off(eventName: string, handler: (instance: CodeMirror) => void );
      
        /** Fires every time the content of the editor is changed. */
        on(eventName: 'change', handler: (instance: CodeMirror, change: CodeMirror.EditorChange) => void );
        off(eventName: 'change', handler: (instance: CodeMirror, change: CodeMirror.EditorChange) => void );
      
        /** Fires every time the content of the editor is changed. */
        on(eventName: 'changes', handler: (instance: CodeMirror, change: CodeMirror.EditorChange[]) => void );
        off(eventName: 'changes', handler: (instance: CodeMirror, change: CodeMirror.EditorChange[]) => void );
      
        /** This event is fired before a change is applied, and its handler may choose to modify or cancel the change.
        The changeObj never has a next property, since this is fired for each individual change, and not batched per operation.
        Note: you may not do anything from a "beforeChange" handler that would cause changes to the document or its visualization.
        Doing so will, since this handler is called directly from the bowels of the CodeMirror implementation,
        probably cause the editor to become corrupted. */
        on(eventName: 'beforeChange', handler: (instance: CodeMirror, change: CodeMirror.EditorChangeCancellable) => void );
        off(eventName: 'beforeChange', handler: (instance: CodeMirror, change: CodeMirror.EditorChangeCancellable) => void );
      
        /** Will be fired when the cursor or selection moves, or any change is made to the editor content. */
        on(eventName: 'cursorActivity', handler: (instance: CodeMirror) => void );
        off(eventName: 'cursorActivity', handler: (instance: CodeMirror) => void );
      
        /** This event is fired before the selection is moved. Its handler may modify the resulting selection head and anchor.
        Handlers for this event have the same restriction as "beforeChange" handlers: they should not do anything to directly update the state of the editor. */
        on(eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: CodeMirror.Pos; anchor: CodeMirror.Pos; }) => void );
        off(eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: CodeMirror.Pos; anchor: CodeMirror.Pos; }) => void );
      
        /** Fires whenever the view port of the editor changes (due to scrolling, editing, or any other factor).
        The from and to arguments give the new start and end of the viewport. */
        on(eventName: 'viewportChange', handler: (instance: CodeMirror, from: number, to: number) => void );
        off(eventName: 'viewportChange', handler: (instance: CodeMirror, from: number, to: number) => void );
      
        /** Fires when the editor gutter (the line-number area) is clicked. Will pass the editor instance as first argument,
        the (zero-based) number of the line that was clicked as second argument, the CSS class of the gutter that was clicked as third argument,
        and the raw mousedown event object as fourth argument. */
        on(eventName: 'gutterClick', handler: (instance: CodeMirror, line: number, gutter: string, clickEvent: Event) => void );
        off(eventName: 'gutterClick', handler: (instance: CodeMirror, line: number, gutter: string, clickEvent: Event) => void );
      
        /** Fires whenever the editor is focused. */
        on(eventName: 'focus', handler: (instance: CodeMirror) => void );
        off(eventName: 'focus', handler: (instance: CodeMirror) => void );
      
        /** Fires whenever the editor is unfocused. */
        on(eventName: 'blur', handler: (instance: CodeMirror) => void );
        off(eventName: 'blur', handler: (instance: CodeMirror) => void );
      
        /** Fires when the editor is scrolled. */
        on(eventName: 'scroll', handler: (instance: CodeMirror) => void );
        off(eventName: 'scroll', handler: (instance: CodeMirror) => void );
      
        /** Will be fired whenever CodeMirror updates its DOM display. */
        on(eventName: 'update', handler: (instance: CodeMirror) => void );
        off(eventName: 'update', handler: (instance: CodeMirror) => void );
      
        /** Fired whenever a line is (re-)rendered to the DOM. Fired right after the DOM element is built, before it is added to the document.
        The handler may mess with the style of the resulting element, or add event handlers, but should not try to change the state of the editor. */
        on(eventName: 'renderLine', handler: (instance: CodeMirror, line: number, element: HTMLElement) => void );
        off(eventName: 'renderLine', handler: (instance: CodeMirror, line: number, element: HTMLElement) => void );
      }
      
      declare module CodeMirror {
        
        export interface ScrollInfo {
          left: any;
          top: any;
          width: any;
          height: any;
          clientWidth: any;
          clientHeight: any;
        }
        
        export interface CodeMirrorStatic {
          
          Pass: any;
      
          new (host: HTMLElement, options?: CodeMirror.Options): CodeMirror;
          new (callback: (host: HTMLElement) => void , options?: CodeMirror.Options): CodeMirror;
      
          (host: HTMLElement, options?: CodeMirror.Options): CodeMirror;
          (callback: (host: HTMLElement) => void , options?: CodeMirror.Options): CodeMirror;
      
          Doc: {
            (text: string, mode?: any, firstLineNumber?: number): Doc;
            new (text: string, mode?: any, firstLineNumber?: number): Doc;
          };
      
          Pos: {
            (line: number, ch?: number): Pos;
            new (line: number, ch?: number): Pos;
          };
      
          fromTextArea(host: HTMLTextAreaElement, options?: Options): CodeMirror;
      
          version: string;
      
          /** If you want to define extra methods in terms of the CodeMirror API, it is possible to use defineExtension.
          This will cause the given value(usually a method) to be added to all CodeMirror instances created from then on. */
          defineExtension(name: string, value: any);
      
          /** Like defineExtension, but the method will be added to the interface for Doc objects instead. */
          defineDocExtension(name: string, value: any);
      
          /** Similarly, defineOption can be used to define new options for CodeMirror.
          The updateFunc will be called with the editor instance and the new value when an editor is initialized,
          and whenever the option is modified through setOption. */
          defineOption(name: string, default_: any, updateFunc: Function);
      
          /** If your extention just needs to run some code whenever a CodeMirror instance is initialized, use CodeMirror.defineInitHook.
          Give it a function as its only argument, and from then on, that function will be called (with the instance as argument)
          whenever a new CodeMirror instance is initialized. */
          defineInitHook(func: Function);
      
          normalizeKeyMap(keymap: any): any;
      
      
      
          on(element: any, eventName: string, handler: Function);
          off(element: any, eventName: string, handler: Function);
      
          /** Fired whenever a change occurs to the document. changeObj has a similar type as the object passed to the editor's "change" event,
          but it never has a next property, because document change events are not batched (whereas editor change events are). */
          on(doc: Doc, eventName: 'change', handler: (instance: Doc, change: EditorChange) => void);
          off(doc: Doc, eventName: 'change', handler: (instance: Doc, change: EditorChange) => void);
      
          /** See the description of the same event on editor instances. */
          on(doc: Doc, eventName: 'beforeChange', handler: (instance: Doc, change: EditorChangeCancellable) => void);
          off(doc: Doc, eventName: 'beforeChange', handler: (instance: Doc, change: EditorChangeCancellable) => void);
      
          /** Fired whenever the cursor or selection in this document changes. */
          on(doc: Doc, eventName: 'cursorActivity', handler: (instance: CodeMirror) => void);
          off(doc: Doc, eventName: 'cursorActivity', handler: (instance: CodeMirror) => void);
      
          /** Equivalent to the event by the same name as fired on editor instances. */
          on(doc: Doc, eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: Pos; anchor: Pos; }) => void);
          off(doc: Doc, eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: Pos; anchor: Pos; }) => void);
      
          /** Will be fired when the line object is deleted. A line object is associated with the start of the line.
          Mostly useful when you need to find out when your gutter markers on a given line are removed. */
          on(line: LineHandle, eventName: 'delete', handler: () => void);
          off(line: LineHandle, eventName: 'delete', handler: () => void);
      
          /** Fires when the line's text content is changed in any way (but the line is not deleted outright).
          The change object is similar to the one passed to change event on the editor object. */
          on(line: LineHandle, eventName: 'change', handler: (line: LineHandle, change: EditorChange) => void);
          off(line: LineHandle, eventName: 'change', handler: (line: LineHandle, change: EditorChange) => void);
      
          /** Fired when the cursor enters the marked range. From this event handler, the editor state may be inspected but not modified,
          with the exception that the range on which the event fires may be cleared. */
          on(marker: TextMarker, eventName: 'beforeCursorEnter', handler: () => void);
          off(marker: TextMarker, eventName: 'beforeCursorEnter', handler: () => void);
      
          /** Fired when the range is cleared, either through cursor movement in combination with clearOnEnter or through a call to its clear() method.
          Will only be fired once per handle. Note that deleting the range through text editing does not fire this event,
          because an undo action might bring the range back into existence. */
          on(marker: TextMarker, eventName: 'clear', handler: () => void);
          off(marker: TextMarker, eventName: 'clear', handler: () => void);
      
          /** Fired when the last part of the marker is removed from the document by editing operations. */
          on(marker: TextMarker, eventName: 'hide', handler: () => void);
          off(marker: TextMarker, eventName: 'hide', handler: () => void);
      
          /** Fired when, after the marker was removed by editing, a undo operation brought the marker back. */
          on(marker: TextMarker, eventName: 'unhide', handler: () => void);
          off(marker: TextMarker, eventName: 'unhide', handler: () => void);
      
          /** Fired whenever the editor re-adds the widget to the DOM. This will happen once right after the widget is added (if it is scrolled into view),
          and then again whenever it is scrolled out of view and back in again, or when changes to the editor options
          or the line the widget is on require the widget to be redrawn. */
          on(line: LineWidget, eventName: 'redraw', handler: () => void);
          off(line: LineWidget, eventName: 'redraw', handler: () => void);
        }
        
        export interface Doc {
      
          /** Get the current editor content. You can pass it an optional argument to specify the string to be used to separate lines (defaults to "\n"). */
          getValue(seperator?: string): string;
      
          /** Set the editor content. */
          setValue(content: string);
      
          /** Get the text between the given points in the editor, which should be {line, ch} objects.
          An optional third argument can be given to indicate the line separator string to use (defaults to "\n"). */
          getRange(from: Pos, to: CodeMirror.Pos, seperator?: string): string;
      
          /** Replace the part of the document between from and to with the given string.
          from and to must be {line, ch} objects. to can be left off to simply insert the string at position from. */
          replaceRange(replacement: string, from: CodeMirror.Pos, to: CodeMirror.Pos);
      
          /** Get the content of line n. */
          getLine(n: number): string;
      
          /** Set the content of line n. */
          setLine(n: number, text: string);
      
          /** Remove the given line from the document. */
          removeLine(n: number);
      
          /** Get the number of lines in the editor. */
          lineCount(): number;
      
          /** Get the first line of the editor. This will usually be zero but for linked sub-views,
          or documents instantiated with a non-zero first line, it might return other values. */
          firstLine(): number;
      
          /** Get the last line of the editor. This will usually be lineCount() - 1, but for linked sub-views, it might return other values. */
          lastLine(): number;
      
          /** Fetches the line handle for the given line number. */
          getLineHandle(num: number): CodeMirror.LineHandle;
      
          /** Given a line handle, returns the current position of that line (or null when it is no longer in the document). */
          getLineNumber(handle: CodeMirror.LineHandle): number;
      
          /** Iterate over the whole document, and call f for each line, passing the line handle.
          This is a faster way to visit a range of line handlers than calling getLineHandle for each of them.
          Note that line handles have a text property containing the line's content (as a string). */
          eachLine(f: (line: CodeMirror.LineHandle) => void);
      
          /** Iterate over the range from start up to (not including) end, and call f for each line, passing the line handle.
          This is a faster way to visit a range of line handlers than calling getLineHandle for each of them.
          Note that line handles have a text property containing the line's content (as a string). */
          eachLine(start: number, end: number, f: (line: CodeMirror.LineHandle) => void);
      
          /** Set the editor content as 'clean', a flag that it will retain until it is edited, and which will be set again when such an edit is undone again.
          Useful to track whether the content needs to be saved. */
          markClean();
      
          /** Returns whether the document is currently clean (not modified since initialization or the last call to markClean). */
          isClean(): boolean;
      
      
      
          /** Get the currently selected code. */
          getSelection(): string;
      
          /** Replace the selection with the given string. By default, the new selection will span the inserted text.
          The optional collapse argument can be used to change this passing "start" or "end" will collapse the selection to the start or end of the inserted text. */
          replaceSelection(replacement: string, collapse?: string)
      
          /** start is a an optional string indicating which end of the selection to return.
          It may be "start" , "end" , "head"(the side of the selection that moves when you press shift + arrow),
          or "anchor"(the fixed side of the selection).Omitting the argument is the same as passing "head".A { line , ch } object will be returned. */
          getCursor(start?: string): CodeMirror.Pos;
      
          /** Return true if any text is selected. */
          somethingSelected(): boolean;
      
          /** Set the cursor position.You can either pass a single { line , ch } object , or the line and the character as two separate parameters. */
          setCursor(pos: CodeMirror.Pos);
      
          /** Set the selection range.anchor and head should be { line , ch } objects.head defaults to anchor when not given. */
          setSelection(anchor: CodeMirror.Pos, head: CodeMirror.Pos);
      
          /** Similar to setSelection , but will, if shift is held or the extending flag is set,
          move the head of the selection while leaving the anchor at its current place.
          pos2 is optional , and can be passed to ensure a region (for example a word or paragraph) will end up selected
          (in addition to whatever lies between that region and the current anchor). */
          extendSelection(from: CodeMirror.Pos, to?: CodeMirror.Pos);
      
          /** Sets or clears the 'extending' flag , which acts similar to the shift key,
          in that it will cause cursor movement and calls to extendSelection to leave the selection anchor in place. */
          setExtending(value: boolean);
      
      
          /** Retrieve the editor associated with a document. May return null. */
          getEditor(): CodeMirror;
      
      
          /** Create an identical copy of the given doc. When copyHistory is true , the history will also be copied.Can not be called directly on an editor. */
          copy(copyHistory: boolean): CodeMirror.Doc;
      
          /** Create a new document that's linked to the target document. Linked documents will stay in sync (changes to one are also applied to the other) until unlinked. */
          linkedDoc(options: {
            /** When turned on, the linked copy will share an undo history with the original.
            Thus, something done in one of the two can be undone in the other, and vice versa. */
            sharedHist?: boolean;
            from?: number;
            /** Can be given to make the new document a subview of the original. Subviews only show a given range of lines.
            Note that line coordinates inside the subview will be consistent with those of the parent,
            so that for example a subview starting at line 10 will refer to its first line as line 10, not 0. */
            to?: number;
            /** By default, the new document inherits the mode of the parent. This option can be set to a mode spec to give it a different mode. */
            mode: any;
          }): CodeMirror.Doc;
      
          /** Break the link between two documents. After calling this , changes will no longer propagate between the documents,
          and, if they had a shared history, the history will become separate. */
          unlinkDoc(doc: CodeMirror.Doc);
      
          /** Will call the given function for all documents linked to the target document. It will be passed two arguments,
          the linked document and a boolean indicating whether that document shares history with the target. */
          iterLinkedDocs(fn: (doc: CodeMirror.Doc, sharedHist: boolean) => void);
      
          /** Undo one edit (if any undo events are stored). */
          undo();
      
          /** Redo one undone edit. */
          redo();
      
          /** Returns an object with {undo, redo } properties , both of which hold integers , indicating the amount of stored undo and redo operations. */
          historySize(): { undo: number; redo: number; };
      
          /** Clears the editor's undo history. */
          clearHistory();
      
          /** Get a(JSON - serializeable) representation of the undo history. */
          getHistory(): any;
      
          /** Replace the editor's undo history with the one provided, which must be a value as returned by getHistory.
          Note that this will have entirely undefined results if the editor content isn't also the same as it was when getHistory was called. */
          setHistory(history: any);
      
      
          /** Can be used to mark a range of text with a specific CSS class name. from and to should be { line , ch } objects. */
          markText(from: CodeMirror.Pos, to: CodeMirror.Pos, options?: CodeMirror.TextMarkerOptions): TextMarker;
      
          /** Inserts a bookmark, a handle that follows the text around it as it is being edited, at the given position.
          A bookmark has two methods find() and clear(). The first returns the current position of the bookmark, if it is still in the document,
          and the second explicitly removes the bookmark. */
          setBookmark(pos: CodeMirror.Pos, options?: {
            /** Can be used to display a DOM node at the current location of the bookmark (analogous to the replacedWith option to markText). */
            widget?: HTMLElement;
      
            /** By default, text typed when the cursor is on top of the bookmark will end up to the right of the bookmark.
            Set this option to true to make it go to the left instead. */
            insertLeft?: boolean;
          }): CodeMirror.TextMarker;
      
          /** Returns an array of all the bookmarks and marked ranges present at the given position. */
          findMarksAt(pos: CodeMirror.Pos): TextMarker[];
      
          /** Returns an array containing all marked ranges in the document. */
          getAllMarks(): CodeMirror.TextMarker[];
      
      
          /** Gets the mode object for the editor. Note that this is distinct from getOption("mode"), which gives you the mode specification,
          rather than the resolved, instantiated mode object. */
          getMode(): any;
      
          /** Calculates and returns a { line , ch } object for a zero-based index whose value is relative to the start of the editor's text.
          If the index is out of range of the text then the returned object is clipped to start or end of the text respectively. */
          posFromIndex(index: number): CodeMirror.Pos;
      
          /** The reverse of posFromIndex. */
          indexFromPos(object: CodeMirror.Pos): number;
      
        }
      
        export interface LineHandle {
          text: string;
        }
      
        export interface TextMarker {
          /** Remove the mark. */
          clear();
      
          /** Returns a {from, to} object (both holding document positions), indicating the current position of the marked range,
          or undefined if the marker is no longer in the document. */
          find(): { from: CodeMirror.Pos; to: CodeMirror.Pos; };
      
          /**  Returns an object representing the options for the marker. If copyWidget is given true, it will clone the value of the replacedWith option, if any. */
          getOptions(copyWidget: boolean): CodeMirror.TextMarkerOptions;
        }
      
        export interface LineWidget {
          /** Removes the widget. */
          clear(): void;
      
          /** Call this if you made some change to the widget's DOM node that might affect its height.
          It'll force CodeMirror to update the height of the line that contains the widget. */
          changed();
        }
      
        export interface EditorChange {
          /** Position (in the pre-change coordinate system) where the change started. */
          from: CodeMirror.Pos;
          /** Position (in the pre-change coordinate system) where the change ended. */
          to: CodeMirror.Pos;
          /** Array of strings representing the text that replaced the changed range (split by line). */
          text: string[];
          /**  Text that used to be between from and to, which is overwritten by this change. */
          removed: string[];
        }
      
        export interface EditorChangeCancellable extends CodeMirror.EditorChange {
          /** may be used to modify the change. All three arguments to update are optional, and can be left off to leave the existing value for that field intact. */
          update(from?: CodeMirror.Pos, to?: CodeMirror.Pos, text?: string);
      
          cancel();
        }
      
        export interface Pos {
          ch: number;
          line: number;
        }
      
        export interface Options {
          /** string| The starting value of the editor. Can be a string, or a document object. */
          value?: any;
      
          /** string|object. The mode to use. When not given, this will default to the first mode that was loaded.
          It may be a string, which either simply names the mode or is a MIME type associated with the mode.
          Alternatively, it may be an object containing configuration options for the mode,
          with a name property that names the mode (for example {name: "javascript", json: true}). */
          mode?: any;
      
          /** The theme to style the editor with. You must make sure the CSS file defining the corresponding .cm-s-[name] styles is loaded.
          The default is "default". */
          theme?: string;
      
          /** How many spaces a block (whatever that means in the edited language) should be indented. The default is 2. */
          indentUnit?: number;
      
          /** Whether to use the context-sensitive indentation that the mode provides (or just indent the same as the line before). Defaults to true. */
          smartIndent?: boolean;
      
          /** The width of a tab character. Defaults to 4. */
          tabSize?: number;
      
          /** Whether, when indenting, the first N*tabSize spaces should be replaced by N tabs. Default is false. */
          indentWithTabs?: boolean;
      
          /** Configures whether the editor should re-indent the current line when a character is typed
          that might change its proper indentation (only works if the mode supports indentation). Default is true. */
          electricChars?: boolean;
      
          /** Determines whether horizontal cursor movement through right-to-left (Arabic, Hebrew) text
          is visual (pressing the left arrow moves the cursor left)
          or logical (pressing the left arrow moves to the next lower index in the string, which is visually right in right-to-left text).
          The default is false on Windows, and true on other platforms. */
          rtlMoveVisually?: boolean;
      
          /** Configures the keymap to use. The default is "default", which is the only keymap defined in codemirror.js itself.
          Extra keymaps are found in the keymap directory. See the section on keymaps for more information. */
          keyMap?: string;
      
          /** Can be used to specify extra keybindings for the editor, alongside the ones defined by keyMap. Should be either null, or a valid keymap value. */
          extraKeys?: any;
      
          /** Whether CodeMirror should scroll or wrap for long lines. Defaults to false (scroll). */
          lineWrapping?: boolean;
      
          /** Whether to show line numbers to the left of the editor. */
          lineNumbers?: boolean;
      
          /** At which number to start counting lines. Default is 1. */
          firstLineNumber?: number;
      
          /** A function used to format line numbers. The function is passed the line number, and should return a string that will be shown in the gutter. */
          lineNumberFormatter?: (line: number) => string;
      
          /** Can be used to add extra gutters (beyond or instead of the line number gutter).
          Should be an array of CSS class names, each of which defines a width (and optionally a background),
          and which will be used to draw the background of the gutters.
          May include the CodeMirror-linenumbers class, in order to explicitly set the position of the line number gutter
          (it will default to be to the right of all other gutters). These class names are the keys passed to setGutterMarker. */
          gutters?: string[];
      
          /** Determines whether the gutter scrolls along with the content horizontally (false)
          or whether it stays fixed during horizontal scrolling (true, the default). */
          fixedGutter?: boolean;
      
          /** boolean|string. This disables editing of the editor content by the user. If the special value "nocursor" is given (instead of simply true), focusing of the editor is also disallowed. */
          readOnly?: any;
      
          /**Whether the cursor should be drawn when a selection is active. Defaults to false. */
          showCursorWhenSelecting?: boolean;
      
          /** The maximum number of undo levels that the editor stores. Defaults to 40. */
          undoDepth?: number;
      
          /** The period of inactivity (in milliseconds) that will cause a new history event to be started when typing or deleting. Defaults to 500. */
          historyEventDelay?: number;
      
          /** The tab index to assign to the editor. If not given, no tab index will be assigned. */
          tabindex?: number;
      
          /** Can be used to make CodeMirror focus itself on initialization. Defaults to off.
          When fromTextArea is used, and no explicit value is given for this option, it will be set to true when either the source textarea is focused,
          or it has an autofocus attribute and no other element is focused. */
          autofocus?: boolean;
      
          /** Controls whether drag-and - drop is enabled. On by default. */
          dragDrop?: boolean;
      
          /** When given , this will be called when the editor is handling a dragenter , dragover , or drop event.
          It will be passed the editor instance and the event object as arguments.
          The callback can choose to handle the event itself , in which case it should return true to indicate that CodeMirror should not do anything further. */
          onDragEvent?: (instance: CodeMirror, event: Event) => boolean;
      
          /** This provides a rather low - level hook into CodeMirror's key handling.
          If provided, this function will be called on every keydown, keyup, and keypress event that CodeMirror captures.
          It will be passed two arguments, the editor instance and the key event.
          This key event is pretty much the raw key event, except that a stop() method is always added to it.
          You could feed it to, for example, jQuery.Event to further normalize it.
          This function can inspect the key event, and handle it if it wants to.
          It may return true to tell CodeMirror to ignore the event.
          Be wary that, on some browsers, stopping a keydown does not stop the keypress from firing, whereas on others it does.
          If you respond to an event, you should probably inspect its type property and only do something when it is keydown
          (or keypress for actions that need character data). */
          onKeyEvent?: (instance: CodeMirror, event: Event) => boolean;
      
          /** Half - period in milliseconds used for cursor blinking. The default blink rate is 530ms. */
          cursorBlinkRate?: number;
      
          /** Determines the height of the cursor. Default is 1 , meaning it spans the whole height of the line.
          For some fonts (and by some tastes) a smaller height (for example 0.85),
          which causes the cursor to not reach all the way to the bottom of the line, looks better */
          cursorHeight?: number;
      
          /** Highlighting is done by a pseudo background - thread that will work for workTime milliseconds,
          and then use timeout to sleep for workDelay milliseconds.
          The defaults are 200 and 300, you can change these options to make the highlighting more or less aggressive. */
          workTime?: number;
      
          /** See workTime. */
          workDelay?: number;
      
          /** Indicates how quickly CodeMirror should poll its input textarea for changes(when focused).
          Most input is captured by events, but some things, like IME input on some browsers, don't generate events that allow CodeMirror to properly detect it.
          Thus, it polls. Default is 100 milliseconds. */
          pollInterval?: number
      
              /** By default, CodeMirror will combine adjacent tokens into a single span if they have the same class.
              This will result in a simpler DOM tree, and thus perform better. With some kinds of styling(such as rounded corners),
              this will change the way the document looks. You can set this option to false to disable this behavior. */
              flattenSpans?: boolean;
      
          /** When highlighting long lines, in order to stay responsive, the editor will give up and simply style
          the rest of the line as plain text when it reaches a certain position. The default is 10000.
          You can set this to Infinity to turn off this behavior. */
          maxHighlightLength?: number;
      
          /** Specifies the amount of lines that are rendered above and below the part of the document that's currently scrolled into view.
          This affects the amount of updates needed when scrolling, and the amount of work that such an update does.
          You should usually leave it at its default, 10. Can be set to Infinity to make sure the whole document is always rendered,
          and thus the browser's text search works on it. This will have bad effects on performance of big documents. */
          viewportMargin?: number;
        }
      
        export interface TextMarkerOptions {
          /** Assigns a CSS class to the marked stretch of text. */
          className?: string;
      
          /** Determines whether text inserted on the left of the marker will end up inside or outside of it. */
          inclusiveLeft?: boolean;
      
          /** Like inclusiveLeft , but for the right side. */
          inclusiveRight?: boolean;
      
          /** Atomic ranges act as a single unit when cursor movement is concerned i.e. it is impossible to place the cursor inside of them.
          In atomic ranges, inclusiveLeft and inclusiveRight have a different meaning they will prevent the cursor from being placed
          respectively directly before and directly after the range. */
          atomic?: boolean;
      
          /** Collapsed ranges do not show up in the display.Setting a range to be collapsed will automatically make it atomic. */
          collapsed?: boolean;
      
          /** When enabled, will cause the mark to clear itself whenever the cursor enters its range.
          This is mostly useful for text - replacement widgets that need to 'snap open' when the user tries to edit them.
          The "clear" event fired on the range handle can be used to be notified when this happens. */
          clearOnEnter?: boolean;
      
          /** Use a given node to display this range.Implies both collapsed and atomic.
          The given DOM node must be an inline element(as opposed to a block element). */
          replacedWith?: HTMLElement;
      
          /** A read - only span can, as long as it is not cleared, not be modified except by calling setValue to reset the whole document.
          Note: adding a read - only span currently clears the undo history of the editor,
          because existing undo events being partially nullified by read - only spans would corrupt the history (in the current implementation). */
          readOnly?: boolean;
      
          /** When set to true (default is false), adding this marker will create an event in the undo history that can be individually undone(clearing the marker). */
          addToHistory?: boolean;
      
          /** Can be used to specify an extra CSS class to be applied to the leftmost span that is part of the marker. */
          startStyle?: string;
      
          /** Equivalent to startStyle, but for the rightmost span. */
          endStyle?: string;
      
          /** When the target document is linked to other documents, you can set shared to true to make the marker appear in all documents.
          By default, a marker appears only in its target document. */
          shared?: boolean;
        }
      }
    • github.d.ts
      /**
       * See https://github.com/michael/github
       */
      declare class Github {
      
        constructor(config: {
          username?: string;
          password?: string;
          token?: string;
          auth?: string;
        });
      
        constructor(config: {
          token?: string;
          auth?: string;
        });
      
        getRepo(username?: string, password?: string): Github.Repo;
      
      }
      
      declare module Github {
      
        export interface Repo {
      
          show(callback: (error: Error, repo: any) => void): void;
      
          deleteRepo(callback: (error: Error, res: any) => void): void;
      
          contents(branch: string, pathToDir: string, callback: (err: Error, contents: any) => void, sync?: boolean);
      
          fork(callback: (err: Error) => void): void;
          
          branch(oldBranchName: string, newBranchName: string, callback: (err: Error) => void);
      
        	createPullRequest(pull: PullRequest, callback: (err: Error, pullRequest: any) => void);
      
          listBranches(callback: (error: Error, braches: any) => void);
      
          write(branch: string, pathToFile: string, contents: string, commitMessage: string, callback: (err: Error) => void);
          
          read(master: string, pathToFile: string, callback: (err, data) => void);
          
          move(branch: string, pathToFile: string, pathToNewFile: string, callback: (err: Error) => void);
      
          remove(branch: string, pathToFile: string, callback: (err: Error) => void);
          
          /** also try branch like master?recursive=true */
          getTree(branch: string, callback: (err: Error, tree: any) => void);
          
          getSha(branch: string, pathToFile: string, callback: (err, sha) => void);
          
      
        }
        
        export interface PullRequest {
          title: string;
          body: string;
          base: string;
          head: string;
        }
      
      }
    • knockout.d.ts
      // Type definitions for Knockout 2.3
      // Project: http://knockoutjs.com
      // Definitions by: Boris Yankov <https://github.com/borisyankov/>
      // Definitions: https://github.com/borisyankov/DefinitelyTyped
      
      
      declare module ko {
      
        export module utils {
      
          //////////////////////////////////
          // utils.domManipulation.js
          //////////////////////////////////
      
          export function simpleHtmlParse(html: string): any[];
      
          export function jQueryHtmlParse(html: string): any[];
      
          export function parseHtmlFragment(html: string): any[];
      
          export function setHtml(node: Element, html: string): void;
      
          export function setHtml(node: Element, html: () => string): void;
      
          //////////////////////////////////
          // utils.domData.js
          //////////////////////////////////
      
          export module domData {
            export function get(node: Element, key: string): any;
      
            export function set(node: Element, key: string, value: any): void;
      
            export function getAll(node: Element, createIfNotFound: boolean): any;
      
            export function clear(node: Element): boolean;
          }
      
          //////////////////////////////////
          // utils.domNodeDisposal.js
          //////////////////////////////////
      
          export module domNodeDisposal {
            export function addDisposeCallback(node: Element, callback: Function): void;
      
            export function removeDisposeCallback(node: Element, callback: Function): void;
      
            export function cleanNode(node: Element): Element;
      
            export function removeNode(node: Element): void;
          }
      
          //////////////////////////////////
          // utils.js
          //////////////////////////////////
      
          export var fieldsIncludedWithJsonPost: any[];
      
          export function compareArrays<T>(a: T[], b: T[]): Array<KnockoutArrayChange<T>>;
      
          export function arrayForEach<T>(array: T[], action: (item: T) => void): void;
      
          export function arrayIndexOf<T>(array: T[], item: T): number;
      
          export function arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;
      
          export function arrayRemoveItem(array: any[], itemToRemove: any): void;
      
          export function arrayGetDistinctValues<T>(array: T[]): T[];
      
          export function arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
      
          export function arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
      
          export function arrayPushAll<T>(array: T[], valuesToPush: T[]): T[];
      
          export function arrayPushAll<T>(array: ObservableArray<T>, valuesToPush: T[]): T[];
      
          export function extend(target: Object, source: Object): Object;
      
          export function emptyDomNode(domNode: HTMLElement): void;
      
          export function moveCleanedNodesToContainerElement(nodes: any[]): HTMLElement;
      
          export function cloneNodes(nodesArray: any[], shouldCleanNodes: boolean): any[];
      
          export function setDomNodeChildren(domNode: any, childNodes: any[]): void;
      
          export function replaceDomNodes(nodeToReplaceOrNodeArray: any, newNodesArray: any[]): void;
      
          export function setOptionNodeSelectionState(optionNode: any, isSelected: boolean): void;
      
          export function stringTrim(str: string): string;
      
          export function stringTokenize(str: string, delimiter: string): string;
      
          export function stringStartsWith(str: string, startsWith: string): string;
      
          export function domNodeIsContainedBy(node: any, containedByNode: any): boolean;
      
          export function domNodeIsAttachedToDocument(node: any): boolean;
      
          export function tagNameLower(element: any): string;
      
          export function registerEventHandler(element: any, eventType: any, handler: Function): void;
      
          export function triggerEvent(element: any, eventType: any): void;
      
          export function unwrapObservable<T>(value: Observable<T>): T;
      
          export function peekObservable<T>(value: Observable<T>): T;
      
          export function toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void;
      
          //setTextContent(element: any, textContent: string): void; // NOT PART OF THE MINIFIED API SURFACE (ONLY IN knockout-{version}.debug.js) https://github.com/SteveSanderson/knockout/issues/670
      
          export function setElementName(element: any, name: string): void;
      
          export function forceRefresh(node: any): void;
      
          export function ensureSelectElementIsRenderedCorrectly(selectElement: any): void;
      
          export function range(min: any, max: any): any;
      
          export function makeArray(arrayLikeObject: any): any[];
      
          export function getFormFields(form: any, fieldName: string): any[];
      
          export function parseJson(jsonString: string): any;
      
          export function stringifyJson(data: any, replacer: Function, space: string): string;
      
          export function postJson(urlOrForm: any, data: any, options: any): void;
      
          export var ieVersion: number;
      
          export var isIe6: boolean;
      
          export var isIe7: boolean;
        }
      
        export module memoization {
      
        }
      
        export module bindingHandlers {
      
          // Controlling text and appearance
          export var visible: BindingHandler;
          export var text: BindingHandler;
          export var html: BindingHandler;
          export var css: BindingHandler;
          export var style: BindingHandler;
          export var attr: BindingHandler;
      
          // Control Flow
          export var foreach: BindingHandler;
          export var ifnot: BindingHandler;
      
          /*export var if: BindingHandler;*/
          /*export var with: BindingHandler;*/
      
          // Working with form fields
          export var click: BindingHandler;
          export var event: BindingHandler;
          export var submit: BindingHandler;
          export var enable: BindingHandler;
          export var disable: BindingHandler;
          export var value: BindingHandler;
          export var hasfocus: BindingHandler;
          export var checked: BindingHandler;
          export var options: BindingHandler;
          export var selectedOptions: BindingHandler;
          export var uniqueName: BindingHandler;
      
          // Rendering templates
          export var template: BindingHandler;
        }
      
        export module virtualElements {
        }
      
        export module extenders {
          export function throttle(target: any, timeout: number): ko.Computed<any>;
          export function notify(target: any, notifyWhen: string): any;
        }
      
        export function applyBindings(viewModel: any, rootNode?: any): void;
        export function applyBindingsToDescendants(viewModel: any, rootNode: any): void;
        export function applyBindingsToNode(node: Element, options: any, viewModel: any): void;
      
        export interface subscribable<T> extends subscribable.CustomFunctions<T> {
          subscribe(callback: (newValue: T) => void, target?: any, event?: string): Disposable;
          subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): Disposable;
          extend(requestedExtenders: { [key: string]: any; }): subscribable<T>;
          getSubscriptionsCount(): number;
        }
      
        export module subscribable {
      
          export var fn: CustomFunctions<any>;
      
          export interface CustomFunctions<T> {
            notifySubscribers(valueToWrite: T, event?: string): void;
          }
      
        }
      
        export interface Disposable {
          dispose(): void;
        }
      
        export function observable<T>(value?: T): Observable<T>;
      
        export interface Observable<T> extends observable.CustomFunctions, subscribable<T> {
      
          (): T;
          (value: T): void;
      
          peek(): T;
          valueHasMutated(): void;
          valueWillMutate(): void;
          extend(requestedExtenders: { [key: string]: any; }): Observable<T>;
        }
      
        export module observable {
      
          export var fn: CustomFunctions;
      
          export interface CustomFunctions {
            equalityComparer(a: any, b: any): boolean;
          }
        }
      
      
      
        export function computed<T>(): Computed<T>;
        export function computed<T>(read: () => T, context?: any, options?: any): Computed<T>;
        export function computed<T>(definition: computed.Definition<T>): Computed<T>;
        export function computed(options?: any): Computed<any>;
      
        export interface Computed<T> extends subscribable<T> {
          (): T;
          (value: T): void;
      
          peek(): T;
          dispose(): void;
          isActive(): boolean;
          getDependenciesCount(): number;
          extend(requestedExtenders: { [key: string]: any; }): Computed<T>;
        }
      
        export module computed {
      
          export var fn: CustomFunctions;
      
          export interface CustomFunctions {
          }
      
          export interface Definition<T> {
            read(): T;
            write? (value: T): void;
            disposeWhenNodeIsRemoved?: Node;
            disposeWhen? (): boolean;
            owner?: any;
            deferEvaluation?: boolean;
          }
        }
      
      
      
        export function observableArray<T>(value?: T[]): ObservableArray<T>;
      
        export interface ObservableArray<T> extends Observable<T[]>, observableArray.CustomFunctions<T> {
        }
      
        export module observableArray {
      
          export var fn: CustomFunctions<any>;
      
          export interface CustomFunctions<T> {
            indexOf(searchElement: T, fromIndex?: number): number;
            slice(start: number, end?: number): T[];
            splice(start: number): T[];
            splice(start: number, deleteCount: number, ...items: T[]): T[];
            pop(): T;
            push(...items: T[]): void;
            shift(): T;
            unshift(...items: T[]): number;
            reverse(): T[];
            sort(): void;
            sort(compareFunction: (left: T, right: T) => number): void;
      
            // Ko specific
            replace(oldItem: T, newItem: T): void;
      
            remove(item: T): T[];
            remove(removeFunction: (item: T) => boolean): T[];
            removeAll(items: T[]): T[];
            removeAll(): T[];
      
            destroy(item: T): void;
            destroyAll(items: T[]): void;
            destroyAll(): void;
          }
        }
      
        export function contextFor(node: any): any;
        export function isSubscribable(instance: any): boolean;
        export function toJSON(viewModel: any, replacer?: Function, space?: any): string;
        export function toJS(viewModel: any): any;
        export function isObservable(instance: any): boolean;
        export function isWriteableObservable(instance: any): boolean;
        export function isComputed(instance: any): boolean;
        export function dataFor(node: any): any;
        export function removeNode(node: Element): void;
        export function cleanNode(node: Element): Element;
        export function renderTemplate(template: Function, viewModel: any, options?: any, target?: any, renderMode?: any): any;
        export function renderTemplate(template: string, viewModel: any, options?: any, target?: any, renderMode?: any): any;
        export function unwrap(value: any): any;
      
        export module templateSources /* KnockoutTemplateSources */ {
      
        }
      
      
        export class templateEngine extends nativeTemplateEngine {
      
          createJavaScriptEvaluatorBlock(script: string): string;
      
          makeTemplateSource(template: any, templateDocument?: Document): any;
      
          renderTemplate(template: any, bindingContext: BindingContext, options: Object, templateDocument: Document): any;
      
          isTemplateRewritten(template: any, templateDocument: Document): boolean;
      
          rewriteTemplate(template: any, rewriterCallback: Function, templateDocument: Document): void;
      
        }
      
        //////////////////////////////////
        // templateRewriting.js
        //////////////////////////////////
      
        export module templateRewriting {
      
          export function ensureTemplateIsRewritten(template: Node, templateEngine: templateEngine, templateDocument: Document): any;
          export function ensureTemplateIsRewritten(template: string, templateEngine: templateEngine, templateDocument: Document): any;
      
          export function memoizeBindingAttributeSyntax(htmlString: string, templateEngine: templateEngine): any;
      
          export function applyMemoizedBindingsToNextSibling(bindings: any, nodeName: string): string;
        }
      
        //////////////////////////////////
        // nativeTemplateEngine.js
        //////////////////////////////////
      
        export class nativeTemplateEngine {
          renderTemplateSource(templateSource: Object, bindingContext?: BindingContext, options?: Object): any[];
        }
      
        //////////////////////////////////
        // jqueryTmplTemplateEngine.js
        //////////////////////////////////
      
        export class jqueryTmplTemplateEngine extends templateEngine {
      
          renderTemplateSource(templateSource: Object, bindingContext: BindingContext, options: Object): Node[];
      
          createJavaScriptEvaluatorBlock(script: string): string;
      
          addTemplate(templateName: string, templateMarkup: string): void;
      
        }
      
        //////////////////////////////////
        // templating.js
        //////////////////////////////////
      
        export function setTemplateEngine(templateEngine: nativeTemplateEngine): void;
      
        export function renderTemplate(template: Function, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
      
        export function renderTemplateForEach(template: Function, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: any, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: Function, arrayOrObservableArray: Observable<any>, options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: any, arrayOrObservableArray: Observable<any>, options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
      
        export module expressionRewriting {
          export var bindingRewriteValidators: any;
        }
      
        /////////////////////////////////
      
        export module bindingProvider {
      
        }
      
        /////////////////////////////////
        // selectExtensions.js
        /////////////////////////////////
      
        export module selectExtensions {
      
          export function readValue(element: HTMLElement): any;
      
          export function writeValue(element: HTMLElement, value: any): void;
        }
      
        export interface BindingContext {
          $parent: any;
          $parents: any[];
          $root: any;
          $data: any;
          $index?: number;
          $parentContext?: BindingContext;
      
          extend(properties: any): any;
          createChildContext(dataItemOrAccessor: any, dataItemAlias?: any, extendCallback?: Function): any;
        }
      
        export interface BindingHandler {
          init? (element: any, valueAccessor: () => any, allBindingsAccessor: () => any, viewModel: any, bindingContext: BindingContext): void;
          update? (element: any, valueAccessor: () => any, allBindingsAccessor: () => any, viewModel: any, bindingContext: BindingContext): void;
          options?: any;
        }
      
      }
      
      
      
      interface KnockoutMemoization {
          memoize(callback: () => string): string;
          unmemoize(memoId: string, callbackParams: any[]): boolean;
          unmemoizeDomNodeAndDescendants(domNode: any, extraCallbackParamsArray: any[]): boolean;
          parseMemoText(memoText: string): string;
      }
      
      interface KnockoutVirtualElement {}
      
      interface KnockoutVirtualElements {
      	allowedBindings: { [bindingName: string]: boolean; };
          emptyNode(node: KnockoutVirtualElement ): void;
          firstChild(node: KnockoutVirtualElement ): KnockoutVirtualElement;
      	insertAfter( container: KnockoutVirtualElement, nodeToInsert: HTMLElement, insertAfter: HTMLElement ): void;
          nextSibling(node: KnockoutVirtualElement): HTMLElement;
          prepend(node: KnockoutVirtualElement, toInsert: HTMLElement ): void;
          setDomNodeChildren(node: KnockoutVirtualElement, newChildren: { length: number;[index: number]: HTMLElement; } ): void;
          childNodes(node: KnockoutVirtualElement ): HTMLElement[];
      }
      
      
      
      interface KnockoutArrayChange<T> {
          status: string;
          value: T;
          index: number;
      }
      
      //////////////////////////////////
      // templateSources.js
      //////////////////////////////////
      
      interface KnockoutTemplateSourcesDomElement {
      
          text(valueToWrite?: any): any;
      
          data(key: string, valueToWrite?: any): any;
      }
      
      
      interface KnockoutTemplateSources {
      
        domElement: KnockoutTemplateSourcesDomElement;
      
        anonymousTemplate: {
      
          prototype: KnockoutTemplateSourcesDomElement;
      
          new (element: Element): KnockoutTemplateSourcesDomElement;
        };
      }
      
      
      
      declare module "knockout" {
      	export = ko;
      }
      
    • marked.d.ts
      declare var marked;
    • typescriptServices.d.ts
      /*! *****************************************************************************
      Copyright (c) Microsoft Corporation. All rights reserved. 
      Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      this file except in compliance with the License. You may obtain a copy of the
      License at http://www.apache.org/licenses/LICENSE-2.0  
       
      THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
      KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
      WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
      MERCHANTABLITY OR NON-INFRINGEMENT. 
       
      See the Apache Version 2.0 License for specific language governing permissions
      and limitations under the License.
      ***************************************************************************** */
      
      declare module ts {
          interface Map<T> {
              [index: string]: T;
          }
          interface TextRange {
              pos: number;
              end: number;
          }
          const enum SyntaxKind {
              Unknown = 0,
              EndOfFileToken = 1,
              SingleLineCommentTrivia = 2,
              MultiLineCommentTrivia = 3,
              NewLineTrivia = 4,
              WhitespaceTrivia = 5,
              ConflictMarkerTrivia = 6,
              NumericLiteral = 7,
              StringLiteral = 8,
              RegularExpressionLiteral = 9,
              NoSubstitutionTemplateLiteral = 10,
              TemplateHead = 11,
              TemplateMiddle = 12,
              TemplateTail = 13,
              OpenBraceToken = 14,
              CloseBraceToken = 15,
              OpenParenToken = 16,
              CloseParenToken = 17,
              OpenBracketToken = 18,
              CloseBracketToken = 19,
              DotToken = 20,
              DotDotDotToken = 21,
              SemicolonToken = 22,
              CommaToken = 23,
              LessThanToken = 24,
              GreaterThanToken = 25,
              LessThanEqualsToken = 26,
              GreaterThanEqualsToken = 27,
              EqualsEqualsToken = 28,
              ExclamationEqualsToken = 29,
              EqualsEqualsEqualsToken = 30,
              ExclamationEqualsEqualsToken = 31,
              EqualsGreaterThanToken = 32,
              PlusToken = 33,
              MinusToken = 34,
              AsteriskToken = 35,
              SlashToken = 36,
              PercentToken = 37,
              PlusPlusToken = 38,
              MinusMinusToken = 39,
              LessThanLessThanToken = 40,
              GreaterThanGreaterThanToken = 41,
              GreaterThanGreaterThanGreaterThanToken = 42,
              AmpersandToken = 43,
              BarToken = 44,
              CaretToken = 45,
              ExclamationToken = 46,
              TildeToken = 47,
              AmpersandAmpersandToken = 48,
              BarBarToken = 49,
              QuestionToken = 50,
              ColonToken = 51,
              EqualsToken = 52,
              PlusEqualsToken = 53,
              MinusEqualsToken = 54,
              AsteriskEqualsToken = 55,
              SlashEqualsToken = 56,
              PercentEqualsToken = 57,
              LessThanLessThanEqualsToken = 58,
              GreaterThanGreaterThanEqualsToken = 59,
              GreaterThanGreaterThanGreaterThanEqualsToken = 60,
              AmpersandEqualsToken = 61,
              BarEqualsToken = 62,
              CaretEqualsToken = 63,
              Identifier = 64,
              BreakKeyword = 65,
              CaseKeyword = 66,
              CatchKeyword = 67,
              ClassKeyword = 68,
              ConstKeyword = 69,
              ContinueKeyword = 70,
              DebuggerKeyword = 71,
              DefaultKeyword = 72,
              DeleteKeyword = 73,
              DoKeyword = 74,
              ElseKeyword = 75,
              EnumKeyword = 76,
              ExportKeyword = 77,
              ExtendsKeyword = 78,
              FalseKeyword = 79,
              FinallyKeyword = 80,
              ForKeyword = 81,
              FunctionKeyword = 82,
              IfKeyword = 83,
              ImportKeyword = 84,
              InKeyword = 85,
              InstanceOfKeyword = 86,
              NewKeyword = 87,
              NullKeyword = 88,
              ReturnKeyword = 89,
              SuperKeyword = 90,
              SwitchKeyword = 91,
              ThisKeyword = 92,
              ThrowKeyword = 93,
              TrueKeyword = 94,
              TryKeyword = 95,
              TypeOfKeyword = 96,
              VarKeyword = 97,
              VoidKeyword = 98,
              WhileKeyword = 99,
              WithKeyword = 100,
              AsKeyword = 101,
              ImplementsKeyword = 102,
              InterfaceKeyword = 103,
              LetKeyword = 104,
              PackageKeyword = 105,
              PrivateKeyword = 106,
              ProtectedKeyword = 107,
              PublicKeyword = 108,
              StaticKeyword = 109,
              YieldKeyword = 110,
              AnyKeyword = 111,
              BooleanKeyword = 112,
              ConstructorKeyword = 113,
              DeclareKeyword = 114,
              GetKeyword = 115,
              ModuleKeyword = 116,
              RequireKeyword = 117,
              NumberKeyword = 118,
              SetKeyword = 119,
              StringKeyword = 120,
              SymbolKeyword = 121,
              TypeKeyword = 122,
              FromKeyword = 123,
              OfKeyword = 124,
              QualifiedName = 125,
              ComputedPropertyName = 126,
              TypeParameter = 127,
              Parameter = 128,
              PropertySignature = 129,
              PropertyDeclaration = 130,
              MethodSignature = 131,
              MethodDeclaration = 132,
              Constructor = 133,
              GetAccessor = 134,
              SetAccessor = 135,
              CallSignature = 136,
              ConstructSignature = 137,
              IndexSignature = 138,
              TypeReference = 139,
              FunctionType = 140,
              ConstructorType = 141,
              TypeQuery = 142,
              TypeLiteral = 143,
              ArrayType = 144,
              TupleType = 145,
              UnionType = 146,
              ParenthesizedType = 147,
              ObjectBindingPattern = 148,
              ArrayBindingPattern = 149,
              BindingElement = 150,
              ArrayLiteralExpression = 151,
              ObjectLiteralExpression = 152,
              PropertyAccessExpression = 153,
              ElementAccessExpression = 154,
              CallExpression = 155,
              NewExpression = 156,
              TaggedTemplateExpression = 157,
              TypeAssertionExpression = 158,
              ParenthesizedExpression = 159,
              FunctionExpression = 160,
              ArrowFunction = 161,
              DeleteExpression = 162,
              TypeOfExpression = 163,
              VoidExpression = 164,
              PrefixUnaryExpression = 165,
              PostfixUnaryExpression = 166,
              BinaryExpression = 167,
              ConditionalExpression = 168,
              TemplateExpression = 169,
              YieldExpression = 170,
              SpreadElementExpression = 171,
              OmittedExpression = 172,
              TemplateSpan = 173,
              Block = 174,
              VariableStatement = 175,
              EmptyStatement = 176,
              ExpressionStatement = 177,
              IfStatement = 178,
              DoStatement = 179,
              WhileStatement = 180,
              ForStatement = 181,
              ForInStatement = 182,
              ForOfStatement = 183,
              ContinueStatement = 184,
              BreakStatement = 185,
              ReturnStatement = 186,
              WithStatement = 187,
              SwitchStatement = 188,
              LabeledStatement = 189,
              ThrowStatement = 190,
              TryStatement = 191,
              DebuggerStatement = 192,
              VariableDeclaration = 193,
              VariableDeclarationList = 194,
              FunctionDeclaration = 195,
              ClassDeclaration = 196,
              InterfaceDeclaration = 197,
              TypeAliasDeclaration = 198,
              EnumDeclaration = 199,
              ModuleDeclaration = 200,
              ModuleBlock = 201,
              CaseBlock = 202,
              ImportEqualsDeclaration = 203,
              ImportDeclaration = 204,
              ImportClause = 205,
              NamespaceImport = 206,
              NamedImports = 207,
              ImportSpecifier = 208,
              ExportAssignment = 209,
              ExportDeclaration = 210,
              NamedExports = 211,
              ExportSpecifier = 212,
              ExternalModuleReference = 213,
              CaseClause = 214,
              DefaultClause = 215,
              HeritageClause = 216,
              CatchClause = 217,
              PropertyAssignment = 218,
              ShorthandPropertyAssignment = 219,
              EnumMember = 220,
              SourceFile = 221,
              SyntaxList = 222,
              Count = 223,
              FirstAssignment = 52,
              LastAssignment = 63,
              FirstReservedWord = 65,
              LastReservedWord = 100,
              FirstKeyword = 65,
              LastKeyword = 124,
              FirstFutureReservedWord = 102,
              LastFutureReservedWord = 110,
              FirstTypeNode = 139,
              LastTypeNode = 147,
              FirstPunctuation = 14,
              LastPunctuation = 63,
              FirstToken = 0,
              LastToken = 124,
              FirstTriviaToken = 2,
              LastTriviaToken = 6,
              FirstLiteralToken = 7,
              LastLiteralToken = 10,
              FirstTemplateToken = 10,
              LastTemplateToken = 13,
              FirstBinaryOperator = 24,
              LastBinaryOperator = 63,
              FirstNode = 125,
          }
          const enum NodeFlags {
              Export = 1,
              Ambient = 2,
              Public = 16,
              Private = 32,
              Protected = 64,
              Static = 128,
              Default = 256,
              MultiLine = 512,
              Synthetic = 1024,
              DeclarationFile = 2048,
              Let = 4096,
              Const = 8192,
              OctalLiteral = 16384,
              Modifier = 499,
              AccessibilityModifier = 112,
              BlockScoped = 12288,
          }
          const enum ParserContextFlags {
              StrictMode = 1,
              DisallowIn = 2,
              Yield = 4,
              GeneratorParameter = 8,
              ThisNodeHasError = 16,
              ParserGeneratedFlags = 31,
              ThisNodeOrAnySubNodesHasError = 32,
              HasAggregatedChildData = 64,
          }
          const enum RelationComparisonResult {
              Succeeded = 1,
              Failed = 2,
              FailedAndReported = 3,
          }
          interface Node extends TextRange {
              kind: SyntaxKind;
              flags: NodeFlags;
              parserContextFlags?: ParserContextFlags;
              modifiers?: ModifiersArray;
              id?: number;
              parent?: Node;
              symbol?: Symbol;
              locals?: SymbolTable;
              nextContainer?: Node;
              localSymbol?: Symbol;
          }
          interface NodeArray<T> extends Array<T>, TextRange {
              hasTrailingComma?: boolean;
          }
          interface ModifiersArray extends NodeArray<Node> {
              flags: number;
          }
          interface Identifier extends PrimaryExpression {
              text: string;
          }
          interface QualifiedName extends Node {
              left: EntityName;
              right: Identifier;
          }
          type EntityName = Identifier | QualifiedName;
          type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern;
          interface Declaration extends Node {
              _declarationBrand: any;
              name?: DeclarationName;
          }
          interface ComputedPropertyName extends Node {
              expression: Expression;
          }
          interface TypeParameterDeclaration extends Declaration {
              name: Identifier;
              constraint?: TypeNode;
              expression?: Expression;
          }
          interface SignatureDeclaration extends Declaration {
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              parameters: NodeArray<ParameterDeclaration>;
              type?: TypeNode;
          }
          interface VariableDeclaration extends Declaration {
              parent?: VariableDeclarationList;
              name: Identifier | BindingPattern;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface VariableDeclarationList extends Node {
              declarations: NodeArray<VariableDeclaration>;
          }
          interface ParameterDeclaration extends Declaration {
              dotDotDotToken?: Node;
              name: Identifier | BindingPattern;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface BindingElement extends Declaration {
              propertyName?: Identifier;
              dotDotDotToken?: Node;
              name: Identifier | BindingPattern;
              initializer?: Expression;
          }
          interface PropertyDeclaration extends Declaration, ClassElement {
              name: DeclarationName;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface ObjectLiteralElement extends Declaration {
              _objectLiteralBrandBrand: any;
          }
          interface PropertyAssignment extends ObjectLiteralElement {
              _propertyAssignmentBrand: any;
              name: DeclarationName;
              questionToken?: Node;
              initializer: Expression;
          }
          interface ShorthandPropertyAssignment extends ObjectLiteralElement {
              name: Identifier;
              questionToken?: Node;
          }
          interface VariableLikeDeclaration extends Declaration {
              propertyName?: Identifier;
              dotDotDotToken?: Node;
              name: DeclarationName;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface BindingPattern extends Node {
              elements: NodeArray<BindingElement>;
          }
          /**
           * Several node kinds share function-like features such as a signature,
           * a name, and a body. These nodes should extend FunctionLikeDeclaration.
           * Examples:
           *  FunctionDeclaration
           *  MethodDeclaration
           *  AccessorDeclaration
           */
          interface FunctionLikeDeclaration extends SignatureDeclaration {
              _functionLikeDeclarationBrand: any;
              asteriskToken?: Node;
              questionToken?: Node;
              body?: Block | Expression;
          }
          interface FunctionDeclaration extends FunctionLikeDeclaration, Statement {
              name?: Identifier;
              body?: Block;
          }
          interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
              body?: Block;
          }
          interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement {
              body?: Block;
          }
          interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
              _accessorDeclarationBrand: any;
              body: Block;
          }
          interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement {
              _indexSignatureDeclarationBrand: any;
          }
          interface TypeNode extends Node {
              _typeNodeBrand: any;
          }
          interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration {
              _functionOrConstructorTypeNodeBrand: any;
          }
          interface TypeReferenceNode extends TypeNode {
              typeName: EntityName;
              typeArguments?: NodeArray<TypeNode>;
          }
          interface TypeQueryNode extends TypeNode {
              exprName: EntityName;
          }
          interface TypeLiteralNode extends TypeNode, Declaration {
              members: NodeArray<Node>;
          }
          interface ArrayTypeNode extends TypeNode {
              elementType: TypeNode;
          }
          interface TupleTypeNode extends TypeNode {
              elementTypes: NodeArray<TypeNode>;
          }
          interface UnionTypeNode extends TypeNode {
              types: NodeArray<TypeNode>;
          }
          interface ParenthesizedTypeNode extends TypeNode {
              type: TypeNode;
          }
          interface StringLiteralTypeNode extends LiteralExpression, TypeNode {
          }
          interface Expression extends Node {
              _expressionBrand: any;
              contextualType?: Type;
          }
          interface UnaryExpression extends Expression {
              _unaryExpressionBrand: any;
          }
          interface PrefixUnaryExpression extends UnaryExpression {
              operator: SyntaxKind;
              operand: UnaryExpression;
          }
          interface PostfixUnaryExpression extends PostfixExpression {
              operand: LeftHandSideExpression;
              operator: SyntaxKind;
          }
          interface PostfixExpression extends UnaryExpression {
              _postfixExpressionBrand: any;
          }
          interface LeftHandSideExpression extends PostfixExpression {
              _leftHandSideExpressionBrand: any;
          }
          interface MemberExpression extends LeftHandSideExpression {
              _memberExpressionBrand: any;
          }
          interface PrimaryExpression extends MemberExpression {
              _primaryExpressionBrand: any;
          }
          interface DeleteExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface TypeOfExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface VoidExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface YieldExpression extends Expression {
              asteriskToken?: Node;
              expression: Expression;
          }
          interface BinaryExpression extends Expression {
              left: Expression;
              operatorToken: Node;
              right: Expression;
          }
          interface ConditionalExpression extends Expression {
              condition: Expression;
              questionToken: Node;
              whenTrue: Expression;
              colonToken: Node;
              whenFalse: Expression;
          }
          interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
              name?: Identifier;
              body: Block | Expression;
          }
          interface LiteralExpression extends PrimaryExpression {
              text: string;
              isUnterminated?: boolean;
              hasExtendedUnicodeEscape?: boolean;
          }
          interface StringLiteralExpression extends LiteralExpression {
              _stringLiteralExpressionBrand: any;
          }
          interface TemplateExpression extends PrimaryExpression {
              head: LiteralExpression;
              templateSpans: NodeArray<TemplateSpan>;
          }
          interface TemplateSpan extends Node {
              expression: Expression;
              literal: LiteralExpression;
          }
          interface ParenthesizedExpression extends PrimaryExpression {
              expression: Expression;
          }
          interface ArrayLiteralExpression extends PrimaryExpression {
              elements: NodeArray<Expression>;
          }
          interface SpreadElementExpression extends Expression {
              expression: Expression;
          }
          interface ObjectLiteralExpression extends PrimaryExpression, Declaration {
              properties: NodeArray<ObjectLiteralElement>;
          }
          interface PropertyAccessExpression extends MemberExpression {
              expression: LeftHandSideExpression;
              dotToken: Node;
              name: Identifier;
          }
          interface ElementAccessExpression extends MemberExpression {
              expression: LeftHandSideExpression;
              argumentExpression?: Expression;
          }
          interface CallExpression extends LeftHandSideExpression {
              expression: LeftHandSideExpression;
              typeArguments?: NodeArray<TypeNode>;
              arguments: NodeArray<Expression>;
          }
          interface NewExpression extends CallExpression, PrimaryExpression {
          }
          interface TaggedTemplateExpression extends MemberExpression {
              tag: LeftHandSideExpression;
              template: LiteralExpression | TemplateExpression;
          }
          type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
          interface TypeAssertion extends UnaryExpression {
              type: TypeNode;
              expression: UnaryExpression;
          }
          interface Statement extends Node, ModuleElement {
              _statementBrand: any;
          }
          interface Block extends Statement {
              statements: NodeArray<Statement>;
          }
          interface VariableStatement extends Statement {
              declarationList: VariableDeclarationList;
          }
          interface ExpressionStatement extends Statement {
              expression: Expression;
          }
          interface IfStatement extends Statement {
              expression: Expression;
              thenStatement: Statement;
              elseStatement?: Statement;
          }
          interface IterationStatement extends Statement {
              statement: Statement;
          }
          interface DoStatement extends IterationStatement {
              expression: Expression;
          }
          interface WhileStatement extends IterationStatement {
              expression: Expression;
          }
          interface ForStatement extends IterationStatement {
              initializer?: VariableDeclarationList | Expression;
              condition?: Expression;
              iterator?: Expression;
          }
          interface ForInStatement extends IterationStatement {
              initializer: VariableDeclarationList | Expression;
              expression: Expression;
          }
          interface ForOfStatement extends IterationStatement {
              initializer: VariableDeclarationList | Expression;
              expression: Expression;
          }
          interface BreakOrContinueStatement extends Statement {
              label?: Identifier;
          }
          interface ReturnStatement extends Statement {
              expression?: Expression;
          }
          interface WithStatement extends Statement {
              expression: Expression;
              statement: Statement;
          }
          interface SwitchStatement extends Statement {
              expression: Expression;
              caseBlock: CaseBlock;
          }
          interface CaseBlock extends Node {
              clauses: NodeArray<CaseOrDefaultClause>;
          }
          interface CaseClause extends Node {
              expression?: Expression;
              statements: NodeArray<Statement>;
          }
          interface DefaultClause extends Node {
              statements: NodeArray<Statement>;
          }
          type CaseOrDefaultClause = CaseClause | DefaultClause;
          interface LabeledStatement extends Statement {
              label: Identifier;
              statement: Statement;
          }
          interface ThrowStatement extends Statement {
              expression: Expression;
          }
          interface TryStatement extends Statement {
              tryBlock: Block;
              catchClause?: CatchClause;
              finallyBlock?: Block;
          }
          interface CatchClause extends Node {
              variableDeclaration: VariableDeclaration;
              block: Block;
          }
          interface ModuleElement extends Node {
              _moduleElementBrand: any;
          }
          interface ClassDeclaration extends Declaration, ModuleElement {
              name?: Identifier;
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              heritageClauses?: NodeArray<HeritageClause>;
              members: NodeArray<ClassElement>;
          }
          interface ClassElement extends Declaration {
              _classElementBrand: any;
          }
          interface InterfaceDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              heritageClauses?: NodeArray<HeritageClause>;
              members: NodeArray<Declaration>;
          }
          interface HeritageClause extends Node {
              token: SyntaxKind;
              types?: NodeArray<TypeReferenceNode>;
          }
          interface TypeAliasDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              type: TypeNode;
          }
          interface EnumMember extends Declaration {
              name: DeclarationName;
              initializer?: Expression;
          }
          interface EnumDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              members: NodeArray<EnumMember>;
          }
          interface ModuleDeclaration extends Declaration, ModuleElement {
              name: Identifier | LiteralExpression;
              body: ModuleBlock | ModuleDeclaration;
          }
          interface ModuleBlock extends Node, ModuleElement {
              statements: NodeArray<ModuleElement>;
          }
          interface ImportEqualsDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              moduleReference: EntityName | ExternalModuleReference;
          }
          interface ExternalModuleReference extends Node {
              expression?: Expression;
          }
          interface ImportDeclaration extends Statement, ModuleElement {
              importClause?: ImportClause;
              moduleSpecifier: Expression;
          }
          interface ImportClause extends Declaration {
              name?: Identifier;
              namedBindings?: NamespaceImport | NamedImports;
          }
          interface NamespaceImport extends Declaration {
              name: Identifier;
          }
          interface ExportDeclaration extends Declaration, ModuleElement {
              exportClause?: NamedExports;
              moduleSpecifier?: Expression;
          }
          interface NamedImportsOrExports extends Node {
              elements: NodeArray<ImportOrExportSpecifier>;
          }
          type NamedImports = NamedImportsOrExports;
          type NamedExports = NamedImportsOrExports;
          interface ImportOrExportSpecifier extends Declaration {
              propertyName?: Identifier;
              name: Identifier;
          }
          type ImportSpecifier = ImportOrExportSpecifier;
          type ExportSpecifier = ImportOrExportSpecifier;
          interface ExportAssignment extends Declaration, ModuleElement {
              isExportEquals?: boolean;
              expression: Expression;
          }
          interface FileReference extends TextRange {
              fileName: string;
          }
          interface CommentRange extends TextRange {
              hasTrailingNewLine?: boolean;
          }
          interface SourceFile extends Declaration {
              statements: NodeArray<ModuleElement>;
              endOfFileToken: Node;
              fileName: string;
              text: string;
              amdDependencies: {
                  path: string;
                  name: string;
              }[];
              amdModuleName: string;
              referencedFiles: FileReference[];
              hasNoDefaultLib: boolean;
              externalModuleIndicator: Node;
              languageVersion: ScriptTarget;
              identifiers: Map<string>;
          }
          interface ScriptReferenceHost {
              getCompilerOptions(): CompilerOptions;
              getSourceFile(fileName: string): SourceFile;
              getCurrentDirectory(): string;
          }
          interface WriteFileCallback {
              (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
          }
          interface Program extends ScriptReferenceHost {
              getSourceFiles(): SourceFile[];
              /**
               * Emits the javascript and declaration files.  If targetSourceFile is not specified, then
               * the javascript and declaration files will be produced for all the files in this program.
               * If targetSourceFile is specified, then only the javascript and declaration for that
               * specific file will be generated.
               *
               * If writeFile is not specified then the writeFile callback from the compiler host will be
               * used for writing the javascript and declaration files.  Otherwise, the writeFile parameter
               * will be invoked when writing the javascript and declaration files.
               */
              emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
              getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              getGlobalDiagnostics(): Diagnostic[];
              getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              getTypeChecker(): TypeChecker;
              getCommonSourceDirectory(): string;
          }
          interface SourceMapSpan {
              emittedLine: number;
              emittedColumn: number;
              sourceLine: number;
              sourceColumn: number;
              nameIndex?: number;
              sourceIndex: number;
          }
          interface SourceMapData {
              sourceMapFilePath: string;
              jsSourceMappingURL: string;
              sourceMapFile: string;
              sourceMapSourceRoot: string;
              sourceMapSources: string[];
              inputSourceFileNames: string[];
              sourceMapNames?: string[];
              sourceMapMappings: string;
              sourceMapDecodedMappings: SourceMapSpan[];
          }
          enum ExitStatus {
              Success = 0,
              DiagnosticsPresent_OutputsSkipped = 1,
              DiagnosticsPresent_OutputsGenerated = 2,
          }
          interface EmitResult {
              emitSkipped: boolean;
              diagnostics: Diagnostic[];
              sourceMaps: SourceMapData[];
          }
          interface TypeCheckerHost {
              getCompilerOptions(): CompilerOptions;
              getSourceFiles(): SourceFile[];
              getSourceFile(fileName: string): SourceFile;
          }
          interface TypeChecker {
              getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
              getDeclaredTypeOfSymbol(symbol: Symbol): Type;
              getPropertiesOfType(type: Type): Symbol[];
              getPropertyOfType(type: Type, propertyName: string): Symbol;
              getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
              getIndexTypeOfType(type: Type, kind: IndexKind): Type;
              getReturnTypeOfSignature(signature: Signature): Type;
              getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
              getSymbolAtLocation(node: Node): Symbol;
              getShorthandAssignmentValueSymbol(location: Node): Symbol;
              getTypeAtLocation(node: Node): Type;
              typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
              symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
              getSymbolDisplayBuilder(): SymbolDisplayBuilder;
              getFullyQualifiedName(symbol: Symbol): string;
              getAugmentedPropertiesOfType(type: Type): Symbol[];
              getRootSymbols(symbol: Symbol): Symbol[];
              getContextualType(node: Expression): Type;
              getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature;
              getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
              isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
              isUndefinedSymbol(symbol: Symbol): boolean;
              isArgumentsSymbol(symbol: Symbol): boolean;
              getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
              isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
              getAliasedSymbol(symbol: Symbol): Symbol;
              getExportsOfExternalModule(node: ImportDeclaration): Symbol[];
          }
          interface SymbolDisplayBuilder {
              buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
              buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
              buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
          }
          interface SymbolWriter {
              writeKeyword(text: string): void;
              writeOperator(text: string): void;
              writePunctuation(text: string): void;
              writeSpace(text: string): void;
              writeStringLiteral(text: string): void;
              writeParameter(text: string): void;
              writeSymbol(text: string, symbol: Symbol): void;
              writeLine(): void;
              increaseIndent(): void;
              decreaseIndent(): void;
              clear(): void;
              trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
          }
          const enum TypeFormatFlags {
              None = 0,
              WriteArrayAsGenericType = 1,
              UseTypeOfFunction = 2,
              NoTruncation = 4,
              WriteArrowStyleSignature = 8,
              WriteOwnNameForAnyLike = 16,
              WriteTypeArgumentsOfSignature = 32,
              InElementType = 64,
              UseFullyQualifiedType = 128,
          }
          const enum SymbolFormatFlags {
              None = 0,
              WriteTypeParametersOrArguments = 1,
              UseOnlyExternalAliasing = 2,
          }
          const enum SymbolAccessibility {
              Accessible = 0,
              NotAccessible = 1,
              CannotBeNamed = 2,
          }
          interface SymbolVisibilityResult {
              accessibility: SymbolAccessibility;
              aliasesToMakeVisible?: ImportEqualsDeclaration[];
              errorSymbolName?: string;
              errorNode?: Node;
          }
          interface SymbolAccessiblityResult extends SymbolVisibilityResult {
              errorModuleName?: string;
          }
          interface EmitResolver {
              getGeneratedNameForNode(node: Node): string;
              getExpressionNameSubstitution(node: Identifier): string;
              hasExportDefaultValue(node: SourceFile): boolean;
              isReferencedAliasDeclaration(node: Node): boolean;
              isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
              getNodeCheckFlags(node: Node): NodeCheckFlags;
              isDeclarationVisible(node: Declaration): boolean;
              isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
              writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
              writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
              isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
              isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
              getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
              isUnknownIdentifier(location: Node, name: string): boolean;
              getBlockScopedVariableId(node: Identifier): number;
          }
          const enum SymbolFlags {
              FunctionScopedVariable = 1,
              BlockScopedVariable = 2,
              Property = 4,
              EnumMember = 8,
              Function = 16,
              Class = 32,
              Interface = 64,
              ConstEnum = 128,
              RegularEnum = 256,
              ValueModule = 512,
              NamespaceModule = 1024,
              TypeLiteral = 2048,
              ObjectLiteral = 4096,
              Method = 8192,
              Constructor = 16384,
              GetAccessor = 32768,
              SetAccessor = 65536,
              Signature = 131072,
              TypeParameter = 262144,
              TypeAlias = 524288,
              ExportValue = 1048576,
              ExportType = 2097152,
              ExportNamespace = 4194304,
              Alias = 8388608,
              Instantiated = 16777216,
              Merged = 33554432,
              Transient = 67108864,
              Prototype = 134217728,
              UnionProperty = 268435456,
              Optional = 536870912,
              ExportStar = 1073741824,
              Enum = 384,
              Variable = 3,
              Value = 107455,
              Type = 793056,
              Namespace = 1536,
              Module = 1536,
              Accessor = 98304,
              FunctionScopedVariableExcludes = 107454,
              BlockScopedVariableExcludes = 107455,
              ParameterExcludes = 107455,
              PropertyExcludes = 107455,
              EnumMemberExcludes = 107455,
              FunctionExcludes = 106927,
              ClassExcludes = 899583,
              InterfaceExcludes = 792992,
              RegularEnumExcludes = 899327,
              ConstEnumExcludes = 899967,
              ValueModuleExcludes = 106639,
              NamespaceModuleExcludes = 0,
              MethodExcludes = 99263,
              GetAccessorExcludes = 41919,
              SetAccessorExcludes = 74687,
              TypeParameterExcludes = 530912,
              TypeAliasExcludes = 793056,
              AliasExcludes = 8388608,
              ModuleMember = 8914931,
              ExportHasLocal = 944,
              HasLocals = 255504,
              HasExports = 1952,
              HasMembers = 6240,
              IsContainer = 262128,
              PropertyOrAccessor = 98308,
              Export = 7340032,
          }
          interface Symbol {
              flags: SymbolFlags;
              name: string;
              id?: number;
              mergeId?: number;
              declarations?: Declaration[];
              parent?: Symbol;
              members?: SymbolTable;
              exports?: SymbolTable;
              exportSymbol?: Symbol;
              valueDeclaration?: Declaration;
              constEnumOnlyModule?: boolean;
          }
          interface SymbolLinks {
              target?: Symbol;
              type?: Type;
              declaredType?: Type;
              mapper?: TypeMapper;
              referenced?: boolean;
              unionType?: UnionType;
              resolvedExports?: SymbolTable;
              exportsChecked?: boolean;
          }
          interface TransientSymbol extends Symbol, SymbolLinks {
          }
          interface SymbolTable {
              [index: string]: Symbol;
          }
          const enum NodeCheckFlags {
              TypeChecked = 1,
              LexicalThis = 2,
              CaptureThis = 4,
              EmitExtends = 8,
              SuperInstance = 16,
              SuperStatic = 32,
              ContextChecked = 64,
              EnumValuesComputed = 128,
              BlockScopedBindingInLoop = 256,
          }
          interface NodeLinks {
              resolvedType?: Type;
              resolvedSignature?: Signature;
              resolvedSymbol?: Symbol;
              flags?: NodeCheckFlags;
              enumMemberValue?: number;
              isIllegalTypeReferenceInConstraint?: boolean;
              isVisible?: boolean;
              generatedName?: string;
              generatedNames?: Map<string>;
              assignmentChecks?: Map<boolean>;
              hasReportedStatementInAmbientContext?: boolean;
              importOnRightSide?: Symbol;
          }
          const enum TypeFlags {
              Any = 1,
              String = 2,
              Number = 4,
              Boolean = 8,
              Void = 16,
              Undefined = 32,
              Null = 64,
              Enum = 128,
              StringLiteral = 256,
              TypeParameter = 512,
              Class = 1024,
              Interface = 2048,
              Reference = 4096,
              Tuple = 8192,
              Union = 16384,
              Anonymous = 32768,
              FromSignature = 65536,
              ObjectLiteral = 131072,
              ContainsUndefinedOrNull = 262144,
              ContainsObjectLiteral = 524288,
              ESSymbol = 1048576,
              Intrinsic = 1048703,
              Primitive = 1049086,
              StringLike = 258,
              NumberLike = 132,
              ObjectType = 48128,
              RequiresWidening = 786432,
          }
          interface Type {
              flags: TypeFlags;
              id: number;
              symbol?: Symbol;
          }
          interface IntrinsicType extends Type {
              intrinsicName: string;
          }
          interface StringLiteralType extends Type {
              text: string;
          }
          interface ObjectType extends Type {
          }
          interface InterfaceType extends ObjectType {
              typeParameters: TypeParameter[];
              baseTypes: ObjectType[];
              declaredProperties: Symbol[];
              declaredCallSignatures: Signature[];
              declaredConstructSignatures: Signature[];
              declaredStringIndexType: Type;
              declaredNumberIndexType: Type;
          }
          interface TypeReference extends ObjectType {
              target: GenericType;
              typeArguments: Type[];
          }
          interface GenericType extends InterfaceType, TypeReference {
              instantiations: Map<TypeReference>;
          }
          interface TupleType extends ObjectType {
              elementTypes: Type[];
              baseArrayType: TypeReference;
          }
          interface UnionType extends Type {
              types: Type[];
              resolvedProperties: SymbolTable;
          }
          interface ResolvedType extends ObjectType, UnionType {
              members: SymbolTable;
              properties: Symbol[];
              callSignatures: Signature[];
              constructSignatures: Signature[];
              stringIndexType: Type;
              numberIndexType: Type;
          }
          interface TypeParameter extends Type {
              constraint: Type;
              target?: TypeParameter;
              mapper?: TypeMapper;
          }
          const enum SignatureKind {
              Call = 0,
              Construct = 1,
          }
          interface Signature {
              declaration: SignatureDeclaration;
              typeParameters: TypeParameter[];
              parameters: Symbol[];
              resolvedReturnType: Type;
              minArgumentCount: number;
              hasRestParameter: boolean;
              hasStringLiterals: boolean;
              target?: Signature;
              mapper?: TypeMapper;
              unionSignatures?: Signature[];
              erasedSignatureCache?: Signature;
              isolatedSignatureType?: ObjectType;
          }
          const enum IndexKind {
              String = 0,
              Number = 1,
          }
          interface TypeMapper {
              (t: Type): Type;
          }
          interface TypeInferences {
              primary: Type[];
              secondary: Type[];
          }
          interface InferenceContext {
              typeParameters: TypeParameter[];
              inferUnionTypes: boolean;
              inferences: TypeInferences[];
              inferredTypes: Type[];
              failedTypeParameterIndex?: number;
          }
          interface DiagnosticMessage {
              key: string;
              category: DiagnosticCategory;
              code: number;
          }
          interface DiagnosticMessageChain {
              messageText: string;
              category: DiagnosticCategory;
              code: number;
              next?: DiagnosticMessageChain;
          }
          interface Diagnostic {
              file: SourceFile;
              start: number;
              length: number;
              messageText: string | DiagnosticMessageChain;
              category: DiagnosticCategory;
              code: number;
          }
          enum DiagnosticCategory {
              Warning = 0,
              Error = 1,
              Message = 2,
          }
          interface CompilerOptions {
              allowNonTsExtensions?: boolean;
              charset?: string;
              codepage?: number;
              declaration?: boolean;
              diagnostics?: boolean;
              emitBOM?: boolean;
              help?: boolean;
              listFiles?: boolean;
              locale?: string;
              mapRoot?: string;
              module?: ModuleKind;
              noEmit?: boolean;
              noEmitOnError?: boolean;
              noErrorTruncation?: boolean;
              noImplicitAny?: boolean;
              noLib?: boolean;
              noLibCheck?: boolean;
              noResolve?: boolean;
              out?: string;
              outDir?: string;
              preserveConstEnums?: boolean;
              project?: string;
              removeComments?: boolean;
              sourceMap?: boolean;
              sourceRoot?: string;
              suppressImplicitAnyIndexErrors?: boolean;
              target?: ScriptTarget;
              version?: boolean;
              watch?: boolean;
              stripInternal?: boolean;
              preserveNewLines?: boolean;
              [option: string]: string | number | boolean;
          }
          const enum ModuleKind {
              None = 0,
              CommonJS = 1,
              AMD = 2,
          }
          interface LineAndCharacter {
              line: number;
              character: number;
          }
          const enum ScriptTarget {
              ES3 = 0,
              ES5 = 1,
              ES6 = 2,
              Latest = 2,
          }
          interface ParsedCommandLine {
              options: CompilerOptions;
              fileNames: string[];
              errors: Diagnostic[];
          }
          interface CommandLineOption {
              name: string;
              type: string | Map<number>;
              isFilePath?: boolean;
              shortName?: string;
              description?: DiagnosticMessage;
              paramType?: DiagnosticMessage;
              error?: DiagnosticMessage;
              experimental?: boolean;
          }
          const enum CharacterCodes {
              nullCharacter = 0,
              maxAsciiCharacter = 127,
              lineFeed = 10,
              carriageReturn = 13,
              lineSeparator = 8232,
              paragraphSeparator = 8233,
              nextLine = 133,
              space = 32,
              nonBreakingSpace = 160,
              enQuad = 8192,
              emQuad = 8193,
              enSpace = 8194,
              emSpace = 8195,
              threePerEmSpace = 8196,
              fourPerEmSpace = 8197,
              sixPerEmSpace = 8198,
              figureSpace = 8199,
              punctuationSpace = 8200,
              thinSpace = 8201,
              hairSpace = 8202,
              zeroWidthSpace = 8203,
              narrowNoBreakSpace = 8239,
              ideographicSpace = 12288,
              mathematicalSpace = 8287,
              ogham = 5760,
              _ = 95,
              $ = 36,
              _0 = 48,
              _1 = 49,
              _2 = 50,
              _3 = 51,
              _4 = 52,
              _5 = 53,
              _6 = 54,
              _7 = 55,
              _8 = 56,
              _9 = 57,
              a = 97,
              b = 98,
              c = 99,
              d = 100,
              e = 101,
              f = 102,
              g = 103,
              h = 104,
              i = 105,
              j = 106,
              k = 107,
              l = 108,
              m = 109,
              n = 110,
              o = 111,
              p = 112,
              q = 113,
              r = 114,
              s = 115,
              t = 116,
              u = 117,
              v = 118,
              w = 119,
              x = 120,
              y = 121,
              z = 122,
              A = 65,
              B = 66,
              C = 67,
              D = 68,
              E = 69,
              F = 70,
              G = 71,
              H = 72,
              I = 73,
              J = 74,
              K = 75,
              L = 76,
              M = 77,
              N = 78,
              O = 79,
              P = 80,
              Q = 81,
              R = 82,
              S = 83,
              T = 84,
              U = 85,
              V = 86,
              W = 87,
              X = 88,
              Y = 89,
              Z = 90,
              ampersand = 38,
              asterisk = 42,
              at = 64,
              backslash = 92,
              backtick = 96,
              bar = 124,
              caret = 94,
              closeBrace = 125,
              closeBracket = 93,
              closeParen = 41,
              colon = 58,
              comma = 44,
              dot = 46,
              doubleQuote = 34,
              equals = 61,
              exclamation = 33,
              greaterThan = 62,
              hash = 35,
              lessThan = 60,
              minus = 45,
              openBrace = 123,
              openBracket = 91,
              openParen = 40,
              percent = 37,
              plus = 43,
              question = 63,
              semicolon = 59,
              singleQuote = 39,
              slash = 47,
              tilde = 126,
              backspace = 8,
              formFeed = 12,
              byteOrderMark = 65279,
              tab = 9,
              verticalTab = 11,
          }
          interface CancellationToken {
              isCancellationRequested(): boolean;
          }
          interface CompilerHost {
              getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
              getDefaultLibFileName(options: CompilerOptions): string;
              getCancellationToken?(): CancellationToken;
              writeFile: WriteFileCallback;
              getCurrentDirectory(): string;
              getCanonicalFileName(fileName: string): string;
              useCaseSensitiveFileNames(): boolean;
              getNewLine(): string;
          }
          interface TextSpan {
              start: number;
              length: number;
          }
          interface TextChangeRange {
              span: TextSpan;
              newLength: number;
          }
      }
      declare module ts {
          interface ErrorCallback {
              (message: DiagnosticMessage, length: number): void;
          }
          interface Scanner {
              getStartPos(): number;
              getToken(): SyntaxKind;
              getTextPos(): number;
              getTokenPos(): number;
              getTokenText(): string;
              getTokenValue(): string;
              hasExtendedUnicodeEscape(): boolean;
              hasPrecedingLineBreak(): boolean;
              isIdentifier(): boolean;
              isReservedWord(): boolean;
              isUnterminated(): boolean;
              reScanGreaterToken(): SyntaxKind;
              reScanSlashToken(): SyntaxKind;
              reScanTemplateToken(): SyntaxKind;
              scan(): SyntaxKind;
              setText(text: string): void;
              setTextPos(textPos: number): void;
              lookAhead<T>(callback: () => T): T;
              tryScan<T>(callback: () => T): T;
          }
          function tokenToString(t: SyntaxKind): string;
          function computeLineStarts(text: string): number[];
          function getPositionOfLineAndCharacter(sourceFile: SourceFile, line: number, character: number): number;
          function computePositionOfLineAndCharacter(lineStarts: number[], line: number, character: number): number;
          function getLineStarts(sourceFile: SourceFile): number[];
          function computeLineAndCharacterOfPosition(lineStarts: number[], position: number): {
              line: number;
              character: number;
          };
          function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter;
          function isWhiteSpace(ch: number): boolean;
          function isLineBreak(ch: number): boolean;
          function isOctalDigit(ch: number): boolean;
          function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number;
          function getLeadingCommentRanges(text: string, pos: number): CommentRange[];
          function getTrailingCommentRanges(text: string, pos: number): CommentRange[];
          function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean;
          function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean;
          function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback): Scanner;
      }
      declare module ts {
          function getNodeConstructor(kind: SyntaxKind): new () => Node;
          function createNode(kind: SyntaxKind): Node;
          function forEachChild<T>(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T;
          function modifierToFlag(token: SyntaxKind): NodeFlags;
          function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile;
          function isEvalOrArgumentsIdentifier(node: Node): boolean;
          function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile;
          function isLeftHandSideExpression(expr: Expression): boolean;
          function isAssignmentOperator(token: SyntaxKind): boolean;
      }
      declare module ts {
          function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker;
      }
      declare module ts {
          /** The version of the TypeScript compiler release */
          var version: string;
          function createCompilerHost(options: CompilerOptions): CompilerHost;
          function getPreEmitDiagnostics(program: Program): Diagnostic[];
          function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string;
          function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program;
      }
      declare module ts {
          /** The version of the language service API */
          var servicesVersion: string;
          interface Node {
              getSourceFile(): SourceFile;
              getChildCount(sourceFile?: SourceFile): number;
              getChildAt(index: number, sourceFile?: SourceFile): Node;
              getChildren(sourceFile?: SourceFile): Node[];
              getStart(sourceFile?: SourceFile): number;
              getFullStart(): number;
              getEnd(): number;
              getWidth(sourceFile?: SourceFile): number;
              getFullWidth(): number;
              getLeadingTriviaWidth(sourceFile?: SourceFile): number;
              getFullText(sourceFile?: SourceFile): string;
              getText(sourceFile?: SourceFile): string;
              getFirstToken(sourceFile?: SourceFile): Node;
              getLastToken(sourceFile?: SourceFile): Node;
          }
          interface Symbol {
              getFlags(): SymbolFlags;
              getName(): string;
              getDeclarations(): Declaration[];
              getDocumentationComment(): SymbolDisplayPart[];
          }
          interface Type {
              getFlags(): TypeFlags;
              getSymbol(): Symbol;
              getProperties(): Symbol[];
              getProperty(propertyName: string): Symbol;
              getApparentProperties(): Symbol[];
              getCallSignatures(): Signature[];
              getConstructSignatures(): Signature[];
              getStringIndexType(): Type;
              getNumberIndexType(): Type;
          }
          interface Signature {
              getDeclaration(): SignatureDeclaration;
              getTypeParameters(): Type[];
              getParameters(): Symbol[];
              getReturnType(): Type;
              getDocumentationComment(): SymbolDisplayPart[];
          }
          interface SourceFile {
              getNamedDeclarations(): Declaration[];
              getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
              getLineStarts(): number[];
              getPositionOfLineAndCharacter(line: number, character: number): number;
              update(newText: string, textChangeRange: TextChangeRange): SourceFile;
          }
          /**
           * Represents an immutable snapshot of a script at a specified time.Once acquired, the
           * snapshot is observably immutable. i.e. the same calls with the same parameters will return
           * the same values.
           */
          interface IScriptSnapshot {
              /** Gets a portion of the script snapshot specified by [start, end). */
              getText(start: number, end: number): string;
              /** Gets the length of this script snapshot. */
              getLength(): number;
              /**
               * Gets the TextChangeRange that describe how the text changed between this text and
               * an older version.  This information is used by the incremental parser to determine
               * what sections of the script need to be re-parsed.  'undefined' can be returned if the
               * change range cannot be determined.  However, in that case, incremental parsing will
               * not happen and the entire document will be re - parsed.
               */
              getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
          }
          module ScriptSnapshot {
              function fromString(text: string): IScriptSnapshot;
          }
          interface PreProcessedFileInfo {
              referencedFiles: FileReference[];
              importedFiles: FileReference[];
              isLibFile: boolean;
          }
          interface LanguageServiceHost {
              getCompilationSettings(): CompilerOptions;
              getNewLine?(): string;
              getScriptFileNames(): string[];
              getScriptVersion(fileName: string): string;
              getScriptSnapshot(fileName: string): IScriptSnapshot;
              getLocalizedDiagnosticMessages?(): any;
              getCancellationToken?(): CancellationToken;
              getCurrentDirectory(): string;
              getDefaultLibFileName(options: CompilerOptions): string;
              log?(s: string): void;
              trace?(s: string): void;
              error?(s: string): void;
          }
          interface LanguageService {
              cleanupSemanticCache(): void;
              getSyntacticDiagnostics(fileName: string): Diagnostic[];
              getSemanticDiagnostics(fileName: string): Diagnostic[];
              getCompilerOptionsDiagnostics(): Diagnostic[];
              getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
              getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
              getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
              getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
              getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
              getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan;
              getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan;
              getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
              getRenameInfo(fileName: string, position: number): RenameInfo;
              findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
              getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
              getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
              getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
              getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
              getNavigationBarItems(fileName: string): NavigationBarItem[];
              getOutliningSpans(fileName: string): OutliningSpan[];
              getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
              getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
              getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
              getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
              getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
              getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
              getEmitOutput(fileName: string): EmitOutput;
              getProgram(): Program;
              getSourceFile(fileName: string): SourceFile;
              dispose(): void;
          }
          interface ClassifiedSpan {
              textSpan: TextSpan;
              classificationType: string;
          }
          interface NavigationBarItem {
              text: string;
              kind: string;
              kindModifiers: string;
              spans: TextSpan[];
              childItems: NavigationBarItem[];
              indent: number;
              bolded: boolean;
              grayed: boolean;
          }
          interface TodoCommentDescriptor {
              text: string;
              priority: number;
          }
          interface TodoComment {
              descriptor: TodoCommentDescriptor;
              message: string;
              position: number;
          }
          class TextChange {
              span: TextSpan;
              newText: string;
          }
          interface RenameLocation {
              textSpan: TextSpan;
              fileName: string;
          }
          interface ReferenceEntry {
              textSpan: TextSpan;
              fileName: string;
              isWriteAccess: boolean;
          }
          interface NavigateToItem {
              name: string;
              kind: string;
              kindModifiers: string;
              matchKind: string;
              isCaseSensitive: boolean;
              fileName: string;
              textSpan: TextSpan;
              containerName: string;
              containerKind: string;
          }
          interface EditorOptions {
              IndentSize: number;
              TabSize: number;
              NewLineCharacter: string;
              ConvertTabsToSpaces: boolean;
          }
          interface FormatCodeOptions extends EditorOptions {
              InsertSpaceAfterCommaDelimiter: boolean;
              InsertSpaceAfterSemicolonInForStatements: boolean;
              InsertSpaceBeforeAndAfterBinaryOperators: boolean;
              InsertSpaceAfterKeywordsInControlFlowStatements: boolean;
              InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
              InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
              PlaceOpenBraceOnNewLineForFunctions: boolean;
              PlaceOpenBraceOnNewLineForControlBlocks: boolean;
              [s: string]: boolean | number | string;
          }
          interface DefinitionInfo {
              fileName: string;
              textSpan: TextSpan;
              kind: string;
              name: string;
              containerKind: string;
              containerName: string;
          }
          enum SymbolDisplayPartKind {
              aliasName = 0,
              className = 1,
              enumName = 2,
              fieldName = 3,
              interfaceName = 4,
              keyword = 5,
              lineBreak = 6,
              numericLiteral = 7,
              stringLiteral = 8,
              localName = 9,
              methodName = 10,
              moduleName = 11,
              operator = 12,
              parameterName = 13,
              propertyName = 14,
              punctuation = 15,
              space = 16,
              text = 17,
              typeParameterName = 18,
              enumMemberName = 19,
              functionName = 20,
              regularExpressionLiteral = 21,
          }
          interface SymbolDisplayPart {
              text: string;
              kind: string;
          }
          interface QuickInfo {
              kind: string;
              kindModifiers: string;
              textSpan: TextSpan;
              displayParts: SymbolDisplayPart[];
              documentation: SymbolDisplayPart[];
          }
          interface RenameInfo {
              canRename: boolean;
              localizedErrorMessage: string;
              displayName: string;
              fullDisplayName: string;
              kind: string;
              kindModifiers: string;
              triggerSpan: TextSpan;
          }
          interface SignatureHelpParameter {
              name: string;
              documentation: SymbolDisplayPart[];
              displayParts: SymbolDisplayPart[];
              isOptional: boolean;
          }
          /**
           * Represents a single signature to show in signature help.
           * The id is used for subsequent calls into the language service to ask questions about the
           * signature help item in the context of any documents that have been updated.  i.e. after
           * an edit has happened, while signature help is still active, the host can ask important
           * questions like 'what parameter is the user currently contained within?'.
           */
          interface SignatureHelpItem {
              isVariadic: boolean;
              prefixDisplayParts: SymbolDisplayPart[];
              suffixDisplayParts: SymbolDisplayPart[];
              separatorDisplayParts: SymbolDisplayPart[];
              parameters: SignatureHelpParameter[];
              documentation: SymbolDisplayPart[];
          }
          /**
           * Represents a set of signature help items, and the preferred item that should be selected.
           */
          interface SignatureHelpItems {
              items: SignatureHelpItem[];
              applicableSpan: TextSpan;
              selectedItemIndex: number;
              argumentIndex: number;
              argumentCount: number;
          }
          interface CompletionInfo {
              isMemberCompletion: boolean;
              isNewIdentifierLocation: boolean;
              entries: CompletionEntry[];
          }
          interface CompletionEntry {
              name: string;
              kind: string;
              kindModifiers: string;
          }
          interface CompletionEntryDetails {
              name: string;
              kind: string;
              kindModifiers: string;
              displayParts: SymbolDisplayPart[];
              documentation: SymbolDisplayPart[];
          }
          interface OutliningSpan {
              /** The span of the document to actually collapse. */
              textSpan: TextSpan;
              /** The span of the document to display when the user hovers over the collapsed span. */
              hintSpan: TextSpan;
              /** The text to display in the editor for the collapsed region. */
              bannerText: string;
              /**
                * Whether or not this region should be automatically collapsed when
                * the 'Collapse to Definitions' command is invoked.
                */
              autoCollapse: boolean;
          }
          interface EmitOutput {
              outputFiles: OutputFile[];
              emitSkipped: boolean;
          }
          const enum OutputFileType {
              JavaScript = 0,
              SourceMap = 1,
              Declaration = 2,
          }
          interface OutputFile {
              name: string;
              writeByteOrderMark: boolean;
              text: string;
          }
          const enum EndOfLineState {
              Start = 0,
              InMultiLineCommentTrivia = 1,
              InSingleQuoteStringLiteral = 2,
              InDoubleQuoteStringLiteral = 3,
              InTemplateHeadOrNoSubstitutionTemplate = 4,
              InTemplateMiddleOrTail = 5,
              InTemplateSubstitutionPosition = 6,
          }
          enum TokenClass {
              Punctuation = 0,
              Keyword = 1,
              Operator = 2,
              Comment = 3,
              Whitespace = 4,
              Identifier = 5,
              NumberLiteral = 6,
              StringLiteral = 7,
              RegExpLiteral = 8,
          }
          interface ClassificationResult {
              finalLexState: EndOfLineState;
              entries: ClassificationInfo[];
          }
          interface ClassificationInfo {
              length: number;
              classification: TokenClass;
          }
          interface Classifier {
              /**
               * Gives lexical classifications of tokens on a line without any syntactic context.
               * For instance, a token consisting of the text 'string' can be either an identifier
               * named 'string' or the keyword 'string', however, because this classifier is not aware,
               * it relies on certain heuristics to give acceptable results. For classifications where
               * speed trumps accuracy, this function is preferable; however, for true accuracy, the
               * syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
               * lexical, syntactic, and semantic classifiers may issue the best user experience.
               *
               * @param text                      The text of a line to classify.
               * @param lexState                  The state of the lexical classifier at the end of the previous line.
               * @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
               *                                  If there is no syntactic classifier (syntacticClassifierAbsent=true),
               *                                  certain heuristics may be used in its place; however, if there is a
               *                                  syntactic classifier (syntacticClassifierAbsent=false), certain
               *                                  classifications which may be incorrectly categorized will be given
               *                                  back as Identifiers in order to allow the syntactic classifier to
               *                                  subsume the classification.
               */
              getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
          }
          /**
            * The document registry represents a store of SourceFile objects that can be shared between
            * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
            * of files in the context.
            * SourceFile objects account for most of the memory usage by the language service. Sharing
            * the same DocumentRegistry instance between different instances of LanguageService allow
            * for more efficient memory utilization since all projects will share at least the library
            * file (lib.d.ts).
            *
            * A more advanced use of the document registry is to serialize sourceFile objects to disk
            * and re-hydrate them when needed.
            *
            * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
            * to all subsequent createLanguageService calls.
            */
          interface DocumentRegistry {
              /**
                * Request a stored SourceFile with a given fileName and compilationSettings.
                * The first call to acquire will call createLanguageServiceSourceFile to generate
                * the SourceFile if was not found in the registry.
                *
                * @param fileName The name of the file requested
                * @param compilationSettings Some compilation settings like target affects the
                * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
                * multiple copies of the same file for different compilation settings.
                * @parm scriptSnapshot Text of the file. Only used if the file was not found
                * in the registry and a new one was created.
                * @parm version Current version of the file. Only used if the file was not found
                * in the registry and a new one was created.
                */
              acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile;
              /**
                * Request an updated version of an already existing SourceFile with a given fileName
                * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
                * to get an updated SourceFile.
                *
                * @param fileName The name of the file requested
                * @param compilationSettings Some compilation settings like target affects the
                * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
                * multiple copies of the same file for different compilation settings.
                * @param scriptSnapshot Text of the file.
                * @param version Current version of the file.
                */
              updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile;
              /**
                * Informs the DocumentRegistry that a file is not needed any longer.
                *
                * Note: It is not allowed to call release on a SourceFile that was not acquired from
                * this registry originally.
                *
                * @param fileName The name of the file to be released
                * @param compilationSettings The compilation settings used to acquire the file
                */
              releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
          }
          class ScriptElementKind {
              static unknown: string;
              static keyword: string;
              static scriptElement: string;
              static moduleElement: string;
              static classElement: string;
              static interfaceElement: string;
              static typeElement: string;
              static enumElement: string;
              static variableElement: string;
              static localVariableElement: string;
              static functionElement: string;
              static localFunctionElement: string;
              static memberFunctionElement: string;
              static memberGetAccessorElement: string;
              static memberSetAccessorElement: string;
              static memberVariableElement: string;
              static constructorImplementationElement: string;
              static callSignatureElement: string;
              static indexSignatureElement: string;
              static constructSignatureElement: string;
              static parameterElement: string;
              static typeParameterElement: string;
              static primitiveType: string;
              static label: string;
              static alias: string;
              static constElement: string;
              static letElement: string;
          }
          class ScriptElementKindModifier {
              static none: string;
              static publicMemberModifier: string;
              static privateMemberModifier: string;
              static protectedMemberModifier: string;
              static exportedModifier: string;
              static ambientModifier: string;
              static staticModifier: string;
          }
          class ClassificationTypeNames {
              static comment: string;
              static identifier: string;
              static keyword: string;
              static numericLiteral: string;
              static operator: string;
              static stringLiteral: string;
              static whiteSpace: string;
              static text: string;
              static punctuation: string;
              static className: string;
              static enumName: string;
              static interfaceName: string;
              static moduleName: string;
              static typeParameterName: string;
              static typeAlias: string;
          }
          interface DisplayPartsSymbolWriter extends SymbolWriter {
              displayParts(): SymbolDisplayPart[];
          }
          function displayPartsToString(displayParts: SymbolDisplayPart[]): string;
          function getDefaultCompilerOptions(): CompilerOptions;
          class OperationCanceledException {
          }
          class CancellationTokenObject {
              private cancellationToken;
              static None: CancellationTokenObject;
              constructor(cancellationToken: CancellationToken);
              isCancellationRequested(): boolean;
              throwIfCancellationRequested(): void;
          }
          function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile;
          var disableIncrementalParsing: boolean;
          function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile;
          function createDocumentRegistry(): DocumentRegistry;
          function preProcessFile(sourceText: string, readImportFiles?: boolean): PreProcessedFileInfo;
          function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService;
          function createClassifier(): Classifier;
          /**
            * Get the path of the default library file (lib.d.ts) as distributed with the typescript
            * node package.
            * The functionality is not supported if the ts module is consumed outside of a node module.
            */
          function getDefaultLibFilePath(options: CompilerOptions): string;
      }
      
    • typescriptServices_internal.d.ts
      /*! *****************************************************************************
      Copyright (c) Microsoft Corporation. All rights reserved. 
      Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      this file except in compliance with the License. You may obtain a copy of the
      License at http://www.apache.org/licenses/LICENSE-2.0  
       
      THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
      KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
      WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
      MERCHANTABLITY OR NON-INFRINGEMENT. 
       
      See the Apache Version 2.0 License for specific language governing permissions
      and limitations under the License.
      ***************************************************************************** */
      
      declare module ts {
          const enum Ternary {
              False = 0,
              Maybe = 1,
              True = -1,
          }
          const enum Comparison {
              LessThan = -1,
              EqualTo = 0,
              GreaterThan = 1,
          }
          interface StringSet extends Map<any> {
          }
          function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U;
          function contains<T>(array: T[], value: T): boolean;
          function indexOf<T>(array: T[], value: T): number;
          function countWhere<T>(array: T[], predicate: (x: T) => boolean): number;
          function filter<T>(array: T[], f: (x: T) => boolean): T[];
          function map<T, U>(array: T[], f: (x: T) => U): U[];
          function concatenate<T>(array1: T[], array2: T[]): T[];
          function deduplicate<T>(array: T[]): T[];
          function sum(array: any[], prop: string): number;
          function addRange<T>(to: T[], from: T[]): void;
          /**
           * Returns the last element of an array if non-empty, undefined otherwise.
           */
          function lastOrUndefined<T>(array: T[]): T;
          function binarySearch(array: number[], value: number): number;
          function hasProperty<T>(map: Map<T>, key: string): boolean;
          function getProperty<T>(map: Map<T>, key: string): T;
          function isEmpty<T>(map: Map<T>): boolean;
          function clone<T>(object: T): T;
          function extend<T>(first: Map<T>, second: Map<T>): Map<T>;
          function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U;
          function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U;
          function lookUp<T>(map: Map<T>, key: string): T;
          function mapToArray<T>(map: Map<T>): T[];
          function copyMap<T>(source: Map<T>, target: Map<T>): void;
          /**
           * Creates a map from the elements of an array.
           *
           * @param array the array of input elements.
           * @param makeKey a function that produces a key for a given element.
           *
           * This function makes no effort to avoid collisions; if any two elements produce
           * the same key with the given 'makeKey' function, then the element with the higher
           * index in the array will be the one associated with the produced key.
           */
          function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
          var localizedDiagnosticMessages: Map<string>;
          function getLocaleSpecificMessage(message: string): string;
          function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
          function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
          function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain;
          function concatenateDiagnosticMessageChains(headChain: DiagnosticMessageChain, tailChain: DiagnosticMessageChain): DiagnosticMessageChain;
          function compareValues<T>(a: T, b: T): Comparison;
          function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison;
          function sortAndDeduplicateDiagnostics(diagnostics: Diagnostic[]): Diagnostic[];
          function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[];
          function normalizeSlashes(path: string): string;
          function getRootLength(path: string): number;
          var directorySeparator: string;
          function normalizePath(path: string): string;
          function getDirectoryPath(path: string): string;
          function isUrl(path: string): boolean;
          function isRootedDiskPath(path: string): boolean;
          function getNormalizedPathComponents(path: string, currentDirectory: string): string[];
          function getNormalizedAbsolutePath(fileName: string, currentDirectory: string): string;
          function getNormalizedPathFromPathComponents(pathComponents: string[]): string;
          function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean): string;
          function getBaseFileName(path: string): string;
          function combinePaths(path1: string, path2: string): string;
          function fileExtensionIs(path: string, extension: string): boolean;
          function removeFileExtension(path: string): string;
          function getDefaultLibFileName(options: CompilerOptions): string;
          interface ObjectAllocator {
              getNodeConstructor(kind: SyntaxKind): new () => Node;
              getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
              getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
              getSignatureConstructor(): new (checker: TypeChecker) => Signature;
          }
          var objectAllocator: ObjectAllocator;
          const enum AssertionLevel {
              None = 0,
              Normal = 1,
              Aggressive = 2,
              VeryAggressive = 3,
          }
          module Debug {
              function shouldAssert(level: AssertionLevel): boolean;
              function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void;
              function fail(message?: string): void;
          }
      }
      declare module ts {
          interface System {
              args: string[];
              newLine: string;
              useCaseSensitiveFileNames: boolean;
              write(s: string): void;
              readFile(fileName: string, encoding?: string): string;
              writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void;
              watchFile?(fileName: string, callback: (fileName: string) => void): FileWatcher;
              resolvePath(path: string): string;
              fileExists(path: string): boolean;
              directoryExists(path: string): boolean;
              createDirectory(directoryName: string): void;
              getExecutingFilePath(): string;
              getCurrentDirectory(): string;
              readDirectory(path: string, extension?: string): string[];
              getMemoryUsage?(): number;
              exit(exitCode?: number): void;
          }
          interface FileWatcher {
              close(): void;
          }
          var sys: System;
      }
      declare module ts {
          interface ReferencePathMatchResult {
              fileReference?: FileReference;
              diagnosticMessage?: DiagnosticMessage;
              isNoDefaultLib?: boolean;
          }
          interface SynthesizedNode extends Node {
              leadingCommentRanges?: CommentRange[];
              trailingCommentRanges?: CommentRange[];
              startsOnNewLine: boolean;
          }
          function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration;
          interface StringSymbolWriter extends SymbolWriter {
              string(): string;
          }
          interface EmitHost extends ScriptReferenceHost {
              getSourceFiles(): SourceFile[];
              getCommonSourceDirectory(): string;
              getCanonicalFileName(fileName: string): string;
              getNewLine(): string;
              writeFile: WriteFileCallback;
          }
          function getSingleLineStringWriter(): StringSymbolWriter;
          function releaseStringWriter(writer: StringSymbolWriter): void;
          function getFullWidth(node: Node): number;
          function containsParseError(node: Node): boolean;
          function getSourceFileOfNode(node: Node): SourceFile;
          function getStartPositionOfLine(line: number, sourceFile: SourceFile): number;
          function nodePosToString(node: Node): string;
          function getStartPosOfNode(node: Node): number;
          function nodeIsMissing(node: Node): boolean;
          function nodeIsPresent(node: Node): boolean;
          function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number;
          function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string;
          function getTextOfNodeFromSourceText(sourceText: string, node: Node): string;
          function getTextOfNode(node: Node): string;
          function escapeIdentifier(identifier: string): string;
          function unescapeIdentifier(identifier: string): string;
          function makeIdentifierFromModuleName(moduleName: string): string;
          function isBlockOrCatchScoped(declaration: Declaration): boolean;
          function getEnclosingBlockScopeContainer(node: Node): Node;
          function isCatchClauseVariableDeclaration(declaration: Declaration): boolean;
          function declarationNameToString(name: DeclarationName): string;
          function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic;
          function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic;
          function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan;
          function isExternalModule(file: SourceFile): boolean;
          function isDeclarationFile(file: SourceFile): boolean;
          function isConstEnumDeclaration(node: Node): boolean;
          function getCombinedNodeFlags(node: Node): NodeFlags;
          function isConst(node: Node): boolean;
          function isLet(node: Node): boolean;
          function isPrologueDirective(node: Node): boolean;
          function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile): CommentRange[];
          function getJsDocComments(node: Node, sourceFileOfNode: SourceFile): CommentRange[];
          var fullTripleSlashReferencePathRegEx: RegExp;
          function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T;
          function isFunctionLike(node: Node): boolean;
          function isFunctionBlock(node: Node): boolean;
          function isObjectLiteralMethod(node: Node): boolean;
          function getContainingFunction(node: Node): FunctionLikeDeclaration;
          function getThisContainer(node: Node, includeArrowFunctions: boolean): Node;
          function getSuperContainer(node: Node, includeFunctions: boolean): Node;
          function getInvokedExpression(node: CallLikeExpression): Expression;
          function isExpression(node: Node): boolean;
          function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean): boolean;
          function isExternalModuleImportEqualsDeclaration(node: Node): boolean;
          function getExternalModuleImportEqualsDeclarationExpression(node: Node): Expression;
          function isInternalModuleImportEqualsDeclaration(node: Node): boolean;
          function getExternalModuleName(node: Node): Expression;
          function hasDotDotDotToken(node: Node): boolean;
          function hasQuestionToken(node: Node): boolean;
          function hasRestParameters(s: SignatureDeclaration): boolean;
          function isLiteralKind(kind: SyntaxKind): boolean;
          function isTextualLiteralKind(kind: SyntaxKind): boolean;
          function isTemplateLiteralKind(kind: SyntaxKind): boolean;
          function isBindingPattern(node: Node): boolean;
          function isInAmbientContext(node: Node): boolean;
          function isDeclaration(node: Node): boolean;
          function isStatement(n: Node): boolean;
          function isDeclarationName(name: Node): boolean;
          function getClassBaseTypeNode(node: ClassDeclaration): TypeReferenceNode;
          function getClassImplementedTypeNodes(node: ClassDeclaration): NodeArray<TypeReferenceNode>;
          function getInterfaceBaseTypeNodes(node: InterfaceDeclaration): NodeArray<TypeReferenceNode>;
          function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind): HeritageClause;
          function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference): SourceFile;
          function getAncestor(node: Node, kind: SyntaxKind): Node;
          function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult;
          function isKeyword(token: SyntaxKind): boolean;
          function isTrivia(token: SyntaxKind): boolean;
          /**
           * A declaration has a dynamic name if both of the following are true:
           *   1. The declaration has a computed property name
           *   2. The computed name is *not* expressed as Symbol.<name>, where name
           *      is a property of the Symbol constructor that denotes a built in
           *      Symbol.
           */
          function hasDynamicName(declaration: Declaration): boolean;
          /**
           * Checks if the expression is of the form:
           *    Symbol.name
           * where Symbol is literally the word "Symbol", and name is any identifierName
           */
          function isWellKnownSymbolSyntactically(node: Expression): boolean;
          function getPropertyNameForPropertyNameNode(name: DeclarationName): string;
          function getPropertyNameForKnownSymbolName(symbolName: string): string;
          /**
           * Includes the word "Symbol" with unicode escapes
           */
          function isESSymbolIdentifier(node: Node): boolean;
          function isModifier(token: SyntaxKind): boolean;
          function textSpanEnd(span: TextSpan): number;
          function textSpanIsEmpty(span: TextSpan): boolean;
          function textSpanContainsPosition(span: TextSpan, position: number): boolean;
          function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean;
          function textSpanOverlapsWith(span: TextSpan, other: TextSpan): boolean;
          function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan;
          function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan): boolean;
          function textSpanIntersectsWith(span: TextSpan, start: number, length: number): boolean;
          function textSpanIntersectsWithPosition(span: TextSpan, position: number): boolean;
          function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan;
          function createTextSpan(start: number, length: number): TextSpan;
          function createTextSpanFromBounds(start: number, end: number): TextSpan;
          function textChangeRangeNewSpan(range: TextChangeRange): TextSpan;
          function textChangeRangeIsUnchanged(range: TextChangeRange): boolean;
          function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange;
          var unchangedTextChangeRange: TextChangeRange;
          /**
           * Called to merge all the changes that occurred across several versions of a script snapshot
           * into a single change.  i.e. if a user keeps making successive edits to a script we will
           * have a text change from V1 to V2, V2 to V3, ..., Vn.
           *
           * This function will then merge those changes into a single change range valid between V1 and
           * Vn.
           */
          function collapseTextChangeRangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange;
          function nodeStartsNewLexicalEnvironment(n: Node): boolean;
          function nodeIsSynthesized(node: Node): boolean;
          function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node;
          function generateUniqueName(baseName: string, isExistingName: (name: string) => boolean): string;
          /**
           * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
           * but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine)
           * Note that this doesn't actually wrap the input in double quotes.
           */
          function escapeString(s: string): string;
          function escapeNonAsciiCharacters(s: string): string;
      }
      declare module ts {
          var optionDeclarations: CommandLineOption[];
          function parseCommandLine(commandLine: string[]): ParsedCommandLine;
          function readConfigFile(fileName: string): any;
          function parseConfigFile(json: any, basePath?: string): ParsedCommandLine;
      }
      declare module ts {
          interface ListItemInfo {
              listItemIndex: number;
              list: Node;
          }
          function getEndLinePosition(line: number, sourceFile: SourceFile): number;
          function getLineStartPositionForPosition(position: number, sourceFile: SourceFile): number;
          function rangeContainsRange(r1: TextRange, r2: TextRange): boolean;
          function startEndContainsRange(start: number, end: number, range: TextRange): boolean;
          function rangeContainsStartEnd(range: TextRange, start: number, end: number): boolean;
          function rangeOverlapsWithStartEnd(r1: TextRange, start: number, end: number): boolean;
          function startEndOverlapsWithStartEnd(start1: number, end1: number, start2: number, end2: number): boolean;
          function findListItemInfo(node: Node): ListItemInfo;
          function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node;
          function findContainingList(node: Node): Node;
          function getTouchingWord(sourceFile: SourceFile, position: number): Node;
          function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node;
          /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
          function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node;
          /** Returns a token if position is in [start-of-leading-trivia, end) */
          function getTokenAtPosition(sourceFile: SourceFile, position: number): Node;
          /**
            * The token on the left of the position is the token that strictly includes the position
            * or sits to the left of the cursor if it is on a boundary. For example
            *
            *   fo|o               -> will return foo
            *   foo <comment> |bar -> will return foo
            *
            */
          function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node;
          function findNextToken(previousToken: Node, parent: Node): Node;
          function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node): Node;
          function getNodeModifiers(node: Node): string;
          function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node>;
          function isToken(n: Node): boolean;
          function isComment(kind: SyntaxKind): boolean;
          function isPunctuation(kind: SyntaxKind): boolean;
          function isInsideTemplateLiteral(node: LiteralExpression, position: number): boolean;
          function compareDataObjects(dst: any, src: any): boolean;
      }
      declare module ts {
          function isFirstDeclarationOfSymbolParameter(symbol: Symbol): boolean;
          function symbolPart(text: string, symbol: Symbol): SymbolDisplayPart;
          function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart;
          function spacePart(): SymbolDisplayPart;
          function keywordPart(kind: SyntaxKind): SymbolDisplayPart;
          function punctuationPart(kind: SyntaxKind): SymbolDisplayPart;
          function operatorPart(kind: SyntaxKind): SymbolDisplayPart;
          function textPart(text: string): SymbolDisplayPart;
          function lineBreakPart(): SymbolDisplayPart;
          function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[];
          function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[];
          function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[];
          function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[];
      }
      
    • websql.d.ts
      declare function openDatabase(
        name: string,
        version: any,
        displayName: string,
        size: number,
        upgrade?: DatabaseCallback): Database;
      
      interface DatabaseCallback {
        (database: Database): void;
      }
      
      interface Database {
        transaction(
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      
        readTransaction(
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      
        version: string;
      
        changeVersion(
          oldVersion: string,
          newVersion: string,
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      }
      
      interface SQLTransaction {
        executeSql(
          sqlStatement: string,
          arguments?: any[],
          callback?: (transaction: SQLTransaction, result: SQLResultSet) => void,
          errorCallback?: (transaction: SQLTransaction, error: SQLError) => void): void;
      }
      
      interface SQLError {
        /**
         * UNKNOWN_ERR = 0;
         * DATABASE_ERR = 1;
         * VERSION_ERR = 2;
         * TOO_LARGE_ERR = 3;
         * QUOTA_ERR = 4;
         * SYNTAX_ERR = 5;
         * CONSTRAINT_ERR = 6;
        * TIMEOUT_ERR = 7;
         */
        code: number;
        message: string
      }
      
      interface SQLResultSet {
        insertId: number;
        rowsAffected: number;
        rows: SQLResultSetRowList;
      }
      
      interface SQLResultSetRowList {
        length: number;
        item(index: number): any;
      }
    • zip.d.ts
      declare module zip {
      
        export var useWebWorkers: boolean;
      
        export function createReader(reader: Reader, callback: (reader: ZipReader) => void, onerror?);
        export function createWriter(writer: Writer, callback: (writer: ZipWriter) => void, onerror?);
      
        export interface Reader {
        }
      
        export interface Writer {
        }
      
        export interface ZipReader {
          getEntries(callback: (entries: Entry[]) => void);
          close(callback: () => void);
        }
      
        export interface ZipWriter {
          add(
            name: string,
            reader: Reader,
            onend,
            onprogress?: (index: number, max: number) => void,
            options?: { directory?: boolean; level?: number; comment?: string; lastModDate?: Date; version?: number; });
      
          close(callback);
        }
      
        export interface Entry {
          filename: string;
          directory: boolean;
          compressedSize: number;
          uncompressedSize: number;
          lastModDate: number;
          lastModDateRaw: number;
          comment: string;
          crc32: number;
      
          getData(writer: Writer, onend?, onprogress?: (index: number, maxValue: number) => void, checkCrc32?: boolean);
        }
      
        export class BlobWriter implements Writer {
          constructor(contentType: string);
        }
          
        export class TextWriter implements Writer {
        }
      
        export class TextReader implements Reader {
          constructor(text: string);
        }
      
        export class BlobReader implements Reader {
          constructor(arg: any);
        }
      }
  • errors.js
    var _errorCache = [];
    _errorCache.byText = {};
    
    window.onerror = function(errObj, file, line, ch, err) {
    
      var txt = err ? err.stack || err.message || err + '' : errObj;
    
      var firstTrigger = _errorCache.length === 0;
      if (_errorCache.byText[txt]) {
        _errorCache.byText[txt]++;
      }
      else {
        _errorCache.byText[txt]=1;
        _errorCache.push(txt);
      }
    
      if (firstTrigger)
        setTimeout(function() {
          var errorText = _errorCache.map(function(txt){return _errorCache.byText[txt]+' - '+txt}).join('\n');
          _errorCache = [];
          _errorCache.byText = {};
          alert(errorText);
        }, 100);
    };
    
  • functions.ts
    module portabled {
    
      /** Stoppable timer with methods specifically targeting debouncing. */
      export class Timer {
    
        private _timeout = 0;
        private _maxTimeout = 0;
        private _tickClosure = () => this._tick();
    
        constructor() {
        }
    
        interval = 300;
        maxInterval = 1000;
    
        ontick: () => void = null;
    
        reset() {
          if (this._timeout)
            clearTimeout(this._timeout);
    
          if (!this._maxTimeout && this.maxInterval)
            this._maxTimeout = setTimeout(this._tickClosure, this.maxInterval);
    
          if (this.interval)
            this._timeout = setTimeout(this._tickClosure, this.interval);
        }
    
        stop() {
          if (this._timeout)
            clearTimeout(this._timeout);
          if (this._maxTimeout)
            clearTimeout(this._maxTimeout);
          this._timeout = 0;
          this._maxTimeout = 0;
        }
    
        endWaiting() {
          if (this.isWaiting())
            this._tick();
        }
    
        isWaiting() {
          return this._timeout || this._maxTimeout ? true : false;
        }
    
        private _tick() {
          this.stop();
          if (this.ontick) {
            var t = this.ontick;
            t();
          }
        }
    
      }
    
      export function asyncForEach<T, TResult>(
        array: T[],
        handleElement: (element: T, index: number, callback: (error: Error, res: TResult) => void) => void,
        callback: (error: Error, res: TResult[]) => void) {
    
        if (!array || !array.length) {
          callback(null, []);
          return;
        }
    
        var res: TResult[] = [];
        var stop = false;
        var completeCount = 0;
        forEach(array, (element, index) => {
          if (stop) return;
          handleElement(element[index], index, (error, resElement) => {
            if (stop) return;
            if (error) {
              stop = true;
              callback(error, null);
              return;
            }
            res[index] = resElement;
            completeCount++;
            if (completeCount === array.length) {
              stop = true;
              callback(null, res);
            }
          });
        });
      }
    
      export function forEach<T>(array: T[], callback: (x: T, index: number) => void) {
        if (array.forEach) {
          array.forEach(callback);
        }
        else {
          for (var i = 0; i < array.length; i++) {
            callback(array[i], i);
          }
        }
      }
    
      export function find<T, R>(array: T[], predicate: (x: T, index: number) => R): R {
        var result = null;
        for (var i = 0; i < array.length; i++) {
          var x = array[i];
          var p = predicate(x, i);
          if (p) return p;
        }
      }
    
      /**
     * Escape unsafe character sequences like a closing script tag.
     */
      export function encodeForInnerHTML(content: string): string {
        // matching script closing tag with *one* or more consequtive slashes
        return content.replace(/<\/+script/g, (match) => {
          return '</' + match.slice(1); // skip angle bracket, inject bracket and extra slash
        });
      }
    
      /**
       * Unescape character sequences wrapped with encodeForInnerHTML for safety.
       */
      export function decodeFromInnerHTML(innerHTML: string): string {
        // matching script closing tag with *t*wo or more consequtive slashes
        return innerHTML.replace(/<\/\/+script/g, (match) => {
          return '<' + match.slice(2); // skip angle bracket and one slash, inject bracket
        });
      }
    
      export function encodeForAttributeName(value: string): string {
        var codes: number[] = [];
        var passableOnly = true;
    
        for (var i = 0; i < value.length; i++) {
          var c = value.charAt(i);
          var cc = value.charCodeAt(i);
          codes.push(cc);
          if (passableOnly)
            passableOnly = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z' || c === '_' || c === '-');
        }
    
        if (passableOnly)
          return 's-' + value;
        else
          return 'n-' + codes.join('-');
      }
    
      export function decodeFromAttributeName(attributeNamePart: string): string {
        if (attributeNamePart.slice(0, 2) === 's-')
          return attributeNamePart.slice(2);
    
        var codes = attributeNamePart.slice(2).split('-');
        var result: string[] = [];
        for (var i = 0; i < codes.length; i++) {
          try {
            result[i] = String.fromCharCode(parseInt(codes[i]));
          }
          catch (error) {
            console.log('Parsing attribute name error: ' + attributeNamePart + ' has non-numeric chunk ' + i + ' (' + codes[i] + ').');
            return null;
          }
        }
        return result.join('');
      }
    
      export function startsWith(str: string, prefix: string) {
        if (!str) return !prefix;
        if (!prefix) return false;
        if (str.length < prefix.length) return false;
        if (str.charCodeAt(0) !== prefix.charCodeAt(0)) return false;
        if (str.slice(0, prefix.length) !== prefix) return false;
        else return true;
      }
    
      export function dateNow(): number {
        if (Date.now)
          return Date.now();
        else
          return new Date().valueOf();
      }
    
      export var objectKeys = (obj: any): string[]=> {
        if (typeof Object.keys === 'function')
          objectKeys = Object.keys;
        else
          objectKeys = (obj: any): string[]=> {
            var result: string[] = [];
            for (var k in obj) if (obj.hasOwnProperty(k)) {
              result.push(k);
            }
            return result;
          };
    
        return objectKeys(obj);
      };
    
      export function addEventListener(element: any, type: string, listener: (event: Event) => void) {
        if (element.addEventListener) {
          element.addEventListener(type, listener, true);
        }
        else {
          var ontype = 'on' + type;
    
          if (element.attachEvent) {
            element.attachEvent('on' + type, listener);
          }
          else if (ontype in element) {
            element[ontype] = listener;
          }
        }
      }
    
      export function removeEventListener(element: any, type: string, listener: (event: Event) => void) {
        if (element.addEventListener) {
          element.removeEventListener(type, listener, true);
        }
        else {
          var ontype = 'on' + type;
    
          if (element.detachEvent) {
            element.detachEvent('on' + type, listener);
          }
          else if (ontype in element) {
            element[ontype] = null;
          }
        }
      }
    
      export function setTextContent(element: HTMLElement, textContent: string) {
        if (!_useTextContent)
          _useTextContent = detectTextContent(element);
        if (_useTextContent === 1)
          element.textContent = textContent;
        else
          element.innerText = textContent;
      }
    
      var _useTextContent = 0;
      function detectTextContent(element: HTMLElement) {
        if ('textContent' in element)
          return 1;
        else
          return 2;
      }
    
      export function element(tag: string, style?: any, parent?: HTMLElement): HTMLElement {
        var el = document.createElement(tag);
        if (style) {
          if (typeof style === 'string') {
            setTextContent(el, style);
          }
          else if (!parent && typeof style.scrollIntoView === 'function') {
            parent = style;
          }
          else {
            for (var k in style) if (style.hasOwnProperty(k)) {
              if (k === 'text')
                setTextContent(el, style.text);
              else
                el.style[k] = style[k];
            }
          }
        }
    
        if (parent)
          parent.appendChild(el);
    
        return el;
      }
      
      /**
       * JS Implementation of MurmurHash2
       * 
       * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
       * @see http://github.com/garycourt/murmurhash-js
       * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
       * @see http://sites.google.com/site/murmurhash/
       * 
       * @param {string} str ASCII only
       * @param {number} seed Positive integer only
       * @return {number} 32-bit positive integer hash
       */
      export function murmurhash2_32_gc(str, seed) {
        var
          l = str.length,
          h = seed ^ l,
          i = 0,
          k;
    
        while (l >= 4) {
          k =
          ((str.charCodeAt(i) & 0xff)) |
          ((str.charCodeAt(++i) & 0xff) << 8) |
          ((str.charCodeAt(++i) & 0xff) << 16) |
          ((str.charCodeAt(++i) & 0xff) << 24);
    
          k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
          k ^= k >>> 24;
          k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
    
          h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
    
          l -= 4;
          ++i;
        }
    
        switch (l) {
          case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
          case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
          case 1: h ^= (str.charCodeAt(i) & 0xff);
            h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
        }
    
        h ^= h >>> 13;
        h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
        h ^= h >>> 15;
    
        return h >>> 0;
      }
    }
  • index.html
    <!doctype html><html><head>
    <meta charset="utf-8">
    <title>portabled - [portabled v0.6w]</title>
    
    <style>
      <%/*uglifyJS.skip = true*/%>
      <%=uglifyCSS(
    
      	// CodeMirror CSS
      	'imports/codemirror/lib/codemirror.css',
      	'imports/codemirror/addon/hint/show-hint.css',
      	'imports/codemirror/addon/lint/lint.css',
      	'imports/codemirror/addon/dialog/dialog.css',
      	'imports/codemirror/addon/merge/merge.css',
      	'imports/codemirror/addon/fold/foldgutter.css',
    
        // portabled CSS
      	'app/body.css',
      	'app/flyout.css',
      	'app/flyout-branding.css',
      	'app/tree-and-bar.css',
      	'app/status.css',
    
      	'files/FileTree.css',
      	'docs/types/text/CodeMirror-ext.css',
      	'app/moreDialog/style.css',
      	'docs/types/text/scrollerView/style.css',
      
      	'docs/types/text/ts/style.css',
      
      	'app/loading.css')
    	%>
    </style>
    
    <% /* embedFile('imports/codemirror/addon/tern/tern.css') */ %>
    
    
    </head>
    <body
        data-bind="event: {keydown:keydown}">
    
    
    <!-- ES5 shim/sham, JSON3 -->
    <script data-legit=portabled>
      <%=embedFile('imports/es5-shim/es5-shim.min.js', 'imports/es5-shim/es5-sham.min.js', 'imports/json3/json3.min.js')%>
    </script>
    
    
    <!-- Error handling script -->
    <script data-legit=portabled><%=embedFile('errors.js')%></script>
    
    <!-- Main portabled JS code -->
    <script data-legit=portabled><%=function(){ var ts = typescriptBuild(); var tsstr = ts(); var ug = uglifyJS(tsstr); return typeof ug === 'function' ? ug() : ug; }%></script>
    
    <div id=portabled-loading-host>
      <div id=portabled-loading-title>
        Booting...
      </div>
      <div id=portabled-loading-progress>
      </div>
    </div>
    
    <script data-legit=portabled>
    
      // Detect JS syntax error in compiled script (resulting in no top-level module),
      // report early to avoid complicated debugging when things are trivially wrong.
    
      if (typeof portabled === 'undefined') {
        alert('Syntax error in the compiled script.');
      }
      else {
      	try { portabled.app.loading('Page layout...'); } catch (err) { alert(err+' '+err.stack); }
      }
    
    </script>
    
    <div class=portabled-flyout-scroller
       data-bind="load: flyoutScroller = $element">
      <div class=portabled-flyout-scroller-bg>
    
        <div class=portabled-main-content
           data-bind="loadRaw: docHostRegions.content = $element"></div>
    
        <div class=portabled-flyout>
    
          <div class=portabled-thick-bar-host>
            <button class=portabled-more-button data-bind="click: moreClick"> ... </button>
            <div class=portabled-thick-bar-bg>
              <div class=portabled-thick-bar
                   data-bind="event: { mousedown: thickbarMouseDown }, loadRaw: docHostRegions.scroller = $element">
              </div>
            </div>
          </div>
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
        try { portabled.app.loading('Files...'); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
          <div class=portabled-file-tree
             timestamp="<%=new Date().getTime()%>"
             data-bind="loadRaw: fileTreeHost = $element">
    
            <ul>
    
              <%=embedTree()%>
              
            </ul>
          </div>
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
      	try { portabled.app.loading('Controls...'); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
          <div class=portabled-extra-content>
            
            <div class=portabled-branding-area
                 data-bind="loadRaw: brandingArea=$element "></div>
    
    
           <div class=portabled-scrollable-bottom>
    
              <div class=portabled-links>
                <button data-bind="click: deleteClick" style="min-width: 7em; margin-bottom: 0.3em;"> Delete </button> <br>
                <button data-bind="click: buildClick" style="min-width: 7em;"> Build </button> <br>
                <br>
                <a href=# data-bind="click: exportAllHTML"> Save whole page </a><br>
                <a href=# data-bind="click: commitToGitHub"> Commit to GitHub </a><br>
                <a href=# data-bind="click: exportAllZIP"> Export to ZIP </a><br>
                <a href=# data-bind="click: exportCurrentFile"> Save current file </a><br>
                <br>
                <a href=# data-bind="click: importText"> Add file </a><br>
                <a href=# data-bind="click: importBase64"> Add binary (base64) </a><br>
                <a href=# data-bind="click: importZIP"> Import files from ZIP </a><br>
                <a href=# data-bind="click: importPortabledHTML"> Import files from portabled </a><br>
    
              </div>
    
              <div class=portabled-credits>
    
                portabled v0.5a by Oleg Mihailik. <br>
                <br>
    
                <div style="font-size: 90%;">
                  Used Open Source libraries:<br>
                  <a href="https://github.com/Microsoft/TypeScript">TypeScript</a> (Microsoft, with Apache 2.0 license) <br>
                  <a href="https://github.com/codemirror/CodeMirror">CodeMirror</a> (Marijn Haverbeke, with MIT license) <br>
                  <a href="https://github.com/knockout/knockout">Knockout.js</a> (Ryan Niemeyer, with MIT license) <br>
                  <a href="https://github.com/gildas-lormeau/zip.js">Zip.js</a> (Gildas Lormeau, with BSD license) <br>
                  <a href="https://github.com/chjj/marked">Marked</a> (Christopher Jeffrey, with MIT license) <br>
                  <a href="https://github.com/es-shims/es5-shim">ES5-shims<a/> (with MIT license)<br>
                  <a href="https://github.com/michael/github">GitHub API wrapper</a> (Michael Aufreiter with BSD2 license)<br>
                  <a href="https://github.com/garycourt/murmurhash-js">JS Murmur hasher</a> (Gary Court with MIT license)<br>
                  <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a> (Google with Apache 2.0 license)<br>
                  <a href="https://github.com/mishoo/UglifyJS2">UglifyJS2</a> (Mihai Bazon with BSD license)<br>
                  <a href="https://github.com/mishoo/UglifyCSS">UglifyCSS</a> (Franck Marcia with MIT license)<br>
                  <a href="https://github.com/bestiejs/json3">JSON3</a> (Kit Cambridge with MIT license)<br>
                  - main contributors mentioned where applicable.
                </div>
    
              </div>
    
            </div>
    
          </div>
    
          
          
        </div>
    
      </div>
    </div>
    
    <div class=portabled-status-bar
       data-bind="loadRaw: docHostRegions.status = $element">
    </div>
    
    <script data-legit=portabled>try { portabled.app.loading('Libraries...'); } catch (err) { alert(err+' '+err.stack); }</script>
    
    
    <% /* embedFile(
       'imports/acorn/acorn.js',
       'imports/acorn/acorn_loose.js',
       'imports/acorn/walk.js',
       'imports/tern/signal.js',
       'imports/tern/tern.js',
       'imports/tern/def.js'
       'imports/tern/comment.js',
       'imports/tern/infer.js',
       'imports/tern/doc_comment.js') */%>
    
    <!-- Google diff/merge algorithm (used for a CodeMirror addon needed for the neat file import dialog) -->
    <script data-legit=portabled><%=embedFile('imports/google-diff-match-patch/diff_match_patch.js')%></script>
    
    <!-- CodeMirror -->
    <script data-legit=portabled>
      <%=uglifyJS([
      	'imports/codemirror/lib/codemirror.js',
      	'imports/codemirror/addon/dialog/dialog.js',
      	'imports/codemirror/addon/search/search.js',
      	'imports/codemirror/addon/search/searchcursor.js',
      	'imports/codemirror/addon/hint/show-hint.js',
      	'imports/codemirror/addon/lint/lint.js',
      	'imports/codemirror/mode/javascript/javascript.js',
      	'imports/codemirror/addon/tern/tern.js',
      	'imports/codemirror/addon/hint/javascript-hint.js',
      	'imports/codemirror/mode/css/css.js',
      	'imports/codemirror/addon/hint/css-hint.js',
      	'imports/codemirror/mode/sass/sass.js',
      	'imports/codemirror/mode/xml/xml.js',
      	'imports/codemirror/addon/hint/xml-hint.js',
      	'imports/codemirror/mode/htmlmixed/htmlmixed.js',
      	'imports/codemirror/mode/htmlembedded/htmlembedded.js',
      	'imports/codemirror/addon/hint/html-hint.js',
      	'imports/codemirror/mode/markdown/markdown.js',
      	'imports/codemirror/addon/edit/matchbrackets.js',
      	'imports/codemirror/addon/selection/active-line.js',
      	'imports/codemirror/addon/edit/trailingspace.js',
      	'imports/codemirror/addon/fold/foldcode.js',
      	'imports/codemirror/addon/fold/foldgutter.js',
      	'imports/codemirror/addon/fold/brace-fold.js',
      	'imports/codemirror/addon/fold/comment-fold.js',
      	'imports/codemirror/addon/fold/markdown-fold.js',
      	'imports/codemirror/addon/fold/xml-fold.js',
      	'imports/codemirror/addon/merge/merge.js'])%></script>
    
    <!-- Knockout -->
    <script data-legit=portabled>
      <%=uglifyJS(['imports/knockout/knockout-3.2.0.js'])%>
    </script>
    
    <!-- Zip.js -->
    <script data-legit=portabled>
      <%=uglifyJS([
        'imports/zip.js/zip.js',
        'imports/zip.js/deflate.js',
        'imports/zip.js/inflate.js'])%>
    </script>
    
    <!-- Marked -->
    <script data-legit=portabled>
      <%=uglifyJS(['imports/marked/marked.js'])%>
    </script>
    
    <!-- Uglify2 -->
    <script data-legit=portabled>
    var Uglify2;
    (function(Uglify2) {
      <%=uglifyJS([
        'imports/uglify2/utils.js',
        'imports/uglify2/ast.js',
        'imports/uglify2/parse.js',
        'imports/uglify2/transform.js',
        'imports/uglify2/scope.js',
        'imports/uglify2/output.js',
        'imports/uglify2/compress.js'
      ])%>
      Uglify2.Compressor = Compressor;
      Uglify2.parse = parse
      
    })(Uglify2 || (Uglify2={}))
    </script>
    
    <!-- UglifyCSS -->
    <script data-legit=portabled>
    var UglifyCSS;
    (function(UglifyCSS) {
      function require() { return {}; }
      var module = { exports: { }};
      <%=embedFile('imports/uglifyCSS/uglifycss-lib.js')%>
      for (var k in module.exports) {
        if (module.exports.hasOwnProperty(k))
        	UglifyCSS[k] = module.exports[k];
      }
    })(UglifyCSS || (UglifyCSS={}))
    </script>
        
    
    
    <script type=text/html id=MoreDialogView data-legit=portabled><%=embedFile('app/moreDialog/layout.html')%></script>
    <script type=text/html id=ScrollerView data-legit=portabled><%=embedFile('docs/types/text/scrollerView/ScrollerView.html')%></script>
    
    <script data-legit=portabled><%=uglifyJS('imports/typescript/typescriptServices.js')%></script>
    <script data-legit=portabled id=core.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/core.d.ts.text')%></script>
    <script data-legit=portabled id=dom.generated.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/dom.generated.d.ts.text')%></script>
    <script data-legit=portabled id=extensions.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/extensions.d.ts.text')%></script>
    
    
    <!--
    <script data-legit=portabled type="text/javascript" src="https://getfirebug.com/firebug-lite.js">
    {
        overrideConsole: true,
        startInNewWindow: false,
        startOpened: true
    }
    </script>
    -->
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
      	try { portabled.app.start(); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
    <div id=portabled-last-element></div>
    
    </body>
    </html>
    
  • readme.md
    # portabled v0.6w
    
    Self-editing filesystem embedded in a single HTML file.
    
    The idea, all of the painstaking implementation and the vision by [Oleg Mihailik](mailto:mihailik@gmail.com).
    See the credits section for the used libraries and respective licences.
    
    ### Outstanding tasks:
     * Unifying of all import/export into 'moreDialog'.
     * Download/upload for GitHub, GDrive, Dropbox etc.
     * Extra power in Chrome app, node-webkit, HTMLA-ie7: I/O to the actual filesystem.
     * Delete folder.
     * Rename file/folder.
     * Saving current position in documents.
     * TypeScript extra features: navigate to, search integration, tooltips.
     * Sub-domains for TypeScript/JavaScript completion/build contexts.
     * Doc handlers in plugins, plugin API and isolation (using iframes with their own 'global' and 'require').
     * node.js emulation for plugins and dependencies, allowing non-doc plugins.
     * Highlight of **changes** in files.
     * Styles and colours (planning for pale seaside 'Whitstable' blue, maybe black theme too).
     * Scrollbar to use syntax-highlighted document lines.
     * Toast popup/fadeout messages for key events: opening, building, import-export completion.
     * Add whole raw TypeScript repository sample.
  • try.js
    var __resizeTimer = 0;
    if (false)
    window.onresize = function() {
      if (!__resizeTimer)
        clearTimeout(__resizeTimer);
      __resizeTimer = setTimeout(function(){
        alert('Resize!')
      }, 700);
    }
    
    var doss = document.createElement('pre');
    doss.textContent = '<pre>abcdef    1\n2      2\n\n </pre>';
    alert(doss.innerHTML)
    alert(doss.textContent)

portabled v0.6w

Self-editing filesystem embedded in a single HTML file.

The idea, all of the painstaking implementation and the vision by Oleg Mihailik. See the credits section for the used libraries and respective licences.

Outstanding tasks:

  • Unifying of all import/export into 'moreDialog'.
  • Download/upload for GitHub, GDrive, Dropbox etc.
  • Extra power in Chrome app, node-webkit, HTMLA-ie7: I/O to the actual filesystem.
  • Delete folder.
  • Rename file/folder.
  • Saving current position in documents.
  • TypeScript extra features: navigate to, search integration, tooltips.
  • Sub-domains for TypeScript/JavaScript completion/build contexts.
  • Doc handlers in plugins, plugin API and isolation (using iframes with their own 'global' and 'require').
  • node.js emulation for plugins and dependencies, allowing non-doc plugins.
  • Highlight of changes in files.
  • Styles and colours (planning for pale seaside 'Whitstable' blue, maybe black theme too).
  • Scrollbar to use syntax-highlighted document lines.
  • Toast popup/fadeout messages for key events: opening, building, import-export completion.
  • Add whole raw TypeScript repository sample.
portabled v0.5a by Oleg Mihailik.

Used Open Source libraries:
TypeScript (Microsoft, with Apache 2.0 license)
CodeMirror (Marijn Haverbeke, with MIT license)
Knockout.js (Ryan Niemeyer, with MIT license)
Zip.js (Gildas Lormeau, with BSD license)
Marked (Christopher Jeffrey, with MIT license)
ES5-shims (with MIT license)
GitHub API wrapper (Michael Aufreiter with BSD2 license)
JS Murmur hasher (Gary Court with MIT license)
google-diff-match-patch (Google with Apache 2.0 license)
UglifyJS2 (Mihai Bazon with BSD license)
UglifyCSS (Franck Marcia with MIT license)
JSON3 (Kit Cambridge with MIT license)
- main contributors mentioned where applicable.
/readme.md